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 8268 2007-08-07 13:24:43Z twisti $
37 #include "vm/jit/mips/codegen.h"
39 #include "mm/memory.h"
41 #include "native/native.h"
43 #include "vm/builtin.h"
44 #include "vm/exceptions.h"
45 #include "vm/initialize.h"
47 #include "vm/jit/asmpart.h"
48 #include "vm/jit/md.h"
49 #include "vm/jit/patcher-common.h"
51 #include "vmcore/class.h"
52 #include "vmcore/field.h"
53 #include "vmcore/options.h"
54 #include "vm/resolve.h"
55 #include "vmcore/references.h"
58 #define PATCH_BACK_ORIGINAL_MCODE \
59 *((u4 *) pr->mpc) = (u4) pr->mcode; \
60 md_icacheflush((u1 *) pr->mpc, PATCHER_CALL_SIZE);
63 /* patcher_initialize_class ****************************************************
65 Initalizes a given classinfo pointer. This function does not patch
68 *******************************************************************************/
70 bool patcher_initialize_class(patchref_t *pr)
74 /* get stuff from the stack */
76 c = (classinfo *) pr->ref;
78 /* check if the class is initialized */
80 if (!(c->state & CLASS_INITIALIZED))
81 if (!initialize_class(c))
84 PATCH_BACK_ORIGINAL_MCODE;
90 /* patcher_resolve_class *****************************************************
92 Initalizes a given classinfo pointer. This function does not patch
95 *******************************************************************************/
97 #ifdef ENABLE_VERIFIER
98 bool patcher_resolve_class(patchref_t *pr)
100 unresolved_class *uc;
102 /* get stuff from the stack */
104 uc = (unresolved_class *) pr->ref;
106 /* resolve the class and check subtype constraints */
108 if (!resolve_class_eager_no_access_check(uc))
111 PATCH_BACK_ORIGINAL_MCODE;
115 #endif /* ENABLE_VERIFIER */
118 /* patcher_get_putstatic *******************************************************
122 <patched call position>
123 dfc1ffb8 ld at,-72(s8)
126 *******************************************************************************/
128 bool patcher_get_putstatic(patchref_t *pr)
130 unresolved_field *uf;
134 /* get stuff from the stack */
136 uf = (unresolved_field *) pr->ref;
137 datap = (u1 *) pr->datap;
139 /* get the fieldinfo */
141 if (!(fi = resolve_field_eager(uf)))
144 /* check if the field's class is initialized */
146 if (!(fi->class->state & CLASS_INITIALIZED))
147 if (!initialize_class(fi->class))
150 PATCH_BACK_ORIGINAL_MCODE;
152 /* patch the field value's address */
154 *((intptr_t *) datap) = (intptr_t) fi->value;
156 /* synchronize data cache */
158 md_dcacheflush(datap, SIZEOF_VOID_P);
164 /* patcher_get_putfield ********************************************************
168 <patched call position>
169 8ee90020 lw a5,32(s7)
171 *******************************************************************************/
173 bool patcher_get_putfield(patchref_t *pr)
176 unresolved_field *uf;
179 /* get stuff from the stack */
182 uf = (unresolved_field *) pr->ref;
184 /* get the fieldinfo */
186 if (!(fi = resolve_field_eager(uf)))
189 PATCH_BACK_ORIGINAL_MCODE;
191 /* if we show disassembly, we have to skip the nop's */
194 ra = ra + PATCHER_CALL_SIZE;
196 #if SIZEOF_VOID_P == 4
197 if (IS_LNG_TYPE(fi->type)) {
198 # if WORDS_BIGENDIAN == 1
199 /* ATTENTION: order of these instructions depend on M_LLD_INTERN */
200 *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
201 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
203 /* ATTENTION: order of these instructions depend on M_LLD_INTERN */
204 *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
205 *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
210 *((u4 *) (ra + 0 * 4)) |= (s2) (fi->offset & 0x0000ffff);
212 /* synchronize instruction cache */
214 md_icacheflush(ra, 2 * 4);
220 /* patcher_resolve_classref_to_classinfo ***************************************
224 <patched call postition>
225 dfc4ff98 ld a0,-104(s8)
229 <patched call position>
230 dfc5ff90 ld a1,-112(s8)
232 dfd9ff88 ld t9,-120(s8)
238 <patched call position>
239 dfc5ffc0 ld a1,-64(s8)
240 dfd9ffb8 ld t9,-72(s8)
244 *******************************************************************************/
246 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
248 constant_classref *cr;
252 /* get stuff from the stack */
254 cr = (constant_classref *) pr->ref;
255 datap = (u1 *) pr->datap;
257 /* get the classinfo */
259 if (!(c = resolve_classref_eager(cr)))
262 PATCH_BACK_ORIGINAL_MCODE;
264 /* patch the classinfo pointer */
266 *((intptr_t *) datap) = (intptr_t) c;
268 /* synchronize data cache */
270 md_dcacheflush(datap, SIZEOF_VOID_P);
276 /* patcher_resolve_classref_to_vftbl *******************************************
281 <patched call position>
283 dfd9ff18 ld t9,-232(s8)
285 *******************************************************************************/
287 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
289 constant_classref *cr;
293 /* get stuff from the stack */
295 cr = (constant_classref *) pr->ref;
296 datap = (u1 *) pr->datap;
298 /* get the fieldinfo */
300 if (!(c = resolve_classref_eager(cr)))
303 PATCH_BACK_ORIGINAL_MCODE;
305 /* patch super class' vftbl */
307 *((intptr_t *) datap) = (intptr_t) c->vftbl;
309 /* synchronize data cache */
311 md_dcacheflush(datap, SIZEOF_VOID_P);
317 /* patcher_resolve_classref_to_flags *******************************************
319 CHECKCAST/INSTANCEOF:
321 <patched call position>
322 8fc3ff24 lw v1,-220(s8)
323 30630200 andi v1,v1,512
324 1060000d beq v1,zero,0x000000001051824c
327 *******************************************************************************/
329 bool patcher_resolve_classref_to_flags(patchref_t *pr)
331 constant_classref *cr;
335 /* get stuff from the stack */
337 cr = (constant_classref *) pr->ref;
338 datap = (u1 *) pr->datap;
340 /* get the fieldinfo */
342 if (!(c = resolve_classref_eager(cr)))
345 PATCH_BACK_ORIGINAL_MCODE;
347 /* patch class flags */
349 *((int32_t *) datap) = (int32_t) c->flags;
351 /* synchronize data cache */
353 md_dcacheflush(datap, sizeof(int32_t));
359 /* patcher_resolve_native ******************************************************
363 *******************************************************************************/
365 #if !defined(WITH_STATIC_CLASSPATH)
366 bool patcher_resolve_native_function(patchref_t *pr)
372 /* get stuff from the stack */
374 m = (methodinfo *) pr->ref;
375 datap = (u1 *) pr->datap;
377 /* resolve native function */
379 if (!(f = native_resolve_function(m)))
382 PATCH_BACK_ORIGINAL_MCODE;
384 /* patch native function pointer */
386 *((ptrint *) datap) = (ptrint) f;
388 /* synchronize data cache */
390 md_dcacheflush(datap, SIZEOF_VOID_P);
394 #endif /* !defined(WITH_STATIC_CLASSPATH) */
397 /* patcher_invokestatic_special ************************************************
401 <patched call position>
402 dfdeffc0 ld s8,-64(s8)
406 ******************************************************************************/
408 bool patcher_invokestatic_special(patchref_t *pr)
410 unresolved_method *um;
414 /* get stuff from the stack */
416 um = (unresolved_method *) pr->ref;
417 datap = (u1 *) pr->datap;
419 /* get the fieldinfo */
421 if (!(m = resolve_method_eager(um)))
424 PATCH_BACK_ORIGINAL_MCODE;
426 /* patch stubroutine */
428 *((ptrint *) datap) = (ptrint) m->stubroutine;
430 /* synchronize data cache */
432 md_dcacheflush(datap, SIZEOF_VOID_P);
438 /* patcher_invokevirtual *******************************************************
442 <patched call position>
444 df3e0040 ld s8,64(t9)
448 *******************************************************************************/
450 bool patcher_invokevirtual(patchref_t *pr)
453 unresolved_method *um;
456 /* get stuff from the stack */
459 um = (unresolved_method *) pr->ref;
461 /* get the fieldinfo */
463 if (!(m = resolve_method_eager(um)))
466 PATCH_BACK_ORIGINAL_MCODE;
468 /* if we show disassembly, we have to skip the nop's */
471 ra = ra + PATCHER_CALL_SIZE;
473 /* patch vftbl index */
475 *((s4 *) (ra + 1 * 4)) |=
476 (s4) ((OFFSET(vftbl_t, table[0]) +
477 sizeof(methodptr) * m->vftblindex) & 0x0000ffff);
479 /* synchronize instruction cache */
481 md_icacheflush(ra + 1 * 4, 1 * 4);
487 /* patcher_invokeinterface *****************************************************
491 <patched call position>
493 df39ffa0 ld t9,-96(t9)
494 df3e0018 ld s8,24(t9)
498 *******************************************************************************/
500 bool patcher_invokeinterface(patchref_t *pr)
503 unresolved_method *um;
506 /* get stuff from the stack */
509 um = (unresolved_method *) pr->ref;
511 /* get the fieldinfo */
513 if (!(m = resolve_method_eager(um)))
516 PATCH_BACK_ORIGINAL_MCODE;
518 /* if we show disassembly, we have to skip the nop's */
521 ra = ra + PATCHER_CALL_SIZE;
523 /* patch interfacetable index */
525 *((s4 *) (ra + 1 * 4)) |=
526 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
527 sizeof(methodptr*) * m->class->index) & 0x0000ffff);
529 /* patch method offset */
531 *((s4 *) (ra + 2 * 4)) |=
532 (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x0000ffff);
534 /* synchronize instruction cache */
536 md_icacheflush(ra + 1 * 4, 2 * 4);
542 /* patcher_checkcast_interface *************************************************
546 <patched call position>
548 8c79001c lw t9,28(v1)
549 27390000 addiu t9,t9,0
550 1b200082 blez t9,zero,0x000000001051843c
554 *******************************************************************************/
556 bool patcher_checkcast_interface(patchref_t *pr)
559 constant_classref *cr;
562 /* get stuff from the stack */
565 cr = (constant_classref *) pr->ref;
567 /* get the fieldinfo */
569 if (!(c = resolve_classref_eager(cr)))
572 PATCH_BACK_ORIGINAL_MCODE;
574 /* if we show disassembly, we have to skip the nop's */
577 ra = ra + PATCHER_CALL_SIZE;
579 /* patch super class index */
581 *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
582 /* *((s4 *) (ra + 5 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) - */
583 /* c->index * sizeof(methodptr*)) & 0x0000ffff); */
584 *((s4 *) (ra + 6 * 4)) |=
585 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
586 c->index * sizeof(methodptr*)) & 0x0000ffff);
588 /* synchronize instruction cache */
590 md_icacheflush(ra + 2 * 4, 5 * 4);
596 /* patcher_instanceof_interface ************************************************
600 <patched call position>
602 8c79001c lw t9,28(v1)
603 27390000 addiu t9,t9,0
604 1b200082 blez t9,zero,0x000000001051843c
608 *******************************************************************************/
610 bool patcher_instanceof_interface(patchref_t *pr)
613 constant_classref *cr;
616 /* get stuff from the stack */
619 cr = (constant_classref *) pr->ref;
621 /* get the fieldinfo */
623 if (!(c = resolve_classref_eager(cr)))
626 PATCH_BACK_ORIGINAL_MCODE;
628 /* if we show disassembly, we have to skip the nop's */
631 ra = ra + PATCHER_CALL_SIZE;
633 /* patch super class index */
635 *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
636 *((s4 *) (ra + 5 * 4)) |=
637 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
638 c->index * sizeof(methodptr*)) & 0x0000ffff);
640 /* synchronize instruction cache */
642 md_icacheflush(ra + 2 * 4, 4 * 4);
649 * These are local overrides for various environment variables in Emacs.
650 * Please do not remove this and leave it at the end of the file, where
651 * Emacs will automagically detect them.
652 * ---------------------------------------------------------------------
655 * indent-tabs-mode: t
659 * vim:noexpandtab:sw=4:ts=4: