1 /* src/vm/jit/mips/patcher.c - SPARC code patching functions
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
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 5164 2006-07-19 15:54:01Z twisti $
36 #include "mm/memory.h"
38 #include "vm/jit/sparc64/md-abi.h"
39 #include "vm/jit/sparc64/codegen.h"
41 #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/patcher.h"
48 #include "vm/jit/md.h"
49 #include "vm/jit/methodheader.h"
50 #include "vm/jit/stacktrace.h"
52 #include "vmcore/class.h"
53 #include "vmcore/field.h"
54 #include "vmcore/options.h"
55 #include "vmcore/references.h"
56 #include "vm/resolve.h"
59 /* patcher_wrapper *************************************************************
61 Wrapper for all patchers. It also creates the stackframe info
64 If the return value of the patcher function is false, it gets the
65 exception object, clears the exception pointer and returns the
68 *******************************************************************************/
70 java_objectheader *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
76 #if SIZEOF_VOID_P == 8
85 /* define the patcher function */
87 bool (*patcher_function)(u1 *);
91 /* get stuff from the stack */
93 xpc = (u1 *) *((ptrint *) (sp + 5 * 8));
94 o = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
95 f = (functionptr) *((ptrint *) (sp + 0 * 8));
97 /* store PV into the patcher function position */
99 *((ptrint *) (sp + 0 * 8)) = (ptrint) pv;
101 /* cast the passed function to a patcher function */
103 patcher_function = (bool (*)(u1 *)) (ptrint) f;
105 /* enter a monitor on the patching position */
107 PATCHER_MONITORENTER;
109 /* the (data) sp points directly to the patcher fields */
110 /* calculate the real sp of the current java function considering the WINSAVE regs */
112 javasp = sp - JITSTACK_CNT * 8 - BIAS;
114 /* create the stackframeinfo */
116 stacktrace_create_extern_stackframeinfo(&sfi, pv, javasp, ra, xpc);
118 /* call the proper patcher function */
120 result = (patcher_function)(sp);
122 /* remove the stackframeinfo */
124 stacktrace_remove_stackframeinfo(&sfi);
126 /* check for return value and exit accordingly */
128 if (result == false) {
129 e = exceptions_get_and_clear_exception();
136 /* patch back original (potentially patched) code */
138 #if SIZEOF_VOID_P == 8
139 mcode = *((u8 *) (sp + 3 * 8));
141 *((u4 *) (xpc + 0 * 4)) = mcode >> 32;
142 *((u4 *) (xpc + 1 * 4)) = mcode;
144 mcode[0] = *((u4 *) (sp + 3 * 8));
145 mcode[1] = *((u4 *) (sp + 3 * 8 + 4));
147 *((u4 *) (xpc + 0 * 4)) = mcode[0];
148 *((u4 *) (xpc + 1 * 4)) = mcode[1];
152 /* synchronize instruction cache */
154 md_icacheflush(xpc, PATCHER_CALL_SIZE);
156 PATCHER_MARK_PATCHED_MONITOREXIT;
162 /* patcher_get_putstatic *******************************************************
166 <patched call position>
170 *******************************************************************************/
172 bool patcher_get_putstatic(u1 *sp)
174 unresolved_field *uf;
179 /* get stuff from the stack */
181 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
182 disp = *((s4 *) (sp + 1 * 8));
183 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
185 /* get the fieldinfo */
187 if (!(fi = resolve_field_eager(uf)))
190 /* check if the field's class is initialized */
192 if (!(fi->class->state & CLASS_INITIALIZED))
193 if (!initialize_class(fi->class))
196 /* patch the field value's address */
198 *((ptrint *) (pv + disp)) = (ptrint) &(fi->value);
200 /* synchronize data cache */
202 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
208 /* patcher_get_putfield ********************************************************
212 <patched call position>
213 8ee90020 lw a5,32(s7)
215 *******************************************************************************/
217 bool patcher_get_putfield(u1 *sp)
220 unresolved_field *uf;
224 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
225 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
227 /* get the fieldinfo */
229 if (!(fi = resolve_field_eager(uf)))
232 /* if we show disassembly, we have to skip the nop's */
235 /* patch the field's offset into the instruction */
237 *((u4 *) (ra + 2 * 4)) |= (s2) (fi->offset & 0x00001fff);
239 /* synchronize instruction cache */
241 md_icacheflush(ra + 2 * 4, 1 * 4);
244 /* otherwise store the patched instruction on the stack */
246 *((u4 *) (sp + 3 * 8)) |= (s2) (fi->offset & 0x00001fff);
253 /* patcher_aconst **************************************************************
257 <patched call postition>
260 *******************************************************************************/
262 bool patcher_aconst(u1 *sp)
264 constant_classref *cr;
269 /* get stuff from the stack */
271 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
272 disp = *((s4 *) (sp + 1 * 8));
273 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
275 /* get the classinfo */
277 if (!(c = resolve_classref_eager(cr)))
280 /* patch the classinfo pointer */
282 *((ptrint *) (pv + disp)) = (ptrint) c;
284 /* synchronize data cache */
286 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
292 /* patcher_builtin_multianewarray **********************************************
296 <patched call position>
297 dfc5ff90 ld a1,-112(s8)
299 dfd9ff88 ld t9,-120(s8)
303 *******************************************************************************/
305 bool patcher_builtin_multianewarray(u1 *sp)
307 constant_classref *cr;
312 /* get stuff from the stack */
314 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
315 disp = *((s4 *) (sp + 1 * 8));
316 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
318 /* get the classinfo */
320 if (!(c = resolve_classref_eager(cr)))
323 /* patch the classinfo pointer */
325 *((ptrint *) (pv + disp)) = (ptrint) c;
327 /* synchronize data cache */
329 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
335 /* patcher_builtin_arraycheckcast **********************************************
339 <patched call position>
340 dfc5ffc0 ld a1,-64(s8)
341 dfd9ffb8 ld t9,-72(s8)
345 *******************************************************************************/
347 bool patcher_builtin_arraycheckcast(u1 *sp)
349 constant_classref *cr;
354 /* get stuff from the stack */
356 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
357 disp = *((s4 *) (sp + 1 * 8));
358 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
360 /* get the classinfo */
362 if (!(c = resolve_classref_eager(cr)))
365 /* patch the classinfo pointer */
367 *((ptrint *) (pv + disp)) = (ptrint) c;
369 /* synchronize data cache */
371 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
377 /* patcher_invokestatic_special ************************************************
381 <patched call position>
382 dfdeffc0 ld s8,-64(s8)
386 ******************************************************************************/
388 bool patcher_invokestatic_special(u1 *sp)
390 unresolved_method *um;
395 /* get stuff from the stack */
397 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
398 disp = *((s4 *) (sp + 1 * 8));
399 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
401 /* get the fieldinfo */
403 if (!(m = resolve_method_eager(um)))
406 /* patch stubroutine */
408 *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
410 /* synchronize data cache */
412 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
418 /* patcher_invokevirtual *******************************************************
422 <patched call position>
428 *******************************************************************************/
430 bool patcher_invokevirtual(u1 *sp)
433 unresolved_method *um;
436 /* get stuff from the stack */
438 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
439 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
441 /* get the fieldinfo */
443 if (!(m = resolve_method_eager(um)))
446 /* if we show disassembly, we have to skip the nop's */
449 ra = ra + PATCHER_CALL_SIZE;
451 /* patch vftbl index */
453 *((s4 *) (ra + 1 * 4)) |=
454 (s4) ((OFFSET(vftbl_t, table[0]) +
455 sizeof(methodptr) * m->vftblindex) & 0x00001fff);
457 /* synchronize instruction cache */
459 md_icacheflush(ra + 1 * 4, 1 * 4);
462 /* patch vftbl index */
464 *((s4 *) (sp + 3 * 8 + 4)) |=
465 (s4) ((OFFSET(vftbl_t, table[0]) +
466 sizeof(methodptr) * m->vftblindex) & 0x00001fff);
473 /* patcher_invokeinterface *****************************************************
477 <patched call position>
479 df39ffa0 ld t9,-96(t9)
480 df3e0018 ld s8,24(t9)
484 *******************************************************************************/
486 bool patcher_invokeinterface(u1 *sp)
489 unresolved_method *um;
492 /* get stuff from the stack */
494 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
495 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
497 /* get the fieldinfo */
499 if (!(m = resolve_method_eager(um)))
502 /* if we show disassembly, we have to skip the nop's */
505 ra = ra + PATCHER_CALL_SIZE;
507 /* patch interfacetable index */
509 *((s4 *) (ra + 1 * 4)) |=
510 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
511 sizeof(methodptr*) * m->class->index) & 0x00001fff);
513 /* patch method offset */
515 *((s4 *) (ra + 2 * 4)) |=
516 (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x00001fff);
518 /* synchronize instruction cache */
520 md_icacheflush(ra + 1 * 4, 2 * 4);
523 /* patch interfacetable index */
525 *((s4 *) (sp + 3 * 8 + 4)) |=
526 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
527 sizeof(methodptr*) * m->class->index) & 0x00001fff);
529 /* patch method offset */
531 *((s4 *) (ra + 2 * 4)) |=
532 (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x00001fff);
534 /* synchronize instruction cache */
536 md_icacheflush(ra + 2 * 4, 1 * 4);
543 /* patcher_checkcast_instanceof_flags ******************************************
547 <patched call position>
548 8fc3ff24 lw v1,-220(s8)
549 30630200 andi v1,v1,512
550 1060000d beq v1,zero,0x000000001051824c
553 *******************************************************************************/
555 bool patcher_checkcast_instanceof_flags(u1 *sp)
557 constant_classref *cr;
562 /* get stuff from the stack */
564 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
565 disp = *((s4 *) (sp + 1 * 8));
566 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
568 /* get the fieldinfo */
570 if (!(c = resolve_classref_eager(cr)))
573 /* patch class flags */
575 *((s4 *) (pv + disp)) = (s4) c->flags;
577 /* synchronize data cache */
579 md_dcacheflush(pv + disp, sizeof(s4));
585 /* patcher_checkcast_interface **************************************
589 <patched call position>
591 8c79001c lw t9,28(v1)
592 27390000 addiu t9,t9,0
593 1b200082 blez t9,zero,0x000000001051843c
597 *******************************************************************************/
599 bool patcher_checkcast_interface(u1 *sp)
602 constant_classref *cr;
605 /* get stuff from the stack */
607 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
608 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
610 /* get the fieldinfo */
612 if (!(c = resolve_classref_eager(cr)))
615 /* if we show disassembly, we have to skip the nop's */
618 ra = ra + PATCHER_CALL_SIZE;
621 /* if we show disassembly, we have to skip the nop's */
624 ra = ra + PATCHER_CALL_SIZE;
626 /* patch super class index */
628 *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x00001fff);
630 *((s4 *) (ra + 5 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
631 c->index * sizeof(methodptr*)) & 0x00001fff);
633 /* synchronize instruction cache */
636 md_icacheflush(ra - 2 * 4, 8 * 4);
638 md_icacheflush(ra, 6 * 4);
643 /* patcher_instanceof_interface ************************************************
647 <patched call position>
649 8c79001c lw t9,28(v1)
650 27390000 addiu t9,t9,0
651 1b200082 blez t9,zero,0x000000001051843c
655 *******************************************************************************/
657 bool patcher_instanceof_interface(u1 *sp)
660 constant_classref *cr;
663 assert(0); /* test this one !!! */
665 /* get stuff from the stack */
667 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
668 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
670 /* get the fieldinfo */
672 if (!(c = resolve_classref_eager(cr)))
675 /* if we show disassembly, we have to skip the nop's */
678 ra = ra + PATCHER_CALL_SIZE;
680 /* patch super class index */
682 *((s4 *) (ra + 2 * 4)) |= (s4) ((c->index) & 0x00001fff);
683 *((s4 *) (ra + 5 * 4)) |=
684 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
685 c->index * sizeof(methodptr*)) & 0x00001fff);
687 /* synchronize instruction cache */
690 md_icacheflush(ra - PATCHER_CALL_SIZE * 4, 8 * 4);
692 md_icacheflush(ra, 6 * 4);
698 /* patcher_checkcast_instanceof_class ******************************************
702 <patched call position>
704 dfd9ff18 ld t9,-232(s8)
706 *******************************************************************************/
708 bool patcher_checkcast_instanceof_class(u1 *sp)
710 constant_classref *cr;
715 /* get stuff from the stack */
717 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
718 disp = *((s4 *) (sp + 1 * 8));
719 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
721 /* get the fieldinfo */
723 if (!(c = resolve_classref_eager(cr)))
726 /* patch super class' vftbl */
728 *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
730 /* synchronize data cache */
732 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
738 /* patcher_clinit **************************************************************
740 No special machine code.
742 *******************************************************************************/
744 bool patcher_clinit(u1 *sp)
748 /* get stuff from the stack */
750 c = (classinfo *) *((ptrint *) (sp + 2 * 8));
752 /* check if the class is initialized */
754 if (!(c->state & CLASS_INITIALIZED))
755 if (!initialize_class(c))
762 /* patcher_athrow_areturn ******************************************************
766 <patched call position>
768 *******************************************************************************/
770 #ifdef ENABLE_VERIFIER
771 bool patcher_athrow_areturn(u1 *sp)
773 unresolved_class *uc;
775 /* get stuff from the stack */
777 uc = (unresolved_class *) *((ptrint *) (sp + 2 * 8));
779 /* resolve the class and check subtype constraints */
781 if (!resolve_class_eager_no_access_check(uc))
786 #endif /* ENABLE_VERIFIER */
789 /* patcher_resolve_native ******************************************************
793 *******************************************************************************/
795 #if !defined(WITH_STATIC_CLASSPATH)
796 bool patcher_resolve_native(u1 *sp)
803 /* get stuff from the stack */
805 m = (methodinfo *) *((ptrint *) (sp + 2 * 8));
806 disp = *((s4 *) (sp + 1 * 8));
807 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
809 /* return address on SPARC is address of jump, therefore correct */
811 /* resolve native function */
813 if (!(f = native_resolve_function(m)))
816 /* patch native function pointer */
818 *((ptrint *) (pv + disp)) = (ptrint) f;
820 /* synchronize data cache */
822 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
826 #endif /* !defined(WITH_STATIC_CLASSPATH) */
830 * These are local overrides for various environment variables in Emacs.
831 * Please do not remove this and leave it at the end of the file, where
832 * Emacs will automagically detect them.
833 * ---------------------------------------------------------------------
836 * indent-tabs-mode: t
840 * vim:noexpandtab:sw=4:ts=4: