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