e9280929ec11c4bcd4dafd9a98fa628ea08514fa
[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 8268 2007-08-07 13:24:43Z 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-common.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 #define PATCH_BACK_ORIGINAL_MCODE \
58         *((u4 *) pr->mpc) = (u4) pr->mcode; \
59     md_icacheflush(NULL, 0);
60
61
62 /* patcher_initialize_class ****************************************************
63
64    Initalizes a given classinfo pointer.  This function does not patch
65    any data.
66
67 *******************************************************************************/
68
69 bool patcher_initialize_class(patchref_t *pr)
70 {
71         classinfo *c;
72
73         /* get stuff from the stack */
74
75         c = (classinfo *) pr->ref;
76
77         /* check if the class is initialized */
78
79         if (!(c->state & CLASS_INITIALIZED))
80                 if (!initialize_class(c))
81                         return false;
82
83         PATCH_BACK_ORIGINAL_MCODE;
84
85         return true;
86 }
87
88 /* patcher_resolve_class *****************************************************
89
90    Initalizes a given classinfo pointer.  This function does not patch
91    any data.
92
93 *******************************************************************************/
94
95 #ifdef ENABLE_VERIFIER
96 bool patcher_resolve_class(patchref_t *pr)
97 {
98         unresolved_class *uc;
99
100         /* get stuff from the stack */
101
102         uc = (unresolved_class *) pr->ref;
103
104         /* resolve the class and check subtype constraints */
105
106         if (!resolve_class_eager_no_access_check(uc))
107                 return false;
108
109         PATCH_BACK_ORIGINAL_MCODE;
110
111         return true;
112 }
113 #endif /* ENABLE_VERIFIER */
114
115
116 /* patcher_resolve_classref_to_classinfo ***************************************
117
118    ACONST:
119
120    <patched call postition>
121    a61bff80    ldq     a0,-128(pv)
122
123    MULTIANEWARRAY:
124
125    <patched call position>
126    a63bff80    ldq     a1,-128(pv)
127    47de0412    mov     sp,a2
128    a77bff78    ldq     pv,-136(pv)
129    6b5b4000    jsr     (pv)
130
131    ARRAYCHECKCAST:
132
133    <patched call position>
134    a63bfe60    ldq     a1,-416(pv)
135    a77bfe58    ldq     pv,-424(pv)
136    6b5b4000    jsr     (pv)
137
138 *******************************************************************************/
139
140 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
141 {
142         constant_classref *cr;
143         u1                *datap;
144         classinfo         *c;
145
146         /* get stuff from the stack */
147
148         cr    = (constant_classref *) pr->ref;
149         datap = (u1 *)                pr->datap;
150
151         /* get the classinfo */
152
153         if (!(c = resolve_classref_eager(cr)))
154                 return false;
155
156         PATCH_BACK_ORIGINAL_MCODE;
157
158         /* patch the classinfo pointer */
159
160         *((ptrint *) datap) = (ptrint) c;
161
162         return true;
163 }
164
165
166 /* patcher_resolve_classref_to_vftbl *******************************************
167
168    CHECKCAST (class):
169    INSTANCEOF (class):
170
171    <patched call position>
172    a7940000    ldq     at,0(a4)
173    a7bbff28    ldq     gp,-216(pv)
174
175 *******************************************************************************/
176
177 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
178 {
179         constant_classref *cr;
180         u1                *datap;
181         classinfo         *c;
182
183         /* get stuff from the stack */
184
185         cr    = (constant_classref *) pr->ref;
186         datap = (u1 *)                pr->datap;
187
188         /* get the fieldinfo */
189
190         if (!(c = resolve_classref_eager(cr)))
191                 return false;
192
193         PATCH_BACK_ORIGINAL_MCODE;
194
195         /* patch super class' vftbl */
196
197         *((ptrint *) datap) = (ptrint) c->vftbl;
198
199         return true;
200 }
201
202
203 /* patcher_resolve_classref_to_flags *******************************************
204
205    CHECKCAST/INSTANCEOF:
206
207    <patched call position>
208
209 *******************************************************************************/
210
211 bool patcher_resolve_classref_to_flags(patchref_t *pr)
212 {
213         constant_classref *cr;
214         u1                *datap;
215         classinfo         *c;
216
217         /* get stuff from the stack */
218
219         cr    = (constant_classref *) pr->ref;
220         datap = (u1 *)                pr->datap;
221
222         /* get the fieldinfo */
223
224         if (!(c = resolve_classref_eager(cr)))
225                 return false;
226
227         PATCH_BACK_ORIGINAL_MCODE;
228
229         /* patch class flags */
230
231         *((s4 *) datap) = (s4) c->flags;
232
233         return true;
234 }
235
236
237 /* patcher_resolve_native_function *********************************************
238
239    XXX
240
241 *******************************************************************************/
242
243 #if !defined(WITH_STATIC_CLASSPATH)
244 bool patcher_resolve_native_function(patchref_t *pr)
245 {
246         methodinfo  *m;
247         u1          *datap;
248         functionptr  f;
249
250         /* get stuff from the stack */
251
252         m     = (methodinfo *) pr->ref;
253         datap = (u1 *)         pr->datap;
254
255         /* resolve native function */
256
257         if (!(f = native_resolve_function(m)))
258                 return false;
259
260         PATCH_BACK_ORIGINAL_MCODE;
261
262         /* patch native function pointer */
263
264         *((ptrint *) datap) = (ptrint) f;
265
266         return true;
267 }
268 #endif /* !defined(WITH_STATIC_CLASSPATH) */
269
270
271 /* patcher_get_putstatic *******************************************************
272
273    Machine code:
274
275    <patched call position>
276    a73bff98    ldq     t11,-104(pv)
277    a2590000    ldl     a2,0(t11)
278
279 *******************************************************************************/
280
281 bool patcher_get_putstatic(patchref_t *pr)
282 {
283         unresolved_field *uf;
284         u1               *datap;
285         fieldinfo        *fi;
286
287         /* get stuff from the stack */
288
289         uf    = (unresolved_field *) pr->ref;
290         datap = (u1 *)               pr->datap;
291
292         /* get the fieldinfo */
293
294         if (!(fi = resolve_field_eager(uf)))
295                 return false;
296
297         /* check if the field's class is initialized */
298
299         if (!(fi->class->state & CLASS_INITIALIZED))
300                 if (!initialize_class(fi->class))
301                         return false;
302
303         PATCH_BACK_ORIGINAL_MCODE;
304
305         /* patch the field value's address */
306
307         *((intptr_t *) datap) = (intptr_t) fi->value;
308
309         return true;
310 }
311
312
313 /* patcher_get_putfield ********************************************************
314
315    Machine code:
316
317    <patched call position>
318    a2af0020    ldl     a5,32(s6)
319
320 *******************************************************************************/
321
322 bool patcher_get_putfield(patchref_t *pr)
323 {
324         u1               *ra;
325         unresolved_field *uf;
326         fieldinfo        *fi;
327
328         ra    = (u1 *)               pr->mpc;
329         uf    = (unresolved_field *) pr->ref;
330
331         /* get the fieldinfo */
332
333         if (!(fi = resolve_field_eager(uf)))
334                 return false;
335
336         PATCH_BACK_ORIGINAL_MCODE;
337
338         /* if we show disassembly, we have to skip the nop */
339
340         if (opt_shownops)
341                 ra = ra + 4;
342
343         /* patch the field's offset into the instruction */
344
345         *((u4 *) ra) |= (s2) (fi->offset & 0x0000ffff);
346
347         md_icacheflush(NULL, 0);
348
349         return true;
350 }
351
352
353 /* patcher_invokestatic_special ************************************************
354
355    Machine code:
356
357    <patched call position>
358    a77bffa8    ldq     pv,-88(pv)
359    6b5b4000    jsr     (pv)
360
361 ******************************************************************************/
362
363 bool patcher_invokestatic_special(patchref_t *pr)
364 {
365         unresolved_method *um;
366         u1                *datap;
367         methodinfo        *m;
368
369         /* get stuff from the stack */
370
371         um    = (unresolved_method *) pr->ref;
372         datap = (u1 *)                pr->datap;
373
374         /* get the fieldinfo */
375
376         if (!(m = resolve_method_eager(um)))
377                 return false;
378
379         PATCH_BACK_ORIGINAL_MCODE;
380
381         /* patch stubroutine */
382
383         *((ptrint *) datap) = (ptrint) m->stubroutine;
384
385         return true;
386 }
387
388
389 /* patcher_invokevirtual *******************************************************
390
391    Machine code:
392
393    <patched call position>
394    a7900000    ldq     at,0(a0)
395    a77c0100    ldq     pv,256(at)
396    6b5b4000    jsr     (pv)
397
398 *******************************************************************************/
399
400 bool patcher_invokevirtual(patchref_t *pr)
401 {
402         u1                *ra;
403         unresolved_method *um;
404         methodinfo        *m;
405
406         /* get stuff from the stack */
407
408         ra    = (u1 *)                pr->mpc;
409         um    = (unresolved_method *) pr->ref;
410
411         /* get the fieldinfo */
412
413         if (!(m = resolve_method_eager(um)))
414                 return false;
415
416         PATCH_BACK_ORIGINAL_MCODE;
417
418         /* if we show disassembly, we have to skip the nop */
419
420         if (opt_shownops)
421                 ra = ra + 4;
422
423         /* patch vftbl index */
424
425         *((s4 *) (ra + 4)) |= (s4) ((OFFSET(vftbl_t, table[0]) +
426                                                                  sizeof(methodptr) * m->vftblindex) & 0x0000ffff);
427
428         md_icacheflush(NULL, 0);
429
430         return true;
431 }
432
433
434 /* patcher_invokeinterface *****************************************************
435
436    Machine code:
437
438    <patched call position>
439    a7900000    ldq     at,0(a0)
440    a79cffa0    ldq     at,-96(at)
441    a77c0018    ldq     pv,24(at)
442    6b5b4000    jsr     (pv)
443
444 *******************************************************************************/
445
446 bool patcher_invokeinterface(patchref_t *pr)
447 {
448         u1                *ra;
449         unresolved_method *um;
450         methodinfo        *m;
451
452         /* get stuff from the stack */
453
454         ra    = (u1 *)                pr->mpc;
455         um    = (unresolved_method *) pr->ref;
456
457         /* get the fieldinfo */
458
459         if (!(m = resolve_method_eager(um)))
460                 return false;
461
462         PATCH_BACK_ORIGINAL_MCODE;
463
464         /* if we show disassembly, we have to skip the nop */
465
466         if (opt_shownops)
467                 ra = ra + 4;
468
469         /* patch interfacetable index */
470
471         *((s4 *) (ra + 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
472                                                                  sizeof(methodptr*) * m->class->index) & 0x0000ffff);
473
474         /* patch method offset */
475
476         *((s4 *) (ra + 4 + 4)) |=
477                 (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x0000ffff);
478
479         md_icacheflush(NULL, 0);
480
481         return true;
482 }
483
484
485 /* patcher_checkcast_interface *************************************************
486
487    Machine code:
488
489    <patched call position>
490    a78e0000    ldq     at,0(s5)
491    a3bc001c    ldl     gp,28(at)
492    23bdfffd    lda     gp,-3(gp)
493    efa0002e    ble     gp,0x00000200002bf6b0
494    a7bcffe8    ldq     gp,-24(at)
495
496 *******************************************************************************/
497
498 bool patcher_checkcast_interface(patchref_t *pr)
499 {
500         u1                *ra;
501         constant_classref *cr;
502         classinfo         *c;
503
504         /* get stuff from the stack */
505
506         ra    = (u1 *)                pr->mpc;
507         cr    = (constant_classref *) pr->ref;
508
509         /* get the fieldinfo */
510
511         if (!(c = resolve_classref_eager(cr)))
512                 return false;
513
514         PATCH_BACK_ORIGINAL_MCODE;
515
516         /* if we show disassembly, we have to skip the nop */
517
518         if (opt_shownops)
519                 ra = ra + 4;
520
521         /* patch super class index */
522
523         *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
524
525         *((s4 *) (ra + 5 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
526                                                                          c->index * sizeof(methodptr*)) & 0x0000ffff);
527
528         md_icacheflush(NULL, 0);
529
530         return true;
531 }
532
533
534 /* patcher_instanceof_interface ************************************************
535
536    Machine code:
537
538    <patched call position>
539    a78e0000    ldq     at,0(s5)
540    a3bc001c    ldl     gp,28(at)
541    23bdfffd    lda     gp,-3(gp)
542    efa0002e    ble     gp,0x00000200002bf6b0
543    a7bcffe8    ldq     gp,-24(at)
544
545 *******************************************************************************/
546
547 bool patcher_instanceof_interface(patchref_t *pr)
548 {
549         u1                *ra;
550         constant_classref *cr;
551         classinfo         *c;
552
553         /* get stuff from the stack */
554
555         ra    = (u1 *)                pr->mpc;
556         cr    = (constant_classref *) pr->ref;
557
558         /* get the fieldinfo */
559
560         if (!(c = resolve_classref_eager(cr)))
561                 return false;
562
563         PATCH_BACK_ORIGINAL_MCODE;
564
565         /* if we show disassembly, we have to skip the nop */
566
567         if (opt_shownops)
568                 ra = ra + 4;
569
570         /* patch super class index */
571
572         *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
573
574         *((s4 *) (ra + 4 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
575                                                                          c->index * sizeof(methodptr*)) & 0x0000ffff);
576
577         md_icacheflush(NULL, 0);
578
579         return true;
580 }
581
582
583 /*
584  * These are local overrides for various environment variables in Emacs.
585  * Please do not remove this and leave it at the end of the file, where
586  * Emacs will automagically detect them.
587  * ---------------------------------------------------------------------
588  * Local variables:
589  * mode: c
590  * indent-tabs-mode: t
591  * c-basic-offset: 4
592  * tab-width: 4
593  * End:
594  * vim:noexpandtab:sw=4:ts=4:
595  */