1 /* src/vm/jit/mips/patcher.c - SPARC code patching functions
3 Copyright (C) 1996-2005, 2006, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
33 #include "mm/memory.h"
35 #include "vm/jit/sparc64/codegen.h"
36 #include "vm/jit/sparc64/md.h"
37 #include "vm/jit/sparc64/md-abi.h"
39 #include "native/native.h"
41 #include "vm/builtin.h"
43 #include "vm/exceptions.hpp"
45 #include "vm/initialize.h"
46 #include "vm/options.h"
47 #include "vm/references.h"
48 #include "vm/resolve.h"
50 #include "vm/jit/asmpart.h"
51 #include "vm/jit/patcher.h"
52 #include "vm/jit/methodheader.h"
53 #include "vm/jit/stacktrace.hpp"
55 #include "vm/jit/sparc64/solaris/macro_rename.h"
58 /* patcher_wrapper *************************************************************
60 Wrapper for all patchers. It also creates the stackframe info
63 If the return value of the patcher function is false, it gets the
64 exception object, clears the exception pointer and returns the
67 *******************************************************************************/
69 java_object_t *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
75 #if SIZEOF_VOID_P == 8
84 /* define the patcher function */
86 bool (*patcher_function)(u1 *);
90 /* get stuff from the stack */
92 xpc = (u1 *) *((ptrint *) (sp + 5 * 8));
93 o = (java_object_t *) *((ptrint *) (sp + 4 * 8));
94 f = (functionptr) *((ptrint *) (sp + 0 * 8));
96 /* store PV into the patcher function position */
98 *((ptrint *) (sp + 0 * 8)) = (ptrint) pv;
100 /* cast the passed function to a patcher function */
102 patcher_function = (bool (*)(u1 *)) (ptrint) f;
104 /* enter a monitor on the patching position */
106 PATCHER_MONITORENTER;
108 /* the (data) sp points directly to the patcher fields */
109 /* calculate the real sp of the current java function considering the WINSAVE regs */
111 javasp = sp - JITSTACK_CNT * 8 - BIAS;
113 /* create the stackframeinfo */
115 printf("patcher opening sfi for xpc=%p\n", xpc);
117 stacktrace_stackframeinfo_add(&sfi, pv, javasp, ra, xpc);
119 /* call the proper patcher function */
121 result = (patcher_function)(sp);
123 /* remove the stackframeinfo */
125 stacktrace_stackframeinfo_remove(&sfi);
126 printf("patcher closing sfi for xpc=%p\n", xpc);
128 /* check for return value and exit accordingly */
130 if (result == false) {
131 e = exceptions_get_and_clear_exception();
138 /* patch back original (potentially patched) code */
140 #if SIZEOF_VOID_P == 8
141 mcode = *((u8 *) (sp + 3 * 8));
143 *((u4 *) (xpc + 0 * 4)) = mcode >> 32;
144 *((u4 *) (xpc + 1 * 4)) = mcode;
146 mcode[0] = *((u4 *) (sp + 3 * 8));
147 mcode[1] = *((u4 *) (sp + 3 * 8 + 4));
149 *((u4 *) (xpc + 0 * 4)) = mcode[0];
150 *((u4 *) (xpc + 1 * 4)) = mcode[1];
154 /* synchronize instruction cache */
156 md_icacheflush(xpc, PATCHER_CALL_SIZE);
158 PATCHER_MARK_PATCHED_MONITOREXIT;
164 /* patcher_get_putstatic *******************************************************
168 <patched call position>
172 *******************************************************************************/
174 bool patcher_get_putstatic(u1 *sp)
176 unresolved_field *uf;
181 /* get stuff from the stack */
183 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
184 disp = *((s4 *) (sp + 1 * 8));
185 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
187 /* get the fieldinfo */
189 if (!(fi = resolve_field_eager(uf)))
192 /* check if the field's class is initialized */
194 if (!(fi->clazz->state & CLASS_INITIALIZED))
195 if (!initialize_class(fi->clazz))
198 /* patch the field value's address */
200 *((intptr_t *) (pv + disp)) = (intptr_t) fi->value;
202 /* synchronize data cache */
204 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
210 /* patcher_get_putfield ********************************************************
214 <patched call position>
215 8ee90020 lw a5,32(s7)
217 *******************************************************************************/
219 bool patcher_get_putfield(u1 *sp)
222 unresolved_field *uf;
226 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
227 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
229 /* get the fieldinfo */
231 if (!(fi = resolve_field_eager(uf)))
234 /* if we show disassembly, we have to skip the nop's */
237 /* patch the field's offset into the instruction */
239 *((u4 *) (ra + 2 * 4)) |= (s2) (fi->offset & 0x00001fff);
241 /* synchronize instruction cache */
243 md_icacheflush(ra + 2 * 4, 1 * 4);
246 /* otherwise store the patched instruction on the stack */
248 *((u4 *) (sp + 3 * 8)) |= (s2) (fi->offset & 0x00001fff);
255 /* patcher_aconst **************************************************************
259 <patched call postition>
262 *******************************************************************************/
264 bool patcher_aconst(u1 *sp)
266 constant_classref *cr;
271 /* get stuff from the stack */
273 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
274 disp = *((s4 *) (sp + 1 * 8));
275 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
277 /* get the classinfo */
279 if (!(c = resolve_classref_eager(cr)))
282 /* patch the classinfo pointer */
284 *((ptrint *) (pv + disp)) = (ptrint) c;
286 /* synchronize data cache */
288 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
294 /* patcher_builtin_multianewarray **********************************************
298 <patched call position>
299 dfc5ff90 ld a1,-112(s8)
301 dfd9ff88 ld t9,-120(s8)
305 *******************************************************************************/
307 bool patcher_builtin_multianewarray(u1 *sp)
309 constant_classref *cr;
314 /* get stuff from the stack */
316 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
317 disp = *((s4 *) (sp + 1 * 8));
318 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
320 /* get the classinfo */
322 if (!(c = resolve_classref_eager(cr)))
325 /* patch the classinfo pointer */
327 *((ptrint *) (pv + disp)) = (ptrint) c;
329 /* synchronize data cache */
331 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
337 /* patcher_builtin_arraycheckcast **********************************************
341 <patched call position>
342 dfc5ffc0 ld a1,-64(s8)
343 dfd9ffb8 ld t9,-72(s8)
347 *******************************************************************************/
349 bool patcher_builtin_arraycheckcast(u1 *sp)
351 constant_classref *cr;
356 /* get stuff from the stack */
358 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
359 disp = *((s4 *) (sp + 1 * 8));
360 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
362 /* get the classinfo */
364 if (!(c = resolve_classref_eager(cr)))
367 /* patch the classinfo pointer */
369 *((ptrint *) (pv + disp)) = (ptrint) c;
371 /* synchronize data cache */
373 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
379 /* patcher_invokestatic_special ************************************************
383 <patched call position>
384 dfdeffc0 ld s8,-64(s8)
388 ******************************************************************************/
390 bool patcher_invokestatic_special(u1 *sp)
392 unresolved_method *um;
397 /* get stuff from the stack */
399 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
400 disp = *((s4 *) (sp + 1 * 8));
401 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
403 /* get the fieldinfo */
405 if (!(m = resolve_method_eager(um)))
408 /* patch stubroutine */
410 *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
412 /* synchronize data cache */
414 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
420 /* patcher_invokevirtual *******************************************************
424 <patched call position>
430 *******************************************************************************/
432 bool patcher_invokevirtual(u1 *sp)
435 unresolved_method *um;
438 /* get stuff from the stack */
440 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
441 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
443 /* get the fieldinfo */
445 if (!(m = resolve_method_eager(um)))
448 /* if we show disassembly, we have to skip the nop's */
451 ra = ra + PATCHER_CALL_SIZE;
453 /* patch vftbl index */
455 *((s4 *) (ra + 1 * 4)) |=
456 (s4) ((OFFSET(vftbl_t, table[0]) +
457 sizeof(methodptr) * m->vftblindex) & 0x00001fff);
459 /* synchronize instruction cache */
461 md_icacheflush(ra + 1 * 4, 1 * 4);
464 /* patch vftbl index */
466 *((s4 *) (sp + 3 * 8 + 4)) |=
467 (s4) ((OFFSET(vftbl_t, table[0]) +
468 sizeof(methodptr) * m->vftblindex) & 0x00001fff);
475 /* patcher_invokeinterface *****************************************************
479 <patched call position>
481 df39ffa0 ld t9,-96(t9)
482 df3e0018 ld s8,24(t9)
486 *******************************************************************************/
488 bool patcher_invokeinterface(u1 *sp)
491 unresolved_method *um;
494 /* get stuff from the stack */
496 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
497 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
499 /* get the fieldinfo */
501 if (!(m = resolve_method_eager(um)))
504 /* if we show disassembly, we have to skip the nop's */
507 ra = ra + PATCHER_CALL_SIZE;
509 /* patch interfacetable index */
511 *((s4 *) (ra + 1 * 4)) |=
512 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
513 sizeof(methodptr*) * m->clazz->index) & 0x00001fff);
515 /* patch method offset */
517 *((s4 *) (ra + 2 * 4)) |=
518 (s4) ((sizeof(methodptr) * (m - m->clazz->methods)) & 0x00001fff);
520 /* synchronize instruction cache */
522 md_icacheflush(ra + 1 * 4, 2 * 4);
525 /* patch interfacetable index */
527 *((s4 *) (sp + 3 * 8 + 4)) |=
528 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
529 sizeof(methodptr*) * m->clazz->index) & 0x00001fff);
531 /* patch method offset */
533 *((s4 *) (ra + 2 * 4)) |=
534 (s4) ((sizeof(methodptr) * (m - m->clazz->methods)) & 0x00001fff);
536 /* synchronize instruction cache */
538 md_icacheflush(ra + 2 * 4, 1 * 4);
545 /* patcher_checkcast_instanceof_flags ******************************************
549 <patched call position>
550 8fc3ff24 lw v1,-220(s8)
551 30630200 andi v1,v1,512
552 1060000d beq v1,zero,0x000000001051824c
555 *******************************************************************************/
557 bool patcher_checkcast_instanceof_flags(u1 *sp)
559 constant_classref *cr;
564 /* get stuff from the stack */
566 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
567 disp = *((s4 *) (sp + 1 * 8));
568 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
570 /* get the fieldinfo */
572 if (!(c = resolve_classref_eager(cr)))
575 /* patch class flags */
577 *((s4 *) (pv + disp)) = (s4) c->flags;
579 /* synchronize data cache */
581 md_dcacheflush(pv + disp, sizeof(s4));
587 /* patcher_checkcast_interface **************************************
591 <patched call position>
593 8c79001c lw t9,28(v1)
594 27390000 addiu t9,t9,0
595 1b200082 blez t9,zero,0x000000001051843c
599 *******************************************************************************/
601 bool patcher_checkcast_interface(u1 *sp)
604 constant_classref *cr;
607 /* get stuff from the stack */
609 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
610 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
612 /* get the fieldinfo */
614 if (!(c = resolve_classref_eager(cr)))
617 /* if we show disassembly, we have to skip the nop's */
620 ra = ra + PATCHER_CALL_SIZE;
622 /* patch super class index */
624 *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x00001fff);
626 *((s4 *) (ra + (3 + EXCEPTION_CHECK_INSTRUCTIONS) * 4)) |=
627 (s4) ((OFFSET(vftbl_t, interfacetable[0])
628 - c->index * sizeof(methodptr*)) & 0x00001fff);
630 /* synchronize instruction cache */
633 md_icacheflush(ra - 2 * 4, (6 + EXCEPTION_CHECK_INSTRUCTIONS) * 4);
635 md_icacheflush(ra, (4 + EXCEPTION_CHECK_INSTRUCTIONS) * 4);
640 /* patcher_instanceof_interface ************************************************
644 <patched call position>
646 8c79001c lw t9,28(v1)
647 27390000 addiu t9,t9,0
648 1b200082 blez t9,zero,0x000000001051843c
652 *******************************************************************************/
654 bool patcher_instanceof_interface(u1 *sp)
657 constant_classref *cr;
660 /* get stuff from the stack */
662 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
663 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
665 /* get the fieldinfo */
667 if (!(c = resolve_classref_eager(cr)))
670 /* if we show disassembly, we have to skip the nop's */
673 ra = ra + PATCHER_CALL_SIZE;
675 /* patch super class index */
677 *((s4 *) (ra + 2 * 4)) |= (s4) ((c->index) & 0x00001fff);
678 *((s4 *) (ra + 5 * 4)) |=
679 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
680 c->index * sizeof(methodptr*)) & 0x00001fff);
682 /* synchronize instruction cache */
685 md_icacheflush(ra - PATCHER_CALL_SIZE * 4, 8 * 4);
687 md_icacheflush(ra, 6 * 4);
693 /* patcher_checkcast_instanceof_class ******************************************
697 <patched call position>
699 dfd9ff18 ld t9,-232(s8)
701 *******************************************************************************/
703 bool patcher_checkcast_instanceof_class(u1 *sp)
705 constant_classref *cr;
710 /* get stuff from the stack */
712 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
713 disp = *((s4 *) (sp + 1 * 8));
714 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
716 /* get the fieldinfo */
718 if (!(c = resolve_classref_eager(cr)))
721 /* patch super class' vftbl */
723 *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
725 /* synchronize data cache */
727 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
733 /* patcher_clinit **************************************************************
735 No special machine code.
737 *******************************************************************************/
739 bool patcher_clinit(u1 *sp)
743 /* get stuff from the stack */
745 c = (classinfo *) *((ptrint *) (sp + 2 * 8));
747 /* check if the class is initialized */
749 if (!(c->state & CLASS_INITIALIZED))
750 if (!initialize_class(c))
757 /* patcher_athrow_areturn ******************************************************
761 <patched call position>
763 *******************************************************************************/
765 #ifdef ENABLE_VERIFIER
766 bool patcher_athrow_areturn(u1 *sp)
768 unresolved_class *uc;
770 /* get stuff from the stack */
772 uc = (unresolved_class *) *((ptrint *) (sp + 2 * 8));
774 /* resolve the class and check subtype constraints */
776 if (!resolve_class_eager_no_access_check(uc))
781 #endif /* ENABLE_VERIFIER */
784 /* patcher_resolve_native ******************************************************
788 *******************************************************************************/
790 bool patcher_resolve_native(u1 *sp)
797 /* get stuff from the stack */
799 m = (methodinfo *) *((ptrint *) (sp + 2 * 8));
800 disp = *((s4 *) (sp + 1 * 8));
801 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
803 /* return address on SPARC is address of jump, therefore correct */
805 /* resolve native function */
807 if (!(f = native_resolve_function(m)))
810 /* patch native function pointer */
812 *((ptrint *) (pv + disp)) = (ptrint) f;
814 /* synchronize data cache */
816 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
823 * These are local overrides for various environment variables in Emacs.
824 * Please do not remove this and leave it at the end of the file, where
825 * Emacs will automagically detect them.
826 * ---------------------------------------------------------------------
829 * indent-tabs-mode: t
833 * vim:noexpandtab:sw=4:ts=4: