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
35 #include "mm/memory.h"
37 #include "vm/jit/sparc64/codegen.h"
38 #include "vm/jit/sparc64/md.h"
39 #include "vm/jit/sparc64/md-abi.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/methodheader.h"
49 #include "vm/jit/stacktrace.h"
51 #include "vmcore/class.h"
52 #include "vmcore/field.h"
53 #include "vmcore/options.h"
54 #include "vmcore/references.h"
55 #include "vm/resolve.h"
57 #include "vm/jit/sparc64/solaris/macro_rename.h"
60 /* patcher_wrapper *************************************************************
62 Wrapper for all patchers. It also creates the stackframe info
65 If the return value of the patcher function is false, it gets the
66 exception object, clears the exception pointer and returns the
69 *******************************************************************************/
71 java_object_t *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
77 #if SIZEOF_VOID_P == 8
86 /* define the patcher function */
88 bool (*patcher_function)(u1 *);
92 /* get stuff from the stack */
94 xpc = (u1 *) *((ptrint *) (sp + 5 * 8));
95 o = (java_object_t *) *((ptrint *) (sp + 4 * 8));
96 f = (functionptr) *((ptrint *) (sp + 0 * 8));
98 /* store PV into the patcher function position */
100 *((ptrint *) (sp + 0 * 8)) = (ptrint) pv;
102 /* cast the passed function to a patcher function */
104 patcher_function = (bool (*)(u1 *)) (ptrint) f;
106 /* enter a monitor on the patching position */
108 PATCHER_MONITORENTER;
110 /* the (data) sp points directly to the patcher fields */
111 /* calculate the real sp of the current java function considering the WINSAVE regs */
113 javasp = sp - JITSTACK_CNT * 8 - BIAS;
115 /* create the stackframeinfo */
117 printf("patcher opening sfi for xpc=%p\n", xpc);
119 stacktrace_stackframeinfo_add(&sfi, pv, javasp, ra, xpc);
121 /* call the proper patcher function */
123 result = (patcher_function)(sp);
125 /* remove the stackframeinfo */
127 stacktrace_stackframeinfo_remove(&sfi);
128 printf("patcher closing sfi for xpc=%p\n", xpc);
130 /* check for return value and exit accordingly */
132 if (result == false) {
133 e = exceptions_get_and_clear_exception();
140 /* patch back original (potentially patched) code */
142 #if SIZEOF_VOID_P == 8
143 mcode = *((u8 *) (sp + 3 * 8));
145 *((u4 *) (xpc + 0 * 4)) = mcode >> 32;
146 *((u4 *) (xpc + 1 * 4)) = mcode;
148 mcode[0] = *((u4 *) (sp + 3 * 8));
149 mcode[1] = *((u4 *) (sp + 3 * 8 + 4));
151 *((u4 *) (xpc + 0 * 4)) = mcode[0];
152 *((u4 *) (xpc + 1 * 4)) = mcode[1];
156 /* synchronize instruction cache */
158 md_icacheflush(xpc, PATCHER_CALL_SIZE);
160 PATCHER_MARK_PATCHED_MONITOREXIT;
166 /* patcher_get_putstatic *******************************************************
170 <patched call position>
174 *******************************************************************************/
176 bool patcher_get_putstatic(u1 *sp)
178 unresolved_field *uf;
183 /* get stuff from the stack */
185 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
186 disp = *((s4 *) (sp + 1 * 8));
187 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
189 /* get the fieldinfo */
191 if (!(fi = resolve_field_eager(uf)))
194 /* check if the field's class is initialized */
196 if (!(fi->class->state & CLASS_INITIALIZED))
197 if (!initialize_class(fi->class))
200 /* patch the field value's address */
202 *((intptr_t *) (pv + disp)) = (intptr_t) fi->value;
204 /* synchronize data cache */
206 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
212 /* patcher_get_putfield ********************************************************
216 <patched call position>
217 8ee90020 lw a5,32(s7)
219 *******************************************************************************/
221 bool patcher_get_putfield(u1 *sp)
224 unresolved_field *uf;
228 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
229 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
231 /* get the fieldinfo */
233 if (!(fi = resolve_field_eager(uf)))
236 /* if we show disassembly, we have to skip the nop's */
239 /* patch the field's offset into the instruction */
241 *((u4 *) (ra + 2 * 4)) |= (s2) (fi->offset & 0x00001fff);
243 /* synchronize instruction cache */
245 md_icacheflush(ra + 2 * 4, 1 * 4);
248 /* otherwise store the patched instruction on the stack */
250 *((u4 *) (sp + 3 * 8)) |= (s2) (fi->offset & 0x00001fff);
257 /* patcher_aconst **************************************************************
261 <patched call postition>
264 *******************************************************************************/
266 bool patcher_aconst(u1 *sp)
268 constant_classref *cr;
273 /* get stuff from the stack */
275 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
276 disp = *((s4 *) (sp + 1 * 8));
277 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
279 /* get the classinfo */
281 if (!(c = resolve_classref_eager(cr)))
284 /* patch the classinfo pointer */
286 *((ptrint *) (pv + disp)) = (ptrint) c;
288 /* synchronize data cache */
290 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
296 /* patcher_builtin_multianewarray **********************************************
300 <patched call position>
301 dfc5ff90 ld a1,-112(s8)
303 dfd9ff88 ld t9,-120(s8)
307 *******************************************************************************/
309 bool patcher_builtin_multianewarray(u1 *sp)
311 constant_classref *cr;
316 /* get stuff from the stack */
318 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
319 disp = *((s4 *) (sp + 1 * 8));
320 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
322 /* get the classinfo */
324 if (!(c = resolve_classref_eager(cr)))
327 /* patch the classinfo pointer */
329 *((ptrint *) (pv + disp)) = (ptrint) c;
331 /* synchronize data cache */
333 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
339 /* patcher_builtin_arraycheckcast **********************************************
343 <patched call position>
344 dfc5ffc0 ld a1,-64(s8)
345 dfd9ffb8 ld t9,-72(s8)
349 *******************************************************************************/
351 bool patcher_builtin_arraycheckcast(u1 *sp)
353 constant_classref *cr;
358 /* get stuff from the stack */
360 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
361 disp = *((s4 *) (sp + 1 * 8));
362 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
364 /* get the classinfo */
366 if (!(c = resolve_classref_eager(cr)))
369 /* patch the classinfo pointer */
371 *((ptrint *) (pv + disp)) = (ptrint) c;
373 /* synchronize data cache */
375 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
381 /* patcher_invokestatic_special ************************************************
385 <patched call position>
386 dfdeffc0 ld s8,-64(s8)
390 ******************************************************************************/
392 bool patcher_invokestatic_special(u1 *sp)
394 unresolved_method *um;
399 /* get stuff from the stack */
401 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
402 disp = *((s4 *) (sp + 1 * 8));
403 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
405 /* get the fieldinfo */
407 if (!(m = resolve_method_eager(um)))
410 /* patch stubroutine */
412 *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
414 /* synchronize data cache */
416 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
422 /* patcher_invokevirtual *******************************************************
426 <patched call position>
432 *******************************************************************************/
434 bool patcher_invokevirtual(u1 *sp)
437 unresolved_method *um;
440 /* get stuff from the stack */
442 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
443 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
445 /* get the fieldinfo */
447 if (!(m = resolve_method_eager(um)))
450 /* if we show disassembly, we have to skip the nop's */
453 ra = ra + PATCHER_CALL_SIZE;
455 /* patch vftbl index */
457 *((s4 *) (ra + 1 * 4)) |=
458 (s4) ((OFFSET(vftbl_t, table[0]) +
459 sizeof(methodptr) * m->vftblindex) & 0x00001fff);
461 /* synchronize instruction cache */
463 md_icacheflush(ra + 1 * 4, 1 * 4);
466 /* patch vftbl index */
468 *((s4 *) (sp + 3 * 8 + 4)) |=
469 (s4) ((OFFSET(vftbl_t, table[0]) +
470 sizeof(methodptr) * m->vftblindex) & 0x00001fff);
477 /* patcher_invokeinterface *****************************************************
481 <patched call position>
483 df39ffa0 ld t9,-96(t9)
484 df3e0018 ld s8,24(t9)
488 *******************************************************************************/
490 bool patcher_invokeinterface(u1 *sp)
493 unresolved_method *um;
496 /* get stuff from the stack */
498 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
499 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
501 /* get the fieldinfo */
503 if (!(m = resolve_method_eager(um)))
506 /* if we show disassembly, we have to skip the nop's */
509 ra = ra + PATCHER_CALL_SIZE;
511 /* patch interfacetable index */
513 *((s4 *) (ra + 1 * 4)) |=
514 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
515 sizeof(methodptr*) * m->class->index) & 0x00001fff);
517 /* patch method offset */
519 *((s4 *) (ra + 2 * 4)) |=
520 (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x00001fff);
522 /* synchronize instruction cache */
524 md_icacheflush(ra + 1 * 4, 2 * 4);
527 /* patch interfacetable index */
529 *((s4 *) (sp + 3 * 8 + 4)) |=
530 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
531 sizeof(methodptr*) * m->class->index) & 0x00001fff);
533 /* patch method offset */
535 *((s4 *) (ra + 2 * 4)) |=
536 (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x00001fff);
538 /* synchronize instruction cache */
540 md_icacheflush(ra + 2 * 4, 1 * 4);
547 /* patcher_checkcast_instanceof_flags ******************************************
551 <patched call position>
552 8fc3ff24 lw v1,-220(s8)
553 30630200 andi v1,v1,512
554 1060000d beq v1,zero,0x000000001051824c
557 *******************************************************************************/
559 bool patcher_checkcast_instanceof_flags(u1 *sp)
561 constant_classref *cr;
566 /* get stuff from the stack */
568 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
569 disp = *((s4 *) (sp + 1 * 8));
570 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
572 /* get the fieldinfo */
574 if (!(c = resolve_classref_eager(cr)))
577 /* patch class flags */
579 *((s4 *) (pv + disp)) = (s4) c->flags;
581 /* synchronize data cache */
583 md_dcacheflush(pv + disp, sizeof(s4));
589 /* patcher_checkcast_interface **************************************
593 <patched call position>
595 8c79001c lw t9,28(v1)
596 27390000 addiu t9,t9,0
597 1b200082 blez t9,zero,0x000000001051843c
601 *******************************************************************************/
603 bool patcher_checkcast_interface(u1 *sp)
606 constant_classref *cr;
609 /* get stuff from the stack */
611 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
612 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
614 /* get the fieldinfo */
616 if (!(c = resolve_classref_eager(cr)))
619 /* if we show disassembly, we have to skip the nop's */
622 ra = ra + PATCHER_CALL_SIZE;
624 /* patch super class index */
626 *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x00001fff);
628 *((s4 *) (ra + (3 + EXCEPTION_CHECK_INSTRUCTIONS) * 4)) |=
629 (s4) ((OFFSET(vftbl_t, interfacetable[0])
630 - c->index * sizeof(methodptr*)) & 0x00001fff);
632 /* synchronize instruction cache */
635 md_icacheflush(ra - 2 * 4, (6 + EXCEPTION_CHECK_INSTRUCTIONS) * 4);
637 md_icacheflush(ra, (4 + EXCEPTION_CHECK_INSTRUCTIONS) * 4);
642 /* patcher_instanceof_interface ************************************************
646 <patched call position>
648 8c79001c lw t9,28(v1)
649 27390000 addiu t9,t9,0
650 1b200082 blez t9,zero,0x000000001051843c
654 *******************************************************************************/
656 bool patcher_instanceof_interface(u1 *sp)
659 constant_classref *cr;
662 /* get stuff from the stack */
664 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
665 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
667 /* get the fieldinfo */
669 if (!(c = resolve_classref_eager(cr)))
672 /* if we show disassembly, we have to skip the nop's */
675 ra = ra + PATCHER_CALL_SIZE;
677 /* patch super class index */
679 *((s4 *) (ra + 2 * 4)) |= (s4) ((c->index) & 0x00001fff);
680 *((s4 *) (ra + 5 * 4)) |=
681 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
682 c->index * sizeof(methodptr*)) & 0x00001fff);
684 /* synchronize instruction cache */
687 md_icacheflush(ra - PATCHER_CALL_SIZE * 4, 8 * 4);
689 md_icacheflush(ra, 6 * 4);
695 /* patcher_checkcast_instanceof_class ******************************************
699 <patched call position>
701 dfd9ff18 ld t9,-232(s8)
703 *******************************************************************************/
705 bool patcher_checkcast_instanceof_class(u1 *sp)
707 constant_classref *cr;
712 /* get stuff from the stack */
714 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
715 disp = *((s4 *) (sp + 1 * 8));
716 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
718 /* get the fieldinfo */
720 if (!(c = resolve_classref_eager(cr)))
723 /* patch super class' vftbl */
725 *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
727 /* synchronize data cache */
729 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
735 /* patcher_clinit **************************************************************
737 No special machine code.
739 *******************************************************************************/
741 bool patcher_clinit(u1 *sp)
745 /* get stuff from the stack */
747 c = (classinfo *) *((ptrint *) (sp + 2 * 8));
749 /* check if the class is initialized */
751 if (!(c->state & CLASS_INITIALIZED))
752 if (!initialize_class(c))
759 /* patcher_athrow_areturn ******************************************************
763 <patched call position>
765 *******************************************************************************/
767 #ifdef ENABLE_VERIFIER
768 bool patcher_athrow_areturn(u1 *sp)
770 unresolved_class *uc;
772 /* get stuff from the stack */
774 uc = (unresolved_class *) *((ptrint *) (sp + 2 * 8));
776 /* resolve the class and check subtype constraints */
778 if (!resolve_class_eager_no_access_check(uc))
783 #endif /* ENABLE_VERIFIER */
786 /* patcher_resolve_native ******************************************************
790 *******************************************************************************/
792 bool patcher_resolve_native(u1 *sp)
799 /* get stuff from the stack */
801 m = (methodinfo *) *((ptrint *) (sp + 2 * 8));
802 disp = *((s4 *) (sp + 1 * 8));
803 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
805 /* return address on SPARC is address of jump, therefore correct */
807 /* resolve native function */
809 if (!(f = native_resolve_function(m)))
812 /* patch native function pointer */
814 *((ptrint *) (pv + disp)) = (ptrint) f;
816 /* synchronize data cache */
818 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
825 * These are local overrides for various environment variables in Emacs.
826 * Please do not remove this and leave it at the end of the file, where
827 * Emacs will automagically detect them.
828 * ---------------------------------------------------------------------
831 * indent-tabs-mode: t
835 * vim:noexpandtab:sw=4:ts=4: