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/md-abi.h"
38 #include "vm/jit/sparc64/codegen.h"
40 #include "native/native.h"
41 #include "vm/builtin.h"
42 #include "vm/exceptions.h"
43 #include "vm/initialize.h"
45 #include "vm/jit/asmpart.h"
46 #include "vm/jit/patcher.h"
47 #include "vm/jit/md.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"
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_object_t *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_object_t *) *((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 printf("patcher opening sfi for xpc=%p\n", xpc);
118 stacktrace_stackframeinfo_add(&sfi, pv, javasp, ra, xpc);
120 /* call the proper patcher function */
122 result = (patcher_function)(sp);
124 /* remove the stackframeinfo */
126 stacktrace_stackframeinfo_remove(&sfi);
127 printf("patcher closing sfi for xpc=%p\n", xpc);
129 /* check for return value and exit accordingly */
131 if (result == false) {
132 e = exceptions_get_and_clear_exception();
139 /* patch back original (potentially patched) code */
141 #if SIZEOF_VOID_P == 8
142 mcode = *((u8 *) (sp + 3 * 8));
144 *((u4 *) (xpc + 0 * 4)) = mcode >> 32;
145 *((u4 *) (xpc + 1 * 4)) = mcode;
147 mcode[0] = *((u4 *) (sp + 3 * 8));
148 mcode[1] = *((u4 *) (sp + 3 * 8 + 4));
150 *((u4 *) (xpc + 0 * 4)) = mcode[0];
151 *((u4 *) (xpc + 1 * 4)) = mcode[1];
155 /* synchronize instruction cache */
157 md_icacheflush(xpc, PATCHER_CALL_SIZE);
159 PATCHER_MARK_PATCHED_MONITOREXIT;
165 /* patcher_get_putstatic *******************************************************
169 <patched call position>
173 *******************************************************************************/
175 bool patcher_get_putstatic(u1 *sp)
177 unresolved_field *uf;
182 /* get stuff from the stack */
184 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
185 disp = *((s4 *) (sp + 1 * 8));
186 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
188 /* get the fieldinfo */
190 if (!(fi = resolve_field_eager(uf)))
193 /* check if the field's class is initialized */
195 if (!(fi->class->state & CLASS_INITIALIZED))
196 if (!initialize_class(fi->class))
199 /* patch the field value's address */
201 *((intptr_t *) (pv + disp)) = (intptr_t) fi->value;
203 /* synchronize data cache */
205 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
211 /* patcher_get_putfield ********************************************************
215 <patched call position>
216 8ee90020 lw a5,32(s7)
218 *******************************************************************************/
220 bool patcher_get_putfield(u1 *sp)
223 unresolved_field *uf;
227 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
228 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
230 /* get the fieldinfo */
232 if (!(fi = resolve_field_eager(uf)))
235 /* if we show disassembly, we have to skip the nop's */
238 /* patch the field's offset into the instruction */
240 *((u4 *) (ra + 2 * 4)) |= (s2) (fi->offset & 0x00001fff);
242 /* synchronize instruction cache */
244 md_icacheflush(ra + 2 * 4, 1 * 4);
247 /* otherwise store the patched instruction on the stack */
249 *((u4 *) (sp + 3 * 8)) |= (s2) (fi->offset & 0x00001fff);
256 /* patcher_aconst **************************************************************
260 <patched call postition>
263 *******************************************************************************/
265 bool patcher_aconst(u1 *sp)
267 constant_classref *cr;
272 /* get stuff from the stack */
274 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
275 disp = *((s4 *) (sp + 1 * 8));
276 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
278 /* get the classinfo */
280 if (!(c = resolve_classref_eager(cr)))
283 /* patch the classinfo pointer */
285 *((ptrint *) (pv + disp)) = (ptrint) c;
287 /* synchronize data cache */
289 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
295 /* patcher_builtin_multianewarray **********************************************
299 <patched call position>
300 dfc5ff90 ld a1,-112(s8)
302 dfd9ff88 ld t9,-120(s8)
306 *******************************************************************************/
308 bool patcher_builtin_multianewarray(u1 *sp)
310 constant_classref *cr;
315 /* get stuff from the stack */
317 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
318 disp = *((s4 *) (sp + 1 * 8));
319 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
321 /* get the classinfo */
323 if (!(c = resolve_classref_eager(cr)))
326 /* patch the classinfo pointer */
328 *((ptrint *) (pv + disp)) = (ptrint) c;
330 /* synchronize data cache */
332 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
338 /* patcher_builtin_arraycheckcast **********************************************
342 <patched call position>
343 dfc5ffc0 ld a1,-64(s8)
344 dfd9ffb8 ld t9,-72(s8)
348 *******************************************************************************/
350 bool patcher_builtin_arraycheckcast(u1 *sp)
352 constant_classref *cr;
357 /* get stuff from the stack */
359 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
360 disp = *((s4 *) (sp + 1 * 8));
361 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
363 /* get the classinfo */
365 if (!(c = resolve_classref_eager(cr)))
368 /* patch the classinfo pointer */
370 *((ptrint *) (pv + disp)) = (ptrint) c;
372 /* synchronize data cache */
374 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
380 /* patcher_invokestatic_special ************************************************
384 <patched call position>
385 dfdeffc0 ld s8,-64(s8)
389 ******************************************************************************/
391 bool patcher_invokestatic_special(u1 *sp)
393 unresolved_method *um;
398 /* get stuff from the stack */
400 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
401 disp = *((s4 *) (sp + 1 * 8));
402 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
404 /* get the fieldinfo */
406 if (!(m = resolve_method_eager(um)))
409 /* patch stubroutine */
411 *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
413 /* synchronize data cache */
415 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
421 /* patcher_invokevirtual *******************************************************
425 <patched call position>
431 *******************************************************************************/
433 bool patcher_invokevirtual(u1 *sp)
436 unresolved_method *um;
439 /* get stuff from the stack */
441 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
442 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
444 /* get the fieldinfo */
446 if (!(m = resolve_method_eager(um)))
449 /* if we show disassembly, we have to skip the nop's */
452 ra = ra + PATCHER_CALL_SIZE;
454 /* patch vftbl index */
456 *((s4 *) (ra + 1 * 4)) |=
457 (s4) ((OFFSET(vftbl_t, table[0]) +
458 sizeof(methodptr) * m->vftblindex) & 0x00001fff);
460 /* synchronize instruction cache */
462 md_icacheflush(ra + 1 * 4, 1 * 4);
465 /* patch vftbl index */
467 *((s4 *) (sp + 3 * 8 + 4)) |=
468 (s4) ((OFFSET(vftbl_t, table[0]) +
469 sizeof(methodptr) * m->vftblindex) & 0x00001fff);
476 /* patcher_invokeinterface *****************************************************
480 <patched call position>
482 df39ffa0 ld t9,-96(t9)
483 df3e0018 ld s8,24(t9)
487 *******************************************************************************/
489 bool patcher_invokeinterface(u1 *sp)
492 unresolved_method *um;
495 /* get stuff from the stack */
497 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
498 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
500 /* get the fieldinfo */
502 if (!(m = resolve_method_eager(um)))
505 /* if we show disassembly, we have to skip the nop's */
508 ra = ra + PATCHER_CALL_SIZE;
510 /* patch interfacetable index */
512 *((s4 *) (ra + 1 * 4)) |=
513 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
514 sizeof(methodptr*) * m->class->index) & 0x00001fff);
516 /* patch method offset */
518 *((s4 *) (ra + 2 * 4)) |=
519 (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x00001fff);
521 /* synchronize instruction cache */
523 md_icacheflush(ra + 1 * 4, 2 * 4);
526 /* patch interfacetable index */
528 *((s4 *) (sp + 3 * 8 + 4)) |=
529 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
530 sizeof(methodptr*) * m->class->index) & 0x00001fff);
532 /* patch method offset */
534 *((s4 *) (ra + 2 * 4)) |=
535 (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x00001fff);
537 /* synchronize instruction cache */
539 md_icacheflush(ra + 2 * 4, 1 * 4);
546 /* patcher_checkcast_instanceof_flags ******************************************
550 <patched call position>
551 8fc3ff24 lw v1,-220(s8)
552 30630200 andi v1,v1,512
553 1060000d beq v1,zero,0x000000001051824c
556 *******************************************************************************/
558 bool patcher_checkcast_instanceof_flags(u1 *sp)
560 constant_classref *cr;
565 /* get stuff from the stack */
567 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
568 disp = *((s4 *) (sp + 1 * 8));
569 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
571 /* get the fieldinfo */
573 if (!(c = resolve_classref_eager(cr)))
576 /* patch class flags */
578 *((s4 *) (pv + disp)) = (s4) c->flags;
580 /* synchronize data cache */
582 md_dcacheflush(pv + disp, sizeof(s4));
588 /* patcher_checkcast_interface **************************************
592 <patched call position>
594 8c79001c lw t9,28(v1)
595 27390000 addiu t9,t9,0
596 1b200082 blez t9,zero,0x000000001051843c
600 *******************************************************************************/
602 bool patcher_checkcast_interface(u1 *sp)
605 constant_classref *cr;
608 /* get stuff from the stack */
610 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
611 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
613 /* get the fieldinfo */
615 if (!(c = resolve_classref_eager(cr)))
618 /* if we show disassembly, we have to skip the nop's */
621 ra = ra + PATCHER_CALL_SIZE;
623 /* patch super class index */
625 *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x00001fff);
627 *((s4 *) (ra + (3 + EXCEPTION_CHECK_INSTRUCTIONS) * 4)) |=
628 (s4) ((OFFSET(vftbl_t, interfacetable[0])
629 - c->index * sizeof(methodptr*)) & 0x00001fff);
631 /* synchronize instruction cache */
634 md_icacheflush(ra - 2 * 4, (6 + EXCEPTION_CHECK_INSTRUCTIONS) * 4);
636 md_icacheflush(ra, (4 + EXCEPTION_CHECK_INSTRUCTIONS) * 4);
641 /* patcher_instanceof_interface ************************************************
645 <patched call position>
647 8c79001c lw t9,28(v1)
648 27390000 addiu t9,t9,0
649 1b200082 blez t9,zero,0x000000001051843c
653 *******************************************************************************/
655 bool patcher_instanceof_interface(u1 *sp)
658 constant_classref *cr;
661 /* get stuff from the stack */
663 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
664 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
666 /* get the fieldinfo */
668 if (!(c = resolve_classref_eager(cr)))
671 /* if we show disassembly, we have to skip the nop's */
674 ra = ra + PATCHER_CALL_SIZE;
676 /* patch super class index */
678 *((s4 *) (ra + 2 * 4)) |= (s4) ((c->index) & 0x00001fff);
679 *((s4 *) (ra + 5 * 4)) |=
680 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
681 c->index * sizeof(methodptr*)) & 0x00001fff);
683 /* synchronize instruction cache */
686 md_icacheflush(ra - PATCHER_CALL_SIZE * 4, 8 * 4);
688 md_icacheflush(ra, 6 * 4);
694 /* patcher_checkcast_instanceof_class ******************************************
698 <patched call position>
700 dfd9ff18 ld t9,-232(s8)
702 *******************************************************************************/
704 bool patcher_checkcast_instanceof_class(u1 *sp)
706 constant_classref *cr;
711 /* get stuff from the stack */
713 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
714 disp = *((s4 *) (sp + 1 * 8));
715 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
717 /* get the fieldinfo */
719 if (!(c = resolve_classref_eager(cr)))
722 /* patch super class' vftbl */
724 *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
726 /* synchronize data cache */
728 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
734 /* patcher_clinit **************************************************************
736 No special machine code.
738 *******************************************************************************/
740 bool patcher_clinit(u1 *sp)
744 /* get stuff from the stack */
746 c = (classinfo *) *((ptrint *) (sp + 2 * 8));
748 /* check if the class is initialized */
750 if (!(c->state & CLASS_INITIALIZED))
751 if (!initialize_class(c))
758 /* patcher_athrow_areturn ******************************************************
762 <patched call position>
764 *******************************************************************************/
766 #ifdef ENABLE_VERIFIER
767 bool patcher_athrow_areturn(u1 *sp)
769 unresolved_class *uc;
771 /* get stuff from the stack */
773 uc = (unresolved_class *) *((ptrint *) (sp + 2 * 8));
775 /* resolve the class and check subtype constraints */
777 if (!resolve_class_eager_no_access_check(uc))
782 #endif /* ENABLE_VERIFIER */
785 /* patcher_resolve_native ******************************************************
789 *******************************************************************************/
791 bool patcher_resolve_native(u1 *sp)
798 /* get stuff from the stack */
800 m = (methodinfo *) *((ptrint *) (sp + 2 * 8));
801 disp = *((s4 *) (sp + 1 * 8));
802 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
804 /* return address on SPARC is address of jump, therefore correct */
806 /* resolve native function */
808 if (!(f = native_resolve_function(m)))
811 /* patch native function pointer */
813 *((ptrint *) (pv + disp)) = (ptrint) f;
815 /* synchronize data cache */
817 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
824 * These are local overrides for various environment variables in Emacs.
825 * Please do not remove this and leave it at the end of the file, where
826 * Emacs will automagically detect them.
827 * ---------------------------------------------------------------------
830 * indent-tabs-mode: t
834 * vim:noexpandtab:sw=4:ts=4: