* Merged in twisti-branch.
[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, 2007 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    $Id: patcher.c 7486 2007-03-08 13:50:07Z twisti $
26
27 */
28
29
30 #include "config.h"
31
32 #include <assert.h>
33
34 #include "vm/types.h"
35
36 #include "mm/memory.h"
37
38 #include "native/native.h"
39
40 #include "vm/builtin.h"
41 #include "vm/exceptions.h"
42 #include "vm/initialize.h"
43
44 #include "vm/jit/asmpart.h"
45 #include "vm/jit/patcher.h"
46 #include "vm/jit/md.h"
47 #include "vm/jit/methodheader.h"
48 #include "vm/jit/stacktrace.h"
49
50 #include "vmcore/class.h"
51 #include "vmcore/field.h"
52 #include "vmcore/options.h"
53 #include "vmcore/references.h"
54 #include "vm/resolve.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 /* patcher_initialize_class ****************************************************
146
147    Initalizes a given classinfo pointer.  This function does not patch
148    any data.
149
150 *******************************************************************************/
151
152 bool patcher_initialize_class(u1 *sp)
153 {
154         classinfo *c;
155
156         /* get stuff from the stack */
157
158         c = (classinfo *) *((ptrint *) (sp + 2 * 8));
159
160         /* check if the class is initialized */
161
162         if (!(c->state & CLASS_INITIALIZED))
163                 if (!initialize_class(c))
164                         return false;
165
166         return true;
167 }
168
169 /* patcher_resolve_class *****************************************************
170
171    Initalizes a given classinfo pointer.  This function does not patch
172    any data.
173
174 *******************************************************************************/
175
176 #ifdef ENABLE_VERIFIER
177 bool patcher_resolve_class(u1 *sp)
178 {
179         unresolved_class *uc;
180
181         /* get stuff from the stack */
182
183         uc = (unresolved_class *)  *((ptrint *) (sp + 2 * 8));
184
185         /* resolve the class and check subtype constraints */
186
187         if (!resolve_class_eager_no_access_check(uc))
188                 return false;
189
190         return true;
191 }
192 #endif /* ENABLE_VERIFIER */
193
194
195 /* patcher_resolve_classref_to_classinfo ***************************************
196
197    ACONST:
198
199    <patched call postition>
200    a61bff80    ldq     a0,-128(pv)
201
202    MULTIANEWARRAY:
203
204    <patched call position>
205    a63bff80    ldq     a1,-128(pv)
206    47de0412    mov     sp,a2
207    a77bff78    ldq     pv,-136(pv)
208    6b5b4000    jsr     (pv)
209
210    ARRAYCHECKCAST:
211
212    <patched call position>
213    a63bfe60    ldq     a1,-416(pv)
214    a77bfe58    ldq     pv,-424(pv)
215    6b5b4000    jsr     (pv)
216
217 *******************************************************************************/
218
219 bool patcher_resolve_classref_to_classinfo(u1 *sp)
220 {
221         constant_classref *cr;
222         s4                 disp;
223         u1                *pv;
224         classinfo         *c;
225
226         /* get stuff from the stack */
227
228         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
229         disp  =                       *((s4 *)     (sp + 1 * 8));
230         pv    = (u1 *)                *((ptrint *) (sp + 0 * 8));
231
232         /* get the classinfo */
233
234         if (!(c = resolve_classref_eager(cr)))
235                 return false;
236
237         /* patch the classinfo pointer */
238
239         *((ptrint *) (pv + disp)) = (ptrint) c;
240
241         return true;
242 }
243
244
245 /* patcher_resolve_classref_to_vftbl *******************************************
246
247    CHECKCAST (class):
248    INSTANCEOF (class):
249
250    <patched call position>
251    a7940000    ldq     at,0(a4)
252    a7bbff28    ldq     gp,-216(pv)
253
254 *******************************************************************************/
255
256 bool patcher_resolve_classref_to_vftbl(u1 *sp)
257 {
258         constant_classref *cr;
259         s4                 disp;
260         u1                *pv;
261         classinfo         *c;
262
263         /* get stuff from the stack */
264
265         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
266         disp  =                       *((s4 *)     (sp + 1 * 8));
267         pv    = (u1 *)                *((ptrint *) (sp + 0 * 8));
268
269         /* get the fieldinfo */
270
271         if (!(c = resolve_classref_eager(cr)))
272                 return false;
273
274         /* patch super class' vftbl */
275
276         *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
277
278         return true;
279 }
280
281
282 /* patcher_resolve_classref_to_flags *******************************************
283
284    CHECKCAST/INSTANCEOF:
285
286    <patched call position>
287
288 *******************************************************************************/
289
290 bool patcher_resolve_classref_to_flags(u1 *sp)
291 {
292         constant_classref *cr;
293         s4                 disp;
294         u1                *pv;
295         classinfo         *c;
296
297         /* get stuff from the stack */
298
299         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
300         disp  =                       *((s4 *)     (sp + 1 * 8));
301         pv    = (u1 *)                *((ptrint *) (sp + 0 * 8));
302
303         /* get the fieldinfo */
304
305         if (!(c = resolve_classref_eager(cr)))
306                 return false;
307
308         /* patch class flags */
309
310         *((s4 *) (pv + disp)) = (s4) c->flags;
311
312         return true;
313 }
314
315
316 /* patcher_resolve_native_function *********************************************
317
318    XXX
319
320 *******************************************************************************/
321
322 #if !defined(WITH_STATIC_CLASSPATH)
323 bool patcher_resolve_native_function(u1 *sp)
324 {
325         methodinfo  *m;
326         s4           disp;
327         u1          *pv;
328         functionptr  f;
329
330         /* get stuff from the stack */
331
332         m     = (methodinfo *) *((ptrint *) (sp + 2 * 8));
333         disp  =                *((s4 *)     (sp + 1 * 8));
334         pv    = (u1 *)         *((ptrint *) (sp + 0 * 8));
335
336         /* resolve native function */
337
338         if (!(f = native_resolve_function(m)))
339                 return false;
340
341         /* patch native function pointer */
342
343         *((ptrint *) (pv + disp)) = (ptrint) f;
344
345         return true;
346 }
347 #endif /* !defined(WITH_STATIC_CLASSPATH) */
348
349
350 /* patcher_get_putstatic *******************************************************
351
352    Machine code:
353
354    <patched call position>
355    a73bff98    ldq     t11,-104(pv)
356    a2590000    ldl     a2,0(t11)
357
358 *******************************************************************************/
359
360 bool patcher_get_putstatic(u1 *sp)
361 {
362         unresolved_field *uf;
363         s4                disp;
364         u1               *pv;
365         fieldinfo        *fi;
366
367         /* get stuff from the stack */
368
369         uf    = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
370         disp  =                      *((s4 *)     (sp + 1 * 8));
371         pv    = (u1 *)               *((ptrint *) (sp + 0 * 8));
372
373         /* get the fieldinfo */
374
375         if (!(fi = resolve_field_eager(uf)))
376                 return false;
377
378         /* check if the field's class is initialized */
379
380         if (!(fi->class->state & CLASS_INITIALIZED))
381                 if (!initialize_class(fi->class))
382                         return false;
383
384         /* patch the field value's address */
385
386         *((ptrint *) (pv + disp)) = (ptrint) &(fi->value);
387
388         return true;
389 }
390
391
392 /* patcher_get_putfield ********************************************************
393
394    Machine code:
395
396    <patched call position>
397    a2af0020    ldl     a5,32(s6)
398
399 *******************************************************************************/
400
401 bool patcher_get_putfield(u1 *sp)
402 {
403         u1               *ra;
404         unresolved_field *uf;
405         fieldinfo        *fi;
406
407         ra    = (u1 *)               *((ptrint *) (sp + 5 * 8));
408         uf    = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
409
410         /* get the fieldinfo */
411
412         if (!(fi = resolve_field_eager(uf)))
413                 return false;
414
415         /* if we show disassembly, we have to skip the nop */
416
417         if (opt_shownops) {
418                 /* patch the field's offset into the instruction */
419
420                 *((u4 *) (ra + 4)) |= (s2) (fi->offset & 0x0000ffff);
421         }
422         else {
423                 /* otherwise store the patched instruction on the stack */
424
425                 *((u4 *) (sp + 3 * 8)) |= (s2) (fi->offset & 0x0000ffff);
426         }
427
428         return true;
429 }
430
431
432 /* patcher_invokestatic_special ************************************************
433
434    Machine code:
435
436    <patched call position>
437    a77bffa8    ldq     pv,-88(pv)
438    6b5b4000    jsr     (pv)
439
440 ******************************************************************************/
441
442 bool patcher_invokestatic_special(u1 *sp)
443 {
444         unresolved_method *um;
445         s4                 disp;
446         u1                *pv;
447         methodinfo        *m;
448
449         /* get stuff from the stack */
450
451         um    = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
452         disp  =                       *((s4 *)     (sp + 1 * 8));
453         pv    = (u1 *)                *((ptrint *) (sp + 0 * 8));
454
455         /* get the fieldinfo */
456
457         if (!(m = resolve_method_eager(um)))
458                 return false;
459
460         /* patch stubroutine */
461
462         *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
463
464         return true;
465 }
466
467
468 /* patcher_invokevirtual *******************************************************
469
470    Machine code:
471
472    <patched call position>
473    a7900000    ldq     at,0(a0)
474    a77c0100    ldq     pv,256(at)
475    6b5b4000    jsr     (pv)
476
477 *******************************************************************************/
478
479 bool patcher_invokevirtual(u1 *sp)
480 {
481         u1                *ra;
482         unresolved_method *um;
483         methodinfo        *m;
484
485         /* get stuff from the stack */
486
487         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
488         um    = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
489
490         /* get the fieldinfo */
491
492         if (!(m = resolve_method_eager(um)))
493                 return false;
494
495         /* if we show disassembly, we have to skip the nop */
496
497         if (opt_shownops)
498                 ra = ra + 4;
499
500         /* patch vftbl index */
501
502         *((s4 *) (ra + 4)) |= (s4) ((OFFSET(vftbl_t, table[0]) +
503                                                                  sizeof(methodptr) * m->vftblindex) & 0x0000ffff);
504
505         return true;
506 }
507
508
509 /* patcher_invokeinterface *****************************************************
510
511    Machine code:
512
513    <patched call position>
514    a7900000    ldq     at,0(a0)
515    a79cffa0    ldq     at,-96(at)
516    a77c0018    ldq     pv,24(at)
517    6b5b4000    jsr     (pv)
518
519 *******************************************************************************/
520
521 bool patcher_invokeinterface(u1 *sp)
522 {
523         u1                *ra;
524         unresolved_method *um;
525         methodinfo        *m;
526
527         /* get stuff from the stack */
528
529         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
530         um    = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
531
532         /* get the fieldinfo */
533
534         if (!(m = resolve_method_eager(um)))
535                 return false;
536
537         /* if we show disassembly, we have to skip the nop */
538
539         if (opt_shownops)
540                 ra = ra + 4;
541
542         /* patch interfacetable index */
543
544         *((s4 *) (ra + 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
545                                                                  sizeof(methodptr*) * m->class->index) & 0x0000ffff);
546
547         /* patch method offset */
548
549         *((s4 *) (ra + 4 + 4)) |=
550                 (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x0000ffff);
551
552         return true;
553 }
554
555
556 /* patcher_checkcast_interface *************************************************
557
558    Machine code:
559
560    <patched call position>
561    a78e0000    ldq     at,0(s5)
562    a3bc001c    ldl     gp,28(at)
563    23bdfffd    lda     gp,-3(gp)
564    efa0002e    ble     gp,0x00000200002bf6b0
565    a7bcffe8    ldq     gp,-24(at)
566
567 *******************************************************************************/
568
569 bool patcher_checkcast_interface(u1 *sp)
570 {
571         u1                *ra;
572         constant_classref *cr;
573         classinfo         *c;
574
575         /* get stuff from the stack */
576
577         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
578         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
579
580         /* get the fieldinfo */
581
582         if (!(c = resolve_classref_eager(cr)))
583                 return false;
584
585         /* if we show disassembly, we have to skip the nop */
586
587         if (opt_shownops)
588                 ra = ra + 4;
589
590         /* patch super class index */
591
592         *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
593
594         *((s4 *) (ra + 5 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
595                                                                          c->index * sizeof(methodptr*)) & 0x0000ffff);
596
597         return true;
598 }
599
600
601 /* patcher_instanceof_interface ************************************************
602
603    Machine code:
604
605    <patched call position>
606    a78e0000    ldq     at,0(s5)
607    a3bc001c    ldl     gp,28(at)
608    23bdfffd    lda     gp,-3(gp)
609    efa0002e    ble     gp,0x00000200002bf6b0
610    a7bcffe8    ldq     gp,-24(at)
611
612 *******************************************************************************/
613
614 bool patcher_instanceof_interface(u1 *sp)
615 {
616         u1                *ra;
617         constant_classref *cr;
618         classinfo         *c;
619
620         /* get stuff from the stack */
621
622         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
623         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
624
625         /* get the fieldinfo */
626
627         if (!(c = resolve_classref_eager(cr)))
628                 return false;
629
630         /* if we show disassembly, we have to skip the nop */
631
632         if (opt_shownops)
633                 ra = ra + 4;
634
635         /* patch super class index */
636
637         *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
638
639         *((s4 *) (ra + 4 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
640                                                                          c->index * sizeof(methodptr*)) & 0x0000ffff);
641
642         return true;
643 }
644
645
646 /*
647  * These are local overrides for various environment variables in Emacs.
648  * Please do not remove this and leave it at the end of the file, where
649  * Emacs will automagically detect them.
650  * ---------------------------------------------------------------------
651  * Local variables:
652  * mode: c
653  * indent-tabs-mode: t
654  * c-basic-offset: 4
655  * tab-width: 4
656  * End:
657  * vim:noexpandtab:sw=4:ts=4:
658  */