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/jit/builtin.hpp"
43 #include "vm/exceptions.hpp"
44 #include "vm/field.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 /* store the patched instruction on the stack */
236 *((u4 *) (sp + 3 * 8)) |= (s2) (fi->offset & 0x00001fff);
242 /* patcher_aconst **************************************************************
246 <patched call postition>
249 *******************************************************************************/
251 bool patcher_aconst(u1 *sp)
253 constant_classref *cr;
258 /* get stuff from the stack */
260 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
261 disp = *((s4 *) (sp + 1 * 8));
262 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
264 /* get the classinfo */
266 if (!(c = resolve_classref_eager(cr)))
269 /* patch the classinfo pointer */
271 *((ptrint *) (pv + disp)) = (ptrint) c;
273 /* synchronize data cache */
275 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
281 /* patcher_builtin_multianewarray **********************************************
285 <patched call position>
286 dfc5ff90 ld a1,-112(s8)
288 dfd9ff88 ld t9,-120(s8)
292 *******************************************************************************/
294 bool patcher_builtin_multianewarray(u1 *sp)
296 constant_classref *cr;
301 /* get stuff from the stack */
303 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
304 disp = *((s4 *) (sp + 1 * 8));
305 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
307 /* get the classinfo */
309 if (!(c = resolve_classref_eager(cr)))
312 /* patch the classinfo pointer */
314 *((ptrint *) (pv + disp)) = (ptrint) c;
316 /* synchronize data cache */
318 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
324 /* patcher_builtin_arraycheckcast **********************************************
328 <patched call position>
329 dfc5ffc0 ld a1,-64(s8)
330 dfd9ffb8 ld t9,-72(s8)
334 *******************************************************************************/
336 bool patcher_builtin_arraycheckcast(u1 *sp)
338 constant_classref *cr;
343 /* get stuff from the stack */
345 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
346 disp = *((s4 *) (sp + 1 * 8));
347 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
349 /* get the classinfo */
351 if (!(c = resolve_classref_eager(cr)))
354 /* patch the classinfo pointer */
356 *((ptrint *) (pv + disp)) = (ptrint) c;
358 /* synchronize data cache */
360 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
366 /* patcher_invokestatic_special ************************************************
370 <patched call position>
371 dfdeffc0 ld s8,-64(s8)
375 ******************************************************************************/
377 bool patcher_invokestatic_special(u1 *sp)
379 unresolved_method *um;
384 /* get stuff from the stack */
386 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
387 disp = *((s4 *) (sp + 1 * 8));
388 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
390 /* get the fieldinfo */
392 if (!(m = resolve_method_eager(um)))
395 /* patch stubroutine */
397 *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
399 /* synchronize data cache */
401 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
407 /* patcher_invokevirtual *******************************************************
411 <patched call position>
417 *******************************************************************************/
419 bool patcher_invokevirtual(u1 *sp)
422 unresolved_method *um;
425 /* get stuff from the stack */
427 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
428 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
430 /* get the fieldinfo */
432 if (!(m = resolve_method_eager(um)))
435 /* patch vftbl index */
437 *((s4 *) (sp + 3 * 8 + 4)) |=
438 (s4) ((OFFSET(vftbl_t, table[0]) +
439 sizeof(methodptr) * m->vftblindex) & 0x00001fff);
445 /* patcher_invokeinterface *****************************************************
449 <patched call position>
451 df39ffa0 ld t9,-96(t9)
452 df3e0018 ld s8,24(t9)
456 *******************************************************************************/
458 bool patcher_invokeinterface(u1 *sp)
461 unresolved_method *um;
464 /* get stuff from the stack */
466 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
467 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
469 /* get the fieldinfo */
471 if (!(m = resolve_method_eager(um)))
474 /* patch interfacetable index */
476 *((s4 *) (sp + 3 * 8 + 4)) |=
477 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
478 sizeof(methodptr*) * m->clazz->index) & 0x00001fff);
480 /* patch method offset */
482 *((s4 *) (ra + 2 * 4)) |=
483 (s4) ((sizeof(methodptr) * (m - m->clazz->methods)) & 0x00001fff);
485 /* synchronize instruction cache */
487 md_icacheflush(ra + 2 * 4, 1 * 4);
493 /* patcher_checkcast_instanceof_flags ******************************************
497 <patched call position>
498 8fc3ff24 lw v1,-220(s8)
499 30630200 andi v1,v1,512
500 1060000d beq v1,zero,0x000000001051824c
503 *******************************************************************************/
505 bool patcher_checkcast_instanceof_flags(u1 *sp)
507 constant_classref *cr;
512 /* get stuff from the stack */
514 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
515 disp = *((s4 *) (sp + 1 * 8));
516 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
518 /* get the fieldinfo */
520 if (!(c = resolve_classref_eager(cr)))
523 /* patch class flags */
525 *((s4 *) (pv + disp)) = (s4) c->flags;
527 /* synchronize data cache */
529 md_dcacheflush(pv + disp, sizeof(s4));
535 /* patcher_checkcast_interface **************************************
539 <patched call position>
541 8c79001c lw t9,28(v1)
542 27390000 addiu t9,t9,0
543 1b200082 blez t9,zero,0x000000001051843c
547 *******************************************************************************/
549 bool patcher_checkcast_interface(u1 *sp)
552 constant_classref *cr;
555 /* get stuff from the stack */
557 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
558 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
560 /* get the fieldinfo */
562 if (!(c = resolve_classref_eager(cr)))
565 /* patch super class index */
567 *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x00001fff);
569 *((s4 *) (ra + (3 + EXCEPTION_CHECK_INSTRUCTIONS) * 4)) |=
570 (s4) ((OFFSET(vftbl_t, interfacetable[0])
571 - c->index * sizeof(methodptr*)) & 0x00001fff);
573 /* synchronize instruction cache */
575 md_icacheflush(ra, (4 + EXCEPTION_CHECK_INSTRUCTIONS) * 4);
580 /* patcher_instanceof_interface ************************************************
584 <patched call position>
586 8c79001c lw t9,28(v1)
587 27390000 addiu t9,t9,0
588 1b200082 blez t9,zero,0x000000001051843c
592 *******************************************************************************/
594 bool patcher_instanceof_interface(u1 *sp)
597 constant_classref *cr;
600 /* get stuff from the stack */
602 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
603 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
605 /* get the fieldinfo */
607 if (!(c = resolve_classref_eager(cr)))
610 /* patch super class index */
612 *((s4 *) (ra + 2 * 4)) |= (s4) ((c->index) & 0x00001fff);
613 *((s4 *) (ra + 5 * 4)) |=
614 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
615 c->index * sizeof(methodptr*)) & 0x00001fff);
617 /* synchronize instruction cache */
619 md_icacheflush(ra, 6 * 4);
625 /* patcher_checkcast_instanceof_class ******************************************
629 <patched call position>
631 dfd9ff18 ld t9,-232(s8)
633 *******************************************************************************/
635 bool patcher_checkcast_instanceof_class(u1 *sp)
637 constant_classref *cr;
642 /* get stuff from the stack */
644 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
645 disp = *((s4 *) (sp + 1 * 8));
646 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
648 /* get the fieldinfo */
650 if (!(c = resolve_classref_eager(cr)))
653 /* patch super class' vftbl */
655 *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
657 /* synchronize data cache */
659 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
665 /* patcher_clinit **************************************************************
667 No special machine code.
669 *******************************************************************************/
671 bool patcher_clinit(u1 *sp)
675 /* get stuff from the stack */
677 c = (classinfo *) *((ptrint *) (sp + 2 * 8));
679 /* check if the class is initialized */
681 if (!(c->state & CLASS_INITIALIZED))
682 if (!initialize_class(c))
689 /* patcher_athrow_areturn ******************************************************
693 <patched call position>
695 *******************************************************************************/
697 #ifdef ENABLE_VERIFIER
698 bool patcher_athrow_areturn(u1 *sp)
700 unresolved_class *uc;
702 /* get stuff from the stack */
704 uc = (unresolved_class *) *((ptrint *) (sp + 2 * 8));
706 /* resolve the class and check subtype constraints */
708 if (!resolve_class_eager_no_access_check(uc))
713 #endif /* ENABLE_VERIFIER */
716 /* patcher_resolve_native ******************************************************
720 *******************************************************************************/
722 bool patcher_resolve_native(u1 *sp)
729 /* get stuff from the stack */
731 m = (methodinfo *) *((ptrint *) (sp + 2 * 8));
732 disp = *((s4 *) (sp + 1 * 8));
733 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
735 /* return address on SPARC is address of jump, therefore correct */
737 /* resolve native function */
739 if (!(f = native_resolve_function(m)))
742 /* patch native function pointer */
744 *((ptrint *) (pv + disp)) = (ptrint) f;
746 /* synchronize data cache */
748 md_dcacheflush(pv + disp, SIZEOF_VOID_P);
755 * These are local overrides for various environment variables in Emacs.
756 * Please do not remove this and leave it at the end of the file, where
757 * Emacs will automagically detect them.
758 * ---------------------------------------------------------------------
761 * indent-tabs-mode: t
765 * vim:noexpandtab:sw=4:ts=4: