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"
58 #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_objectheader *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_objectheader *) *((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 stacktrace_create_extern_stackframeinfo(&sfi, pv, javasp, ra, xpc);
119 /* call the proper patcher function */
121 result = (patcher_function)(sp);
123 /* remove the stackframeinfo */
125 stacktrace_remove_stackframeinfo(&sfi);
127 /* check for return value and exit accordingly */
129 if (result == false) {
130 e = exceptions_get_and_clear_exception();
137 /* patch back original (potentially patched) code */
139 #if SIZEOF_VOID_P == 8
140 mcode = *((u8 *) (sp + 3 * 8));
142 *((u4 *) (xpc + 0 * 4)) = mcode >> 32;
143 *((u4 *) (xpc + 1 * 4)) = mcode;
145 mcode[0] = *((u4 *) (sp + 3 * 8));
146 mcode[1] = *((u4 *) (sp + 3 * 8 + 4));
148 *((u4 *) (xpc + 0 * 4)) = mcode[0];
149 *((u4 *) (xpc + 1 * 4)) = mcode[1];
153 /* synchronize instruction cache */
155 md_icacheflush(xpc, PATCHER_CALL_SIZE);
157 PATCHER_MARK_PATCHED_MONITOREXIT;
163 /* patcher_get_putstatic *******************************************************
167 <patched call position>
171 *******************************************************************************/
173 bool patcher_get_putstatic(u1 *sp)
175 unresolved_field *uf;
180 /* get stuff from the stack */
182 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
183 disp = *((s4 *) (sp + 1 * 8));
184 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
186 /* get the fieldinfo */
188 if (!(fi = resolve_field_eager(uf)))
191 /* check if the field's class is initialized */
193 if (!(fi->class->state & CLASS_INITIALIZED))
194 if (!initialize_class(fi->class))
197 /* patch the field value's address */
199 *((ptrint *) (pv + disp)) = (ptrint) &(fi->value);
201 /* synchronize data cache */
203 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
209 /* patcher_get_putfield ********************************************************
213 <patched call position>
214 8ee90020 lw a5,32(s7)
216 *******************************************************************************/
218 bool patcher_get_putfield(u1 *sp)
221 unresolved_field *uf;
225 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
226 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
228 /* get the fieldinfo */
230 if (!(fi = resolve_field_eager(uf)))
233 /* if we show disassembly, we have to skip the nop's */
236 /* patch the field's offset into the instruction */
238 *((u4 *) (ra + 2 * 4)) |= (s2) (fi->offset & 0x00001fff);
240 /* synchronize instruction cache */
242 md_icacheflush(ra + 2 * 4, 1 * 4);
245 /* otherwise store the patched instruction on the stack */
247 *((u4 *) (sp + 3 * 8)) |= (s2) (fi->offset & 0x00001fff);
254 /* patcher_aconst **************************************************************
258 <patched call postition>
261 *******************************************************************************/
263 bool patcher_aconst(u1 *sp)
265 constant_classref *cr;
270 /* get stuff from the stack */
272 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
273 disp = *((s4 *) (sp + 1 * 8));
274 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
276 /* get the classinfo */
278 if (!(c = resolve_classref_eager(cr)))
281 /* patch the classinfo pointer */
283 *((ptrint *) (pv + disp)) = (ptrint) c;
285 /* synchronize data cache */
287 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
293 /* patcher_builtin_multianewarray **********************************************
297 <patched call position>
298 dfc5ff90 ld a1,-112(s8)
300 dfd9ff88 ld t9,-120(s8)
304 *******************************************************************************/
306 bool patcher_builtin_multianewarray(u1 *sp)
308 constant_classref *cr;
313 /* get stuff from the stack */
315 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
316 disp = *((s4 *) (sp + 1 * 8));
317 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
319 /* get the classinfo */
321 if (!(c = resolve_classref_eager(cr)))
324 /* patch the classinfo pointer */
326 *((ptrint *) (pv + disp)) = (ptrint) c;
328 /* synchronize data cache */
330 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
336 /* patcher_builtin_arraycheckcast **********************************************
340 <patched call position>
341 dfc5ffc0 ld a1,-64(s8)
342 dfd9ffb8 ld t9,-72(s8)
346 *******************************************************************************/
348 bool patcher_builtin_arraycheckcast(u1 *sp)
350 constant_classref *cr;
355 /* get stuff from the stack */
357 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
358 disp = *((s4 *) (sp + 1 * 8));
359 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
361 /* get the classinfo */
363 if (!(c = resolve_classref_eager(cr)))
366 /* patch the classinfo pointer */
368 *((ptrint *) (pv + disp)) = (ptrint) c;
370 /* synchronize data cache */
372 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
378 /* patcher_invokestatic_special ************************************************
382 <patched call position>
383 dfdeffc0 ld s8,-64(s8)
387 ******************************************************************************/
389 bool patcher_invokestatic_special(u1 *sp)
391 unresolved_method *um;
396 /* get stuff from the stack */
398 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
399 disp = *((s4 *) (sp + 1 * 8));
400 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
402 /* get the fieldinfo */
404 if (!(m = resolve_method_eager(um)))
407 /* patch stubroutine */
409 *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
411 /* synchronize data cache */
413 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
419 /* patcher_invokevirtual *******************************************************
423 <patched call position>
429 *******************************************************************************/
431 bool patcher_invokevirtual(u1 *sp)
434 unresolved_method *um;
437 /* get stuff from the stack */
439 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
440 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
442 /* get the fieldinfo */
444 if (!(m = resolve_method_eager(um)))
447 /* if we show disassembly, we have to skip the nop's */
450 ra = ra + PATCHER_CALL_SIZE;
452 /* patch vftbl index */
454 *((s4 *) (ra + 1 * 4)) |=
455 (s4) ((OFFSET(vftbl_t, table[0]) +
456 sizeof(methodptr) * m->vftblindex) & 0x00001fff);
458 /* synchronize instruction cache */
460 md_icacheflush(ra + 1 * 4, 1 * 4);
463 /* patch vftbl index */
465 *((s4 *) (sp + 3 * 8 + 4)) |=
466 (s4) ((OFFSET(vftbl_t, table[0]) +
467 sizeof(methodptr) * m->vftblindex) & 0x00001fff);
474 /* patcher_invokeinterface *****************************************************
478 <patched call position>
480 df39ffa0 ld t9,-96(t9)
481 df3e0018 ld s8,24(t9)
485 *******************************************************************************/
487 bool patcher_invokeinterface(u1 *sp)
490 unresolved_method *um;
493 /* get stuff from the stack */
495 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
496 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
498 /* get the fieldinfo */
500 if (!(m = resolve_method_eager(um)))
503 /* if we show disassembly, we have to skip the nop's */
506 ra = ra + PATCHER_CALL_SIZE;
508 /* patch interfacetable index */
510 *((s4 *) (ra + 1 * 4)) |=
511 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
512 sizeof(methodptr*) * m->class->index) & 0x00001fff);
514 /* patch method offset */
516 *((s4 *) (ra + 2 * 4)) |=
517 (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x00001fff);
519 /* synchronize instruction cache */
521 md_icacheflush(ra + 1 * 4, 2 * 4);
524 /* patch interfacetable index */
526 *((s4 *) (sp + 3 * 8 + 4)) |=
527 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
528 sizeof(methodptr*) * m->class->index) & 0x00001fff);
530 /* patch method offset */
532 *((s4 *) (ra + 2 * 4)) |=
533 (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x00001fff);
535 /* synchronize instruction cache */
537 md_icacheflush(ra + 2 * 4, 1 * 4);
544 /* patcher_checkcast_instanceof_flags ******************************************
548 <patched call position>
549 8fc3ff24 lw v1,-220(s8)
550 30630200 andi v1,v1,512
551 1060000d beq v1,zero,0x000000001051824c
554 *******************************************************************************/
556 bool patcher_checkcast_instanceof_flags(u1 *sp)
558 constant_classref *cr;
563 /* get stuff from the stack */
565 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
566 disp = *((s4 *) (sp + 1 * 8));
567 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
569 /* get the fieldinfo */
571 if (!(c = resolve_classref_eager(cr)))
574 /* patch class flags */
576 *((s4 *) (pv + disp)) = (s4) c->flags;
578 /* synchronize data cache */
580 md_dcacheflush(pv + disp, sizeof(s4));
586 /* patcher_checkcast_interface **************************************
590 <patched call position>
592 8c79001c lw t9,28(v1)
593 27390000 addiu t9,t9,0
594 1b200082 blez t9,zero,0x000000001051843c
598 *******************************************************************************/
600 bool patcher_checkcast_interface(u1 *sp)
603 constant_classref *cr;
606 /* get stuff from the stack */
608 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
609 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
611 /* get the fieldinfo */
613 if (!(c = resolve_classref_eager(cr)))
616 /* if we show disassembly, we have to skip the nop's */
619 ra = ra + PATCHER_CALL_SIZE;
621 /* patch super class index */
623 *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x00001fff);
625 *((s4 *) (ra + (3 + EXCEPTION_CHECK_INSTRUCTIONS) * 4)) |=
626 (s4) ((OFFSET(vftbl_t, interfacetable[0])
627 - c->index * sizeof(methodptr*)) & 0x00001fff);
629 /* synchronize instruction cache */
632 md_icacheflush(ra - 2 * 4, (6 + EXCEPTION_CHECK_INSTRUCTIONS) * 4);
634 md_icacheflush(ra, (4 + EXCEPTION_CHECK_INSTRUCTIONS) * 4);
639 /* patcher_instanceof_interface ************************************************
643 <patched call position>
645 8c79001c lw t9,28(v1)
646 27390000 addiu t9,t9,0
647 1b200082 blez t9,zero,0x000000001051843c
651 *******************************************************************************/
653 bool patcher_instanceof_interface(u1 *sp)
656 constant_classref *cr;
659 /* get stuff from the stack */
661 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
662 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
664 /* get the fieldinfo */
666 if (!(c = resolve_classref_eager(cr)))
669 /* if we show disassembly, we have to skip the nop's */
672 ra = ra + PATCHER_CALL_SIZE;
674 /* patch super class index */
676 *((s4 *) (ra + 2 * 4)) |= (s4) ((c->index) & 0x00001fff);
677 *((s4 *) (ra + 5 * 4)) |=
678 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
679 c->index * sizeof(methodptr*)) & 0x00001fff);
681 /* synchronize instruction cache */
684 md_icacheflush(ra - PATCHER_CALL_SIZE * 4, 8 * 4);
686 md_icacheflush(ra, 6 * 4);
692 /* patcher_checkcast_instanceof_class ******************************************
696 <patched call position>
698 dfd9ff18 ld t9,-232(s8)
700 *******************************************************************************/
702 bool patcher_checkcast_instanceof_class(u1 *sp)
704 constant_classref *cr;
709 /* get stuff from the stack */
711 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
712 disp = *((s4 *) (sp + 1 * 8));
713 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
715 /* get the fieldinfo */
717 if (!(c = resolve_classref_eager(cr)))
720 /* patch super class' vftbl */
722 *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
724 /* synchronize data cache */
726 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
732 /* patcher_clinit **************************************************************
734 No special machine code.
736 *******************************************************************************/
738 bool patcher_clinit(u1 *sp)
742 /* get stuff from the stack */
744 c = (classinfo *) *((ptrint *) (sp + 2 * 8));
746 /* check if the class is initialized */
748 if (!(c->state & CLASS_INITIALIZED))
749 if (!initialize_class(c))
756 /* patcher_athrow_areturn ******************************************************
760 <patched call position>
762 *******************************************************************************/
764 #ifdef ENABLE_VERIFIER
765 bool patcher_athrow_areturn(u1 *sp)
767 unresolved_class *uc;
769 /* get stuff from the stack */
771 uc = (unresolved_class *) *((ptrint *) (sp + 2 * 8));
773 /* resolve the class and check subtype constraints */
775 if (!resolve_class_eager_no_access_check(uc))
780 #endif /* ENABLE_VERIFIER */
783 /* patcher_resolve_native ******************************************************
787 *******************************************************************************/
789 #if !defined(WITH_STATIC_CLASSPATH)
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);
820 #endif /* !defined(WITH_STATIC_CLASSPATH) */
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: