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