1 /* src/vm/jit/alpha/patcher.c - Alpha 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 Contact: cacao@cacaojvm.org
27 Authors: Christian Thalinger
31 $Id: patcher.c 5094 2006-07-10 13:51:38Z twisti $
42 #include "mm/memory.h"
43 #include "native/native.h"
44 #include "vm/builtin.h"
46 #include "vm/exceptions.h"
48 #include "vm/initialize.h"
49 #include "vm/options.h"
50 #include "vm/references.h"
51 #include "vm/resolve.h"
52 #include "vm/jit/asmpart.h"
53 #include "vm/jit/patcher.h"
54 #include "vm/jit/methodheader.h"
57 /* patcher_wrapper *************************************************************
59 Wrapper for all patchers. It also creates the stackframe info
62 If the return value of the patcher function is false, it gets the
63 exception object, clears the exception pointer and returns the
66 *******************************************************************************/
68 java_objectheader *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
77 /* define the patcher function */
79 bool (*patcher_function)(u1 *);
83 /* get stuff from the stack */
85 xpc = (u1 *) *((ptrint *) (sp + 5 * 8));
86 o = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
87 f = (functionptr) *((ptrint *) (sp + 0 * 8));
89 /* store PV into the patcher function position */
91 *((ptrint *) (sp + 0 * 8)) = (ptrint) pv;
93 /* cast the passed function to a patcher function */
95 patcher_function = (bool (*)(u1 *)) (ptrint) f;
97 /* enter a monitor on the patching position */
101 /* create the stackframeinfo */
103 stacktrace_create_extern_stackframeinfo(&sfi, pv, sp + 6 * 8, ra, xpc);
105 /* call the proper patcher function */
107 result = (patcher_function)(sp);
109 /* remove the stackframeinfo */
111 stacktrace_remove_stackframeinfo(&sfi);
113 /* check for return value and exit accordingly */
115 if (result == false) {
116 e = exceptions_get_and_clear_exception();
123 PATCHER_MARK_PATCHED_MONITOREXIT;
129 /* patcher_get_putstatic *******************************************************
133 <patched call position>
134 a73bff98 ldq t11,-104(pv)
135 a2590000 ldl a2,0(t11)
137 *******************************************************************************/
139 bool patcher_get_putstatic(u1 *sp)
143 unresolved_field *uf;
148 /* get stuff from the stack */
150 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
151 mcode = *((u4 *) (sp + 3 * 8));
152 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
153 disp = *((s4 *) (sp + 1 * 8));
154 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
156 /* calculate and set the new return address */
159 *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
161 /* get the fieldinfo */
163 if (!(fi = resolve_field_eager(uf)))
166 /* check if the field's class is initialized */
168 if (!(fi->class->state & CLASS_INITIALIZED))
169 if (!initialize_class(fi->class))
172 /* patch back original code */
174 *((u4 *) ra) = mcode;
176 /* synchronize instruction cache */
178 md_icacheflush(NULL, 0);
180 /* patch the field value's address */
182 *((ptrint *) (pv + disp)) = (ptrint) &(fi->value);
188 /* patcher_get_putfield ********************************************************
192 <patched call position>
193 a2af0020 ldl a5,32(s6)
195 *******************************************************************************/
197 bool patcher_get_putfield(u1 *sp)
201 unresolved_field *uf;
204 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
205 mcode = *((u4 *) (sp + 3 * 8));
206 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
208 /* calculate and set the new return address */
211 *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
213 /* get the fieldinfo */
215 if (!(fi = resolve_field_eager(uf)))
218 /* patch back original code */
220 *((u4 *) ra) = mcode;
222 /* if we show disassembly, we have to skip the nop */
224 if (opt_showdisassemble)
227 /* patch the field's offset */
229 *((u4 *) ra) |= (s2) (fi->offset & 0x0000ffff);
231 /* synchronize instruction cache */
233 md_icacheflush(NULL, 0);
239 /* patcher_aconst **************************************************************
243 <patched call postition>
244 a61bff80 ldq a0,-128(pv)
246 *******************************************************************************/
248 bool patcher_aconst(u1 *sp)
252 constant_classref *cr;
257 /* get stuff from the stack */
259 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
260 mcode = *((u4 *) (sp + 3 * 8));
261 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
262 disp = *((s4 *) (sp + 1 * 8));
263 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
265 /* calculate and set the new return address */
268 *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
270 /* get the classinfo */
272 if (!(c = resolve_classref_eager(cr)))
275 /* patch back original code */
277 *((u4 *) ra) = mcode;
279 /* synchronize instruction cache */
281 md_icacheflush(NULL, 0);
283 /* patch the classinfo pointer */
285 *((ptrint *) (pv + disp)) = (ptrint) c;
291 /* patcher_builtin_multianewarray **********************************************
295 <patched call position>
296 a63bff80 ldq a1,-128(pv)
298 a77bff78 ldq pv,-136(pv)
301 *******************************************************************************/
303 bool patcher_builtin_multianewarray(u1 *sp)
307 constant_classref *cr;
312 /* get stuff from the stack */
314 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
315 mcode = *((u4 *) (sp + 3 * 8));
316 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
317 disp = *((s4 *) (sp + 1 * 8));
318 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
320 /* calculate and set the new return address */
323 *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
325 /* get the classinfo */
327 if (!(c = resolve_classref_eager(cr)))
330 /* patch back original code */
332 *((u4 *) ra) = mcode;
334 /* synchronize instruction cache */
336 md_icacheflush(NULL, 0);
338 /* patch the classinfo pointer */
340 *((ptrint *) (pv + disp)) = (ptrint) c;
346 /* patcher_builtin_arraycheckcast **********************************************
350 <patched call position>
351 a63bfe60 ldq a1,-416(pv)
352 a77bfe58 ldq pv,-424(pv)
355 *******************************************************************************/
357 bool patcher_builtin_arraycheckcast(u1 *sp)
361 constant_classref *cr;
366 /* get stuff from the stack */
368 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
369 mcode = *((u4 *) (sp + 3 * 8));
370 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
371 disp = *((s4 *) (sp + 1 * 8));
372 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
374 /* calculate and set the new return address */
377 *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
379 /* get the classinfo */
381 if (!(c = resolve_classref_eager(cr)))
384 /* patch back original code */
386 *((u4 *) ra) = mcode;
388 /* synchronize instruction cache */
390 md_icacheflush(NULL, 0);
392 /* patch the classinfo pointer */
394 *((ptrint *) (pv + disp)) = (ptrint) c;
400 /* patcher_invokestatic_special ************************************************
404 <patched call position>
405 a77bffa8 ldq pv,-88(pv)
408 ******************************************************************************/
410 bool patcher_invokestatic_special(u1 *sp)
414 unresolved_method *um;
419 /* get stuff from the stack */
421 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
422 mcode = *((u4 *) (sp + 3 * 8));
423 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
424 disp = *((s4 *) (sp + 1 * 8));
425 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
427 /* calculate and set the new return address */
430 *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
432 /* get the fieldinfo */
434 if (!(m = resolve_method_eager(um)))
437 /* patch back original code */
439 *((u4 *) ra) = mcode;
441 /* synchronize instruction cache */
443 md_icacheflush(NULL, 0);
445 /* patch stubroutine */
447 *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
453 /* patcher_invokevirtual *******************************************************
457 <patched call position>
458 a7900000 ldq at,0(a0)
459 a77c0100 ldq pv,256(at)
462 *******************************************************************************/
464 bool patcher_invokevirtual(u1 *sp)
468 unresolved_method *um;
471 /* get stuff from the stack */
473 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
474 mcode = *((u4 *) (sp + 3 * 8));
475 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
477 /* calculate and set the new return address */
480 *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
482 /* get the fieldinfo */
484 if (!(m = resolve_method_eager(um)))
487 /* patch back original code */
489 *((u4 *) ra) = mcode;
491 /* if we show disassembly, we have to skip the nop */
493 if (opt_showdisassemble)
496 /* patch vftbl index */
498 *((s4 *) (ra + 4)) |= (s4) ((OFFSET(vftbl_t, table[0]) +
499 sizeof(methodptr) * m->vftblindex) & 0x0000ffff);
501 /* synchronize instruction cache */
503 md_icacheflush(NULL, 0);
509 /* patcher_invokeinterface *****************************************************
513 <patched call position>
514 a7900000 ldq at,0(a0)
515 a79cffa0 ldq at,-96(at)
516 a77c0018 ldq pv,24(at)
519 *******************************************************************************/
521 bool patcher_invokeinterface(u1 *sp)
525 unresolved_method *um;
528 /* get stuff from the stack */
530 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
531 mcode = *((u4 *) (sp + 3 * 8));
532 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
534 /* calculate and set the new return address */
537 *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
539 /* get the fieldinfo */
541 if (!(m = resolve_method_eager(um)))
544 /* patch back original code */
546 *((u4 *) ra) = mcode;
548 /* if we show disassembly, we have to skip the nop */
550 if (opt_showdisassemble)
553 /* patch interfacetable index */
555 *((s4 *) (ra + 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
556 sizeof(methodptr*) * m->class->index) & 0x0000ffff);
558 /* patch method offset */
560 *((s4 *) (ra + 4 + 4)) |=
561 (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x0000ffff);
563 /* synchronize instruction cache */
565 md_icacheflush(NULL, 0);
571 /* patcher_checkcast_instanceof_flags ******************************************
575 <patched call position>
577 *******************************************************************************/
579 bool patcher_checkcast_instanceof_flags(u1 *sp)
583 constant_classref *cr;
588 /* get stuff from the stack */
590 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
591 mcode = *((u4 *) (sp + 3 * 8));
592 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
593 disp = *((s4 *) (sp + 1 * 8));
594 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
596 /* calculate and set the new return address */
599 *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
601 /* get the fieldinfo */
603 if (!(c = resolve_classref_eager(cr)))
606 /* patch back original code */
608 *((u4 *) ra) = mcode;
610 /* synchronize instruction cache */
612 md_icacheflush(NULL, 0);
614 /* patch class flags */
616 *((s4 *) (pv + disp)) = (s4) c->flags;
622 /* patcher_checkcast_instanceof_interface **************************************
626 <patched call position>
627 a78e0000 ldq at,0(s5)
628 a3bc001c ldl gp,28(at)
629 23bdfffd lda gp,-3(gp)
630 efa0002e ble gp,0x00000200002bf6b0
631 a7bcffe8 ldq gp,-24(at)
633 *******************************************************************************/
635 bool patcher_checkcast_instanceof_interface(u1 *sp)
639 constant_classref *cr;
642 /* get stuff from the stack */
644 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
645 mcode = *((u4 *) (sp + 3 * 8));
646 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
648 /* calculate and set the new return address */
651 *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
653 /* get the fieldinfo */
655 if (!(c = resolve_classref_eager(cr)))
658 /* patch back original code */
660 *((u4 *) ra) = mcode;
662 /* if we show disassembly, we have to skip the nop */
664 if (opt_showdisassemble)
667 /* patch super class index */
669 *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
671 *((s4 *) (ra + 4 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
672 c->index * sizeof(methodptr*)) & 0x0000ffff);
674 /* synchronize instruction cache */
676 md_icacheflush(NULL, 0);
682 /* patcher_checkcast_instanceof_class ******************************************
686 <patched call position>
687 a7940000 ldq at,0(a4)
688 a7bbff28 ldq gp,-216(pv)
690 *******************************************************************************/
692 bool patcher_checkcast_instanceof_class(u1 *sp)
696 constant_classref *cr;
701 /* get stuff from the stack */
703 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
704 mcode = *((u4 *) (sp + 3 * 8));
705 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
706 disp = *((s4 *) (sp + 1 * 8));
707 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
709 /* calculate and set the new return address */
712 *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
714 /* get the fieldinfo */
716 if (!(c = resolve_classref_eager(cr)))
719 /* patch back original code */
721 *((u4 *) ra) = mcode;
723 /* synchronize instruction cache */
725 md_icacheflush(NULL, 0);
727 /* patch super class' vftbl */
729 *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
735 /* patcher_clinit **************************************************************
739 *******************************************************************************/
741 bool patcher_clinit(u1 *sp)
747 /* get stuff from the stack */
749 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
750 mcode = *((u4 *) (sp + 3 * 8));
751 c = (classinfo *) *((ptrint *) (sp + 2 * 8));
753 /* calculate and set the new return address */
756 *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
758 /* check if the class is initialized */
760 if (!(c->state & CLASS_INITIALIZED))
761 if (!initialize_class(c))
764 /* patch back original code */
766 *((u4 *) ra) = mcode;
768 /* synchronize instruction cache */
770 md_icacheflush(NULL, 0);
776 /* patcher_athrow_areturn ******************************************************
780 <patched call position>
782 *******************************************************************************/
784 #ifdef ENABLE_VERIFIER
785 bool patcher_athrow_areturn(u1 *sp)
789 unresolved_class *uc;
792 /* get stuff from the stack */
794 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
795 mcode = *((u4 *) (sp + 3 * 8));
796 uc = (unresolved_class *) *((ptrint *) (sp + 2 * 8));
798 /* calculate and set the new return address */
801 *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
803 /* resolve the class */
805 if (!resolve_class(uc, resolveEager, false, &c))
808 /* patch back original code */
810 *((u4 *) ra) = mcode;
812 /* synchronize instruction cache */
814 md_icacheflush(NULL, 0);
818 #endif /* ENABLE_VERIFIER */
821 /* patcher_resolve_native ******************************************************
825 *******************************************************************************/
827 #if !defined(WITH_STATIC_CLASSPATH)
828 bool patcher_resolve_native(u1 *sp)
837 /* get stuff from the stack */
839 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
840 mcode = *((u4 *) (sp + 3 * 8));
841 m = (methodinfo *) *((ptrint *) (sp + 2 * 8));
842 disp = *((s4 *) (sp + 1 * 8));
843 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
845 /* calculate and set the new return address */
848 *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
850 /* resolve native function */
852 if (!(f = native_resolve_function(m)))
855 /* patch back original code */
857 *((u4 *) ra) = mcode;
859 /* synchronize instruction cache */
861 md_icacheflush(NULL, 0);
863 /* patch native function pointer */
865 *((ptrint *) (pv + disp)) = (ptrint) f;
869 #endif /* !defined(WITH_STATIC_CLASSPATH) */
873 * These are local overrides for various environment variables in Emacs.
874 * Please do not remove this and leave it at the end of the file, where
875 * Emacs will automagically detect them.
876 * ---------------------------------------------------------------------
879 * indent-tabs-mode: t
883 * vim:noexpandtab:sw=4:ts=4: