* src/vm/jit/alpha/patcher.c (patcher_wrapper): Patch back the
[cacao.git] / src / vm / jit / alpha / patcher.c
1 /* src/vm/jit/alpha/patcher.c - Alpha code patching functions
2
3    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    Contact: cacao@cacaojvm.org
26
27    Authors: Christian Thalinger
28
29    Changes:
30
31    $Id: patcher.c 5160 2006-07-19 09:13:34Z twisti $
32
33 */
34
35
36 #include "config.h"
37
38 #include <assert.h>
39
40 #include "vm/types.h"
41
42 #include "mm/memory.h"
43 #include "native/native.h"
44 #include "vm/builtin.h"
45 #include "vm/class.h"
46 #include "vm/exceptions.h"
47 #include "vm/field.h"
48 #include "vm/initialize.h"
49 #include "vm/options.h"
50 #include "vm/references.h"
51 #include "vm/resolve.h"
52 #include "vm/jit/asmpart.h"
53 #include "vm/jit/patcher.h"
54 #include "vm/jit/methodheader.h"
55
56
57 /* patcher_wrapper *************************************************************
58
59    Wrapper for all patchers.  It also creates the stackframe info
60    structure.
61
62    If the return value of the patcher function is false, it gets the
63    exception object, clears the exception pointer and returns the
64    exception.
65
66 *******************************************************************************/
67
68 java_objectheader *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
69 {
70         stackframeinfo     sfi;
71         u1                *xpc;
72         java_objectheader *o;
73         u4                 mcode;
74         functionptr        f;
75         bool               result;
76         java_objectheader *e;
77
78         /* define the patcher function */
79
80         bool (*patcher_function)(u1 *);
81
82         assert(pv != NULL);
83
84         /* get stuff from the stack */
85
86         xpc   = (u1 *)                *((ptrint *) (sp + 5 * 8));
87         o     = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
88         f     = (functionptr)         *((ptrint *) (sp + 0 * 8));
89
90         /* calculate and set the new return address */
91
92         xpc = xpc - 1 * 4;
93
94         *((ptrint *) (sp + 5 * 8)) = (ptrint) xpc;
95
96         /* store PV into the patcher function position */
97
98         *((ptrint *) (sp + 0 * 8)) = (ptrint) pv;
99
100         /* cast the passed function to a patcher function */
101
102         patcher_function = (bool (*)(u1 *)) (ptrint) f;
103
104         /* enter a monitor on the patching position */
105
106         PATCHER_MONITORENTER;
107
108         /* create the stackframeinfo */
109
110         stacktrace_create_extern_stackframeinfo(&sfi, pv, sp + 6 * 8, ra, xpc);
111
112         /* call the proper patcher function */
113
114         result = (patcher_function)(sp);
115
116         /* remove the stackframeinfo */
117
118         stacktrace_remove_stackframeinfo(&sfi);
119
120         /* check for an error, get the exception and return it */
121
122         if (result == false) {
123                 e = exceptions_get_and_clear_exception();
124
125                 PATCHER_MONITOREXIT;
126
127                 return e;
128         }
129
130         /* patch back original code */
131
132         mcode = *((u4 *) (sp + 3 * 8));
133
134         *((u4 *) xpc) = mcode;
135
136         /* synchronize instruction cache */
137
138         md_icacheflush(NULL, 0);
139
140         PATCHER_MARK_PATCHED_MONITOREXIT;
141
142         return NULL;
143 }
144
145
146 /* patcher_get_putstatic *******************************************************
147
148    Machine code:
149
150    <patched call position>
151    a73bff98    ldq     t11,-104(pv)
152    a2590000    ldl     a2,0(t11)
153
154 *******************************************************************************/
155
156 bool patcher_get_putstatic(u1 *sp)
157 {
158         unresolved_field *uf;
159         s4                disp;
160         u1               *pv;
161         fieldinfo        *fi;
162
163         /* get stuff from the stack */
164
165         uf    = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
166         disp  =                      *((s4 *)     (sp + 1 * 8));
167         pv    = (u1 *)               *((ptrint *) (sp + 0 * 8));
168
169         /* get the fieldinfo */
170
171         if (!(fi = resolve_field_eager(uf)))
172                 return false;
173
174         /* check if the field's class is initialized */
175
176         if (!(fi->class->state & CLASS_INITIALIZED))
177                 if (!initialize_class(fi->class))
178                         return false;
179
180         /* patch the field value's address */
181
182         *((ptrint *) (pv + disp)) = (ptrint) &(fi->value);
183
184         return true;
185 }
186
187
188 /* patcher_get_putfield ********************************************************
189
190    Machine code:
191
192    <patched call position>
193    a2af0020    ldl     a5,32(s6)
194
195 *******************************************************************************/
196
197 bool patcher_get_putfield(u1 *sp)
198 {
199         u1               *ra;
200         unresolved_field *uf;
201         fieldinfo        *fi;
202
203         ra    = (u1 *)               *((ptrint *) (sp + 5 * 8));
204         uf    = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
205
206         /* get the fieldinfo */
207
208         if (!(fi = resolve_field_eager(uf)))
209                 return false;
210
211         /* if we show disassembly, we have to skip the nop */
212
213         if (opt_showdisassemble) {
214                 /* patch the field's offset into the instruction */
215
216                 *((u4 *) (ra + 4)) |= (s2) (fi->offset & 0x0000ffff);
217         }
218         else {
219                 /* otherwise store the patched instruction on the stack */
220
221                 *((u4 *) (sp + 3 * 8)) |= (s2) (fi->offset & 0x0000ffff);
222         }
223
224         return true;
225 }
226
227
228 /* patcher_aconst **************************************************************
229
230    Machine code:
231
232    <patched call postition>
233    a61bff80    ldq     a0,-128(pv)
234
235 *******************************************************************************/
236
237 bool patcher_aconst(u1 *sp)
238 {
239         constant_classref *cr;
240         s4                 disp;
241         u1                *pv;
242         classinfo         *c;
243
244         /* get stuff from the stack */
245
246         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
247         disp  =                       *((s4 *)     (sp + 1 * 8));
248         pv    = (u1 *)                *((ptrint *) (sp + 0 * 8));
249
250         /* get the classinfo */
251
252         if (!(c = resolve_classref_eager(cr)))
253                 return false;
254
255         /* patch the classinfo pointer */
256
257         *((ptrint *) (pv + disp)) = (ptrint) c;
258
259         return true;
260 }
261
262
263 /* patcher_builtin_multianewarray **********************************************
264
265    Machine code:
266
267    <patched call position>
268    a63bff80    ldq     a1,-128(pv)
269    47de0412    mov     sp,a2
270    a77bff78    ldq     pv,-136(pv)
271    6b5b4000    jsr     (pv)
272
273 *******************************************************************************/
274
275 bool patcher_builtin_multianewarray(u1 *sp)
276 {
277         constant_classref *cr;
278         s4                 disp;
279         u1                *pv;
280         classinfo         *c;
281
282         /* get stuff from the stack */
283
284         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
285         disp  =                       *((s4 *)     (sp + 1 * 8));
286         pv    = (u1 *)                *((ptrint *) (sp + 0 * 8));
287
288         /* get the classinfo */
289
290         if (!(c = resolve_classref_eager(cr)))
291                 return false;
292
293         /* patch the classinfo pointer */
294
295         *((ptrint *) (pv + disp)) = (ptrint) c;
296
297         return true;
298 }
299
300
301 /* patcher_builtin_arraycheckcast **********************************************
302
303    Machine code:
304
305    <patched call position>
306    a63bfe60    ldq     a1,-416(pv)
307    a77bfe58    ldq     pv,-424(pv)
308    6b5b4000    jsr     (pv)
309
310 *******************************************************************************/
311
312 bool patcher_builtin_arraycheckcast(u1 *sp)
313 {
314         constant_classref *cr;
315         s4                 disp;
316         u1                *pv;
317         classinfo         *c;
318
319         /* get stuff from the stack */
320
321         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
322         disp  =                       *((s4 *)     (sp + 1 * 8));
323         pv    = (u1 *)                *((ptrint *) (sp + 0 * 8));
324
325         /* get the classinfo */
326
327         if (!(c = resolve_classref_eager(cr)))
328                 return false;
329
330         /* patch the classinfo pointer */
331
332         *((ptrint *) (pv + disp)) = (ptrint) c;
333
334         return true;
335 }
336
337
338 /* patcher_invokestatic_special ************************************************
339
340    Machine code:
341
342    <patched call position>
343    a77bffa8    ldq     pv,-88(pv)
344    6b5b4000    jsr     (pv)
345
346 ******************************************************************************/
347
348 bool patcher_invokestatic_special(u1 *sp)
349 {
350         unresolved_method *um;
351         s4                 disp;
352         u1                *pv;
353         methodinfo        *m;
354
355         /* get stuff from the stack */
356
357         um    = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
358         disp  =                       *((s4 *)     (sp + 1 * 8));
359         pv    = (u1 *)                *((ptrint *) (sp + 0 * 8));
360
361         /* get the fieldinfo */
362
363         if (!(m = resolve_method_eager(um)))
364                 return false;
365
366         /* patch stubroutine */
367
368         *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
369
370         return true;
371 }
372
373
374 /* patcher_invokevirtual *******************************************************
375
376    Machine code:
377
378    <patched call position>
379    a7900000    ldq     at,0(a0)
380    a77c0100    ldq     pv,256(at)
381    6b5b4000    jsr     (pv)
382
383 *******************************************************************************/
384
385 bool patcher_invokevirtual(u1 *sp)
386 {
387         u1                *ra;
388         unresolved_method *um;
389         methodinfo        *m;
390
391         /* get stuff from the stack */
392
393         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
394         um    = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
395
396         /* get the fieldinfo */
397
398         if (!(m = resolve_method_eager(um)))
399                 return false;
400
401         /* if we show disassembly, we have to skip the nop */
402
403         if (opt_showdisassemble)
404                 ra = ra + 4;
405
406         /* patch vftbl index */
407
408         *((s4 *) (ra + 4)) |= (s4) ((OFFSET(vftbl_t, table[0]) +
409                                                                  sizeof(methodptr) * m->vftblindex) & 0x0000ffff);
410
411         return true;
412 }
413
414
415 /* patcher_invokeinterface *****************************************************
416
417    Machine code:
418
419    <patched call position>
420    a7900000    ldq     at,0(a0)
421    a79cffa0    ldq     at,-96(at)
422    a77c0018    ldq     pv,24(at)
423    6b5b4000    jsr     (pv)
424
425 *******************************************************************************/
426
427 bool patcher_invokeinterface(u1 *sp)
428 {
429         u1                *ra;
430         unresolved_method *um;
431         methodinfo        *m;
432
433         /* get stuff from the stack */
434
435         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
436         um    = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
437
438         /* get the fieldinfo */
439
440         if (!(m = resolve_method_eager(um)))
441                 return false;
442
443         /* if we show disassembly, we have to skip the nop */
444
445         if (opt_showdisassemble)
446                 ra = ra + 4;
447
448         /* patch interfacetable index */
449
450         *((s4 *) (ra + 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
451                                                                  sizeof(methodptr*) * m->class->index) & 0x0000ffff);
452
453         /* patch method offset */
454
455         *((s4 *) (ra + 4 + 4)) |=
456                 (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x0000ffff);
457
458         return true;
459 }
460
461
462 /* patcher_checkcast_instanceof_flags ******************************************
463
464    Machine code:
465
466    <patched call position>
467
468 *******************************************************************************/
469
470 bool patcher_checkcast_instanceof_flags(u1 *sp)
471 {
472         constant_classref *cr;
473         s4                 disp;
474         u1                *pv;
475         classinfo         *c;
476
477         /* get stuff from the stack */
478
479         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
480         disp  =                       *((s4 *)     (sp + 1 * 8));
481         pv    = (u1 *)                *((ptrint *) (sp + 0 * 8));
482
483         /* get the fieldinfo */
484
485         if (!(c = resolve_classref_eager(cr)))
486                 return false;
487
488         /* patch class flags */
489
490         *((s4 *) (pv + disp)) = (s4) c->flags;
491
492         return true;
493 }
494
495
496 /* patcher_checkcast_instanceof_interface **************************************
497
498    Machine code:
499
500    <patched call position>
501    a78e0000    ldq     at,0(s5)
502    a3bc001c    ldl     gp,28(at)
503    23bdfffd    lda     gp,-3(gp)
504    efa0002e    ble     gp,0x00000200002bf6b0
505    a7bcffe8    ldq     gp,-24(at)
506
507 *******************************************************************************/
508
509 bool patcher_checkcast_instanceof_interface(u1 *sp)
510 {
511         u1                *ra;
512         constant_classref *cr;
513         classinfo         *c;
514
515         /* get stuff from the stack */
516
517         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
518         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
519
520         /* get the fieldinfo */
521
522         if (!(c = resolve_classref_eager(cr)))
523                 return false;
524
525         /* if we show disassembly, we have to skip the nop */
526
527         if (opt_showdisassemble)
528                 ra = ra + 4;
529
530         /* patch super class index */
531
532         *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
533
534         *((s4 *) (ra + 4 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
535                                                                          c->index * sizeof(methodptr*)) & 0x0000ffff);
536
537         return true;
538 }
539
540
541 /* patcher_checkcast_instanceof_class ******************************************
542
543    Machine code:
544
545    <patched call position>
546    a7940000    ldq     at,0(a4)
547    a7bbff28    ldq     gp,-216(pv)
548
549 *******************************************************************************/
550
551 bool patcher_checkcast_instanceof_class(u1 *sp)
552 {
553         constant_classref *cr;
554         s4                 disp;
555         u1                *pv;
556         classinfo         *c;
557
558         /* get stuff from the stack */
559
560         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
561         disp  =                       *((s4 *)     (sp + 1 * 8));
562         pv    = (u1 *)                *((ptrint *) (sp + 0 * 8));
563
564         /* get the fieldinfo */
565
566         if (!(c = resolve_classref_eager(cr)))
567                 return false;
568
569         /* patch super class' vftbl */
570
571         *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
572
573         return true;
574 }
575
576
577 /* patcher_clinit **************************************************************
578
579    XXX
580
581 *******************************************************************************/
582
583 bool patcher_clinit(u1 *sp)
584 {
585         classinfo *c;
586
587         /* get stuff from the stack */
588
589         c = (classinfo *) *((ptrint *) (sp + 2 * 8));
590
591         /* check if the class is initialized */
592
593         if (!(c->state & CLASS_INITIALIZED))
594                 if (!initialize_class(c))
595                         return false;
596
597         return true;
598 }
599
600
601 /* patcher_athrow_areturn ******************************************************
602
603    Machine code:
604
605    <patched call position>
606
607 *******************************************************************************/
608
609 #ifdef ENABLE_VERIFIER
610 bool patcher_athrow_areturn(u1 *sp)
611 {
612         unresolved_class *uc;
613         classinfo        *c;
614
615         /* get stuff from the stack */
616
617         uc = (unresolved_class *)  *((ptrint *) (sp + 2 * 8));
618
619         /* resolve the class */
620
621         if (!resolve_class(uc, resolveEager, false, &c))
622                 return false;
623
624         return true;
625 }
626 #endif /* ENABLE_VERIFIER */
627
628
629 /* patcher_resolve_native ******************************************************
630
631    XXX
632
633 *******************************************************************************/
634
635 #if !defined(WITH_STATIC_CLASSPATH)
636 bool patcher_resolve_native(u1 *sp)
637 {
638         methodinfo  *m;
639         s4           disp;
640         u1          *pv;
641         functionptr  f;
642
643         /* get stuff from the stack */
644
645         m     = (methodinfo *) *((ptrint *) (sp + 2 * 8));
646         disp  =                *((s4 *)     (sp + 1 * 8));
647         pv    = (u1 *)         *((ptrint *) (sp + 0 * 8));
648
649         /* resolve native function */
650
651         if (!(f = native_resolve_function(m)))
652                 return false;
653
654         /* patch native function pointer */
655
656         *((ptrint *) (pv + disp)) = (ptrint) f;
657
658         return true;
659 }
660 #endif /* !defined(WITH_STATIC_CLASSPATH) */
661
662
663 /*
664  * These are local overrides for various environment variables in Emacs.
665  * Please do not remove this and leave it at the end of the file, where
666  * Emacs will automagically detect them.
667  * ---------------------------------------------------------------------
668  * Local variables:
669  * mode: c
670  * indent-tabs-mode: t
671  * c-basic-offset: 4
672  * tab-width: 4
673  * End:
674  * vim:noexpandtab:sw=4:ts=4:
675  */