1 /* src/vm/jit/mips/patcher.c - MIPS code patching functions
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
8 This file is part of CACAO.
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.
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.
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
25 $Id: patcher.c 8264 2007-08-06 16:02:28Z twisti $
36 #include "vm/jit/mips/codegen.h"
38 #include "mm/memory.h"
40 #include "native/native.h"
42 #include "vm/builtin.h"
43 #include "vm/exceptions.h"
44 #include "vm/initialize.h"
46 #include "vm/jit/asmpart.h"
47 #include "vm/jit/md.h"
48 #include "vm/jit/patcher-common.h"
50 #include "vmcore/class.h"
51 #include "vmcore/field.h"
52 #include "vmcore/options.h"
53 #include "vm/resolve.h"
54 #include "vmcore/references.h"
57 #define PATCH_BACK_ORIGINAL_MCODE \
58 *((u4 *) pr->mpc) = (u4) pr->mcode; \
59 md_icacheflush((u1 *) pr->mpc, PATCHER_CALL_SIZE);
62 /* patcher_initialize_class ****************************************************
64 Initalizes a given classinfo pointer. This function does not patch
67 *******************************************************************************/
69 bool patcher_initialize_class(patchref_t *pr)
73 /* get stuff from the stack */
75 c = (classinfo *) pr->ref;
77 /* check if the class is initialized */
79 if (!(c->state & CLASS_INITIALIZED))
80 if (!initialize_class(c))
83 PATCH_BACK_ORIGINAL_MCODE;
89 /* patcher_resolve_class *****************************************************
91 Initalizes a given classinfo pointer. This function does not patch
94 *******************************************************************************/
96 #ifdef ENABLE_VERIFIER
97 bool patcher_resolve_class(patchref_t *pr)
101 /* get stuff from the stack */
103 uc = (unresolved_class *) pr->ref;
105 /* resolve the class and check subtype constraints */
107 if (!resolve_class_eager_no_access_check(uc))
110 PATCH_BACK_ORIGINAL_MCODE;
114 #endif /* ENABLE_VERIFIER */
117 /* patcher_get_putstatic *******************************************************
121 <patched call position>
122 dfc1ffb8 ld at,-72(s8)
125 *******************************************************************************/
127 bool patcher_get_putstatic(patchref_t *pr)
129 unresolved_field *uf;
133 /* get stuff from the stack */
135 uf = (unresolved_field *) pr->ref;
136 datap = (u1 *) pr->datap;
138 /* get the fieldinfo */
140 if (!(fi = resolve_field_eager(uf)))
143 /* check if the field's class is initialized */
145 if (!(fi->class->state & CLASS_INITIALIZED))
146 if (!initialize_class(fi->class))
149 PATCH_BACK_ORIGINAL_MCODE;
151 /* patch the field value's address */
153 *((ptrint *) datap) = (ptrint) &(fi->value);
155 /* synchronize data cache */
157 md_dcacheflush(datap, SIZEOF_VOID_P);
163 /* patcher_get_putfield ********************************************************
167 <patched call position>
168 8ee90020 lw a5,32(s7)
170 *******************************************************************************/
172 bool patcher_get_putfield(patchref_t *pr)
175 unresolved_field *uf;
178 /* get stuff from the stack */
181 uf = (unresolved_field *) pr->ref;
183 /* get the fieldinfo */
185 if (!(fi = resolve_field_eager(uf)))
188 PATCH_BACK_ORIGINAL_MCODE;
190 /* if we show disassembly, we have to skip the nop's */
193 ra = ra + PATCHER_CALL_SIZE;
195 #if SIZEOF_VOID_P == 4
196 if (IS_LNG_TYPE(fi->type)) {
197 # if WORDS_BIGENDIAN == 1
198 /* ATTENTION: order of these instructions depend on M_LLD_INTERN */
199 *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
200 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
202 /* ATTENTION: order of these instructions depend on M_LLD_INTERN */
203 *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
204 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
209 *((u4 *) (ra + 0 * 4)) |= (s2) (fi->offset & 0x0000ffff);
211 /* synchronize instruction cache */
213 md_icacheflush(ra, 2 * 4);
219 /* patcher_resolve_classref_to_classinfo ***************************************
223 <patched call postition>
224 dfc4ff98 ld a0,-104(s8)
228 <patched call position>
229 dfc5ff90 ld a1,-112(s8)
231 dfd9ff88 ld t9,-120(s8)
237 <patched call position>
238 dfc5ffc0 ld a1,-64(s8)
239 dfd9ffb8 ld t9,-72(s8)
243 *******************************************************************************/
245 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
247 constant_classref *cr;
251 /* get stuff from the stack */
253 cr = (constant_classref *) pr->ref;
254 datap = (u1 *) pr->datap;
256 /* get the classinfo */
258 if (!(c = resolve_classref_eager(cr)))
261 PATCH_BACK_ORIGINAL_MCODE;
263 /* patch the classinfo pointer */
265 *((intptr_t *) datap) = (intptr_t) c;
267 /* synchronize data cache */
269 md_dcacheflush(datap, SIZEOF_VOID_P);
275 /* patcher_resolve_classref_to_vftbl *******************************************
280 <patched call position>
282 dfd9ff18 ld t9,-232(s8)
284 *******************************************************************************/
286 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
288 constant_classref *cr;
292 /* get stuff from the stack */
294 cr = (constant_classref *) pr->ref;
295 datap = (u1 *) pr->datap;
297 /* get the fieldinfo */
299 if (!(c = resolve_classref_eager(cr)))
302 PATCH_BACK_ORIGINAL_MCODE;
304 /* patch super class' vftbl */
306 *((intptr_t *) datap) = (intptr_t) c->vftbl;
308 /* synchronize data cache */
310 md_dcacheflush(datap, SIZEOF_VOID_P);
316 /* patcher_resolve_classref_to_flags *******************************************
318 CHECKCAST/INSTANCEOF:
320 <patched call position>
321 8fc3ff24 lw v1,-220(s8)
322 30630200 andi v1,v1,512
323 1060000d beq v1,zero,0x000000001051824c
326 *******************************************************************************/
328 bool patcher_resolve_classref_to_flags(patchref_t *pr)
330 constant_classref *cr;
334 /* get stuff from the stack */
336 cr = (constant_classref *) pr->ref;
337 datap = (u1 *) pr->datap;
339 /* get the fieldinfo */
341 if (!(c = resolve_classref_eager(cr)))
344 PATCH_BACK_ORIGINAL_MCODE;
346 /* patch class flags */
348 *((int32_t *) datap) = (int32_t) c->flags;
350 /* synchronize data cache */
352 md_dcacheflush(datap, sizeof(int32_t));
358 /* patcher_resolve_native ******************************************************
362 *******************************************************************************/
364 #if !defined(WITH_STATIC_CLASSPATH)
365 bool patcher_resolve_native_function(patchref_t *pr)
371 /* get stuff from the stack */
373 m = (methodinfo *) pr->ref;
374 datap = (u1 *) pr->datap;
376 /* resolve native function */
378 if (!(f = native_resolve_function(m)))
381 PATCH_BACK_ORIGINAL_MCODE;
383 /* patch native function pointer */
385 *((ptrint *) datap) = (ptrint) f;
387 /* synchronize data cache */
389 md_dcacheflush(datap, SIZEOF_VOID_P);
393 #endif /* !defined(WITH_STATIC_CLASSPATH) */
396 /* patcher_invokestatic_special ************************************************
400 <patched call position>
401 dfdeffc0 ld s8,-64(s8)
405 ******************************************************************************/
407 bool patcher_invokestatic_special(patchref_t *pr)
409 unresolved_method *um;
413 /* get stuff from the stack */
415 um = (unresolved_method *) pr->ref;
416 datap = (u1 *) pr->datap;
418 /* get the fieldinfo */
420 if (!(m = resolve_method_eager(um)))
423 PATCH_BACK_ORIGINAL_MCODE;
425 /* patch stubroutine */
427 *((ptrint *) datap) = (ptrint) m->stubroutine;
429 /* synchronize data cache */
431 md_dcacheflush(datap, SIZEOF_VOID_P);
437 /* patcher_invokevirtual *******************************************************
441 <patched call position>
443 df3e0040 ld s8,64(t9)
447 *******************************************************************************/
449 bool patcher_invokevirtual(patchref_t *pr)
452 unresolved_method *um;
455 /* get stuff from the stack */
458 um = (unresolved_method *) pr->ref;
460 /* get the fieldinfo */
462 if (!(m = resolve_method_eager(um)))
465 PATCH_BACK_ORIGINAL_MCODE;
467 /* if we show disassembly, we have to skip the nop's */
470 ra = ra + PATCHER_CALL_SIZE;
472 /* patch vftbl index */
474 *((s4 *) (ra + 1 * 4)) |=
475 (s4) ((OFFSET(vftbl_t, table[0]) +
476 sizeof(methodptr) * m->vftblindex) & 0x0000ffff);
478 /* synchronize instruction cache */
480 md_icacheflush(ra + 1 * 4, 1 * 4);
486 /* patcher_invokeinterface *****************************************************
490 <patched call position>
492 df39ffa0 ld t9,-96(t9)
493 df3e0018 ld s8,24(t9)
497 *******************************************************************************/
499 bool patcher_invokeinterface(patchref_t *pr)
502 unresolved_method *um;
505 /* get stuff from the stack */
508 um = (unresolved_method *) pr->ref;
510 /* get the fieldinfo */
512 if (!(m = resolve_method_eager(um)))
515 PATCH_BACK_ORIGINAL_MCODE;
517 /* if we show disassembly, we have to skip the nop's */
520 ra = ra + PATCHER_CALL_SIZE;
522 /* patch interfacetable index */
524 *((s4 *) (ra + 1 * 4)) |=
525 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
526 sizeof(methodptr*) * m->class->index) & 0x0000ffff);
528 /* patch method offset */
530 *((s4 *) (ra + 2 * 4)) |=
531 (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x0000ffff);
533 /* synchronize instruction cache */
535 md_icacheflush(ra + 1 * 4, 2 * 4);
541 /* patcher_checkcast_interface *************************************************
545 <patched call position>
547 8c79001c lw t9,28(v1)
548 27390000 addiu t9,t9,0
549 1b200082 blez t9,zero,0x000000001051843c
553 *******************************************************************************/
555 bool patcher_checkcast_interface(patchref_t *pr)
558 constant_classref *cr;
561 /* get stuff from the stack */
564 cr = (constant_classref *) pr->ref;
566 /* get the fieldinfo */
568 if (!(c = resolve_classref_eager(cr)))
571 PATCH_BACK_ORIGINAL_MCODE;
573 /* if we show disassembly, we have to skip the nop's */
576 ra = ra + PATCHER_CALL_SIZE;
578 /* patch super class index */
580 *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
581 /* *((s4 *) (ra + 5 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) - */
582 /* c->index * sizeof(methodptr*)) & 0x0000ffff); */
583 *((s4 *) (ra + 6 * 4)) |=
584 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
585 c->index * sizeof(methodptr*)) & 0x0000ffff);
587 /* synchronize instruction cache */
589 md_icacheflush(ra + 2 * 4, 5 * 4);
595 /* patcher_instanceof_interface ************************************************
599 <patched call position>
601 8c79001c lw t9,28(v1)
602 27390000 addiu t9,t9,0
603 1b200082 blez t9,zero,0x000000001051843c
607 *******************************************************************************/
609 bool patcher_instanceof_interface(patchref_t *pr)
612 constant_classref *cr;
615 /* get stuff from the stack */
618 cr = (constant_classref *) pr->ref;
620 /* get the fieldinfo */
622 if (!(c = resolve_classref_eager(cr)))
625 PATCH_BACK_ORIGINAL_MCODE;
627 /* if we show disassembly, we have to skip the nop's */
630 ra = ra + PATCHER_CALL_SIZE;
632 /* patch super class index */
634 *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
635 *((s4 *) (ra + 5 * 4)) |=
636 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
637 c->index * sizeof(methodptr*)) & 0x0000ffff);
639 /* synchronize instruction cache */
641 md_icacheflush(ra + 2 * 4, 4 * 4);
648 * These are local overrides for various environment variables in Emacs.
649 * Please do not remove this and leave it at the end of the file, where
650 * Emacs will automagically detect them.
651 * ---------------------------------------------------------------------
654 * indent-tabs-mode: t
658 * vim:noexpandtab:sw=4:ts=4: