1 /* src/vm/jit/alpha/patcher.c - Alpha code patching functions
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 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., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Christian Thalinger
31 $Id: patcher.c 3571 2005-11-04 17:17:36Z twisti $
39 #include "mm/memory.h"
40 #include "native/native.h"
41 #include "vm/builtin.h"
43 #include "vm/initialize.h"
44 #include "vm/options.h"
45 #include "vm/references.h"
46 #include "vm/resolve.h"
47 #include "vm/jit/asmpart.h"
48 #include "vm/jit/patcher.h"
51 /* patcher_get_putstatic *******************************************************
55 <patched call position>
56 a73bff98 ldq t11,-104(pv)
57 a2590000 ldl a2,0(t11)
59 *******************************************************************************/
61 bool patcher_get_putstatic(u1 *sp)
71 /* get stuff from the stack */
73 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
74 o = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
75 mcode = *((u4 *) (sp + 3 * 8));
76 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
77 disp = *((s4 *) (sp + 1 * 8));
78 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
80 /* calculate and set the new return address */
83 *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
87 /* get the fieldinfo */
89 if (!(fi = resolve_field_eager(uf))) {
95 /* check if the field's class is initialized */
97 if (!fi->class->initialized) {
98 if (!initialize_class(fi->class)) {
105 /* patch back original code */
107 *((u4 *) ra) = mcode;
109 /* synchronize instruction cache */
111 asm_sync_instruction_cache();
113 /* patch the field value's address */
115 *((ptrint *) (pv + disp)) = (ptrint) &(fi->value);
117 PATCHER_MARK_PATCHED_MONITOREXIT;
123 /* patcher_get_putfield ********************************************************
127 <patched call position>
128 a2af0020 ldl a5,32(s6)
130 *******************************************************************************/
132 bool patcher_get_putfield(u1 *sp)
135 java_objectheader *o;
137 unresolved_field *uf;
140 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
141 o = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
142 mcode = *((u4 *) (sp + 3 * 8));
143 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
145 /* calculate and set the new return address */
148 *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
150 PATCHER_MONITORENTER;
152 /* get the fieldinfo */
154 if (!(fi = resolve_field_eager(uf))) {
160 /* patch back original code */
162 *((u4 *) ra) = mcode;
164 /* if we show disassembly, we have to skip the nop */
166 if (opt_showdisassemble)
169 /* patch the field's offset */
171 *((u4 *) ra) |= (s2) (fi->offset & 0x0000ffff);
173 /* synchronize instruction cache */
175 asm_sync_instruction_cache();
177 PATCHER_MARK_PATCHED_MONITOREXIT;
183 /* patcher_builtin_new *********************************************************
187 a61bff80 ldq a0,-128(pv)
188 <patched call postition>
189 a77bff78 ldq pv,-136(pv)
192 NOTICE: Only the displacement for the function address is passed,
193 but the address of the classinfo pointer is one below (above, in
194 addresses speaking). This is for sure.
196 *******************************************************************************/
198 bool patcher_builtin_new(u1 *sp)
201 java_objectheader *o;
203 constant_classref *cr;
208 /* get stuff from the stack */
210 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
211 o = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
212 mcode = *((u4 *) (sp + 3 * 8));
213 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
214 disp = *((s4 *) (sp + 1 * 8));
215 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
217 /* calculate and set the new return address */
220 *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
222 PATCHER_MONITORENTER;
224 /* get the classinfo */
226 if (!(c = resolve_classref_eager_nonabstract(cr))) {
232 /* patch back original code */
234 *((u4 *) (ra + 4)) = mcode;
236 /* synchronize instruction cache */
238 asm_sync_instruction_cache();
240 /* patch the classinfo pointer */
242 *((ptrint *) (pv + (disp + SIZEOF_VOID_P))) = (ptrint) c;
244 /* patch new function address */
246 *((ptrint *) (pv + disp)) = (ptrint) BUILTIN_new;
248 PATCHER_MARK_PATCHED_MONITOREXIT;
254 /* patcher_builtin_newarray ****************************************************
258 a63bff88 ldq a1,-120(pv)
259 <patched call position>
260 a77bff80 ldq pv,-128(pv)
263 NOTICE: Only the displacement for the function address is passed,
264 but the address of the classinfo pointer is one below (above, in
265 addresses speaking). This is for sure.
267 *******************************************************************************/
269 bool patcher_builtin_newarray(u1 *sp)
272 java_objectheader *o;
274 constant_classref *cr;
279 /* get stuff from the stack */
281 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
282 o = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
283 mcode = *((u4 *) (sp + 3 * 8));
284 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
285 disp = *((s4 *) (sp + 1 * 8));
286 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
288 /* calculate and set the new return address */
291 *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
293 PATCHER_MONITORENTER;
295 /* get the classinfo */
297 if (!(c = resolve_classref_eager(cr))) {
303 /* patch back original code */
305 *((u4 *) (ra + 4)) = mcode;
307 /* synchronize instruction cache */
309 asm_sync_instruction_cache();
311 /* patch the classinfo pointer */
313 *((ptrint *) (pv + (disp + SIZEOF_VOID_P))) = (ptrint) c;
315 /* patch new function address */
317 *((ptrint *) (pv + disp)) = (ptrint) BUILTIN_newarray;
319 PATCHER_MARK_PATCHED_MONITOREXIT;
325 /* patcher_builtin_multianewarray **********************************************
329 <patched call position>
330 a63bff80 ldq a1,-128(pv)
332 a77bff78 ldq pv,-136(pv)
335 *******************************************************************************/
337 bool patcher_builtin_multianewarray(u1 *sp)
340 java_objectheader *o;
342 constant_classref *cr;
347 /* get stuff from the stack */
349 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
350 o = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
351 mcode = *((u4 *) (sp + 3 * 8));
352 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
353 disp = *((s4 *) (sp + 1 * 8));
354 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
356 /* calculate and set the new return address */
359 *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
361 PATCHER_MONITORENTER;
363 /* get the classinfo */
365 if (!(c = resolve_classref_eager(cr))) {
371 /* patch back original code */
373 *((u4 *) ra) = mcode;
375 /* synchronize instruction cache */
377 asm_sync_instruction_cache();
379 /* patch the classinfo pointer */
381 *((ptrint *) (pv + disp)) = (ptrint) c;
383 PATCHER_MARK_PATCHED_MONITOREXIT;
389 /* patcher_builtin_arraycheckcast **********************************************
393 <patched call position>
394 a63bfe60 ldq a1,-416(pv)
395 a77bfe58 ldq pv,-424(pv)
398 NOTICE: Only the displacement of the vftbl pointer address is
399 passed, but the address of the function pointer is one above
400 (below, in addresses speaking). This is for sure.
402 *******************************************************************************/
404 bool patcher_builtin_arraycheckcast(u1 *sp)
407 java_objectheader *o;
409 constant_classref *cr;
414 /* get stuff from the stack */
416 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
417 o = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
418 mcode = *((u4 *) (sp + 3 * 8));
419 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
420 disp = *((s4 *) (sp + 1 * 8));
421 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
423 /* calculate and set the new return address */
426 *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
428 PATCHER_MONITORENTER;
430 /* get the classinfo */
432 if (!(c = resolve_classref_eager(cr))) {
438 /* patch back original code */
440 *((u4 *) ra) = mcode;
442 /* synchronize instruction cache */
444 asm_sync_instruction_cache();
446 /* patch the classinfo pointer */
448 *((ptrint *) (pv + disp)) = (ptrint) c;
450 /* patch new function address */
452 *((ptrint *) (pv + (disp - SIZEOF_VOID_P))) =
453 (ptrint) BUILTIN_arraycheckcast;
455 PATCHER_MARK_PATCHED_MONITOREXIT;
461 /* patcher_builtin_arrayinstanceof *********************************************
465 a63bfeb0 ldq a1,-336(pv)
466 <patched call position>
467 a77bfea8 ldq pv,-344(pv)
470 NOTICE: Only the displacement for the function address is passed,
471 but the address of the vftbl pointer is one below (above, in
472 addresses speaking). This is for sure.
474 *******************************************************************************/
476 bool patcher_builtin_arrayinstanceof(u1 *sp)
479 java_objectheader *o;
481 constant_classref *cr;
486 /* get stuff from the stack */
488 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
489 o = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
490 mcode = *((u4 *) (sp + 3 * 8));
491 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
492 disp = *((s4 *) (sp + 1 * 8));
493 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
495 /* calculate and set the new return address */
498 *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
500 PATCHER_MONITORENTER;
502 /* get the classinfo */
504 if (!(c = resolve_classref_eager(cr))) {
510 /* patch back original code */
512 *((u4 *) (ra + 4)) = mcode;
514 /* synchronize instruction cache */
516 asm_sync_instruction_cache();
518 /* patch the classinfo pointer */
520 *((ptrint *) (pv + (disp + SIZEOF_VOID_P))) = (ptrint) c;
522 /* patch new function address */
524 *((ptrint *) (pv + disp)) = (ptrint) BUILTIN_arrayinstanceof;
526 PATCHER_MARK_PATCHED_MONITOREXIT;
532 /* patcher_invokestatic_special ************************************************
536 <patched call position>
537 a77bffa8 ldq pv,-88(pv)
540 ******************************************************************************/
542 bool patcher_invokestatic_special(u1 *sp)
545 java_objectheader *o;
547 unresolved_method *um;
552 /* get stuff from the stack */
554 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
555 o = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
556 mcode = *((u4 *) (sp + 3 * 8));
557 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
558 disp = *((s4 *) (sp + 1 * 8));
559 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
561 /* calculate and set the new return address */
564 *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
566 PATCHER_MONITORENTER;
568 /* get the fieldinfo */
570 if (!(m = resolve_method_eager(um))) {
576 /* patch back original code */
578 *((u4 *) ra) = mcode;
580 /* synchronize instruction cache */
582 asm_sync_instruction_cache();
584 /* patch stubroutine */
586 *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
588 PATCHER_MARK_PATCHED_MONITOREXIT;
594 /* patcher_invokevirtual *******************************************************
598 <patched call position>
599 a7900000 ldq at,0(a0)
600 a77c0100 ldq pv,256(at)
603 *******************************************************************************/
605 bool patcher_invokevirtual(u1 *sp)
608 java_objectheader *o;
610 unresolved_method *um;
613 /* get stuff from the stack */
615 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
616 o = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
617 mcode = *((u4 *) (sp + 3 * 8));
618 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
620 /* calculate and set the new return address */
623 *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
625 PATCHER_MONITORENTER;
627 /* get the fieldinfo */
629 if (!(m = resolve_method_eager(um))) {
635 /* patch back original code */
637 *((u4 *) ra) = mcode;
639 /* if we show disassembly, we have to skip the nop */
641 if (opt_showdisassemble)
644 /* patch vftbl index */
646 *((s4 *) (ra + 4)) |= (s4) ((OFFSET(vftbl_t, table[0]) +
647 sizeof(methodptr) * m->vftblindex) & 0x0000ffff);
649 /* synchronize instruction cache */
651 asm_sync_instruction_cache();
653 PATCHER_MARK_PATCHED_MONITOREXIT;
659 /* patcher_invokeinterface *****************************************************
663 <patched call position>
664 a7900000 ldq at,0(a0)
665 a79cffa0 ldq at,-96(at)
666 a77c0018 ldq pv,24(at)
669 *******************************************************************************/
671 bool patcher_invokeinterface(u1 *sp)
674 java_objectheader *o;
676 unresolved_method *um;
679 /* get stuff from the stack */
681 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
682 o = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
683 mcode = *((u4 *) (sp + 3 * 8));
684 um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
686 /* calculate and set the new return address */
689 *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
691 PATCHER_MONITORENTER;
693 /* get the fieldinfo */
695 if (!(m = resolve_method_eager(um))) {
701 /* patch back original code */
703 *((u4 *) ra) = mcode;
705 /* if we show disassembly, we have to skip the nop */
707 if (opt_showdisassemble)
710 /* patch interfacetable index */
712 *((s4 *) (ra + 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
713 sizeof(methodptr*) * m->class->index) & 0x0000ffff);
715 /* patch method offset */
717 *((s4 *) (ra + 4 + 4)) |=
718 (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x0000ffff);
720 /* synchronize instruction cache */
722 asm_sync_instruction_cache();
724 PATCHER_MARK_PATCHED_MONITOREXIT;
730 /* patcher_checkcast_instanceof_flags ******************************************
734 <patched call position>
736 *******************************************************************************/
738 bool patcher_checkcast_instanceof_flags(u1 *sp)
741 java_objectheader *o;
743 constant_classref *cr;
748 /* get stuff from the stack */
750 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
751 o = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
752 mcode = *((u4 *) (sp + 3 * 8));
753 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
754 disp = *((s4 *) (sp + 1 * 8));
755 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
757 /* calculate and set the new return address */
760 *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
762 PATCHER_MONITORENTER;
764 /* get the fieldinfo */
766 if (!(c = resolve_classref_eager(cr))) {
772 /* patch back original code */
774 *((u4 *) ra) = mcode;
776 /* synchronize instruction cache */
778 asm_sync_instruction_cache();
780 /* patch class flags */
782 *((s4 *) (pv + disp)) = (s4) c->flags;
784 PATCHER_MARK_PATCHED_MONITOREXIT;
790 /* patcher_checkcast_instanceof_interface **************************************
794 <patched call position>
795 a78e0000 ldq at,0(s5)
796 a3bc001c ldl gp,28(at)
797 23bdfffd lda gp,-3(gp)
798 efa0002e ble gp,0x00000200002bf6b0
799 a7bcffe8 ldq gp,-24(at)
801 *******************************************************************************/
803 bool patcher_checkcast_instanceof_interface(u1 *sp)
806 java_objectheader *o;
808 constant_classref *cr;
811 /* get stuff from the stack */
813 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
814 o = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
815 mcode = *((u4 *) (sp + 3 * 8));
816 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
818 /* calculate and set the new return address */
821 *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
823 PATCHER_MONITORENTER;
825 /* get the fieldinfo */
827 if (!(c = resolve_classref_eager(cr))) {
833 /* patch back original code */
835 *((u4 *) ra) = mcode;
837 /* if we show disassembly, we have to skip the nop */
839 if (opt_showdisassemble)
842 /* patch super class index */
844 *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
846 *((s4 *) (ra + 4 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
847 c->index * sizeof(methodptr*)) & 0x0000ffff);
849 /* synchronize instruction cache */
851 asm_sync_instruction_cache();
853 PATCHER_MARK_PATCHED_MONITOREXIT;
859 /* patcher_checkcast_instanceof_class ******************************************
863 <patched call position>
864 a7940000 ldq at,0(a4)
865 a7bbff28 ldq gp,-216(pv)
867 *******************************************************************************/
869 bool patcher_checkcast_instanceof_class(u1 *sp)
872 java_objectheader *o;
874 constant_classref *cr;
879 /* get stuff from the stack */
881 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
882 o = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
883 mcode = *((u4 *) (sp + 3 * 8));
884 cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
885 disp = *((s4 *) (sp + 1 * 8));
886 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
888 /* calculate and set the new return address */
891 *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
893 PATCHER_MONITORENTER;
895 /* get the fieldinfo */
897 if (!(c = resolve_classref_eager(cr))) {
903 /* patch back original code */
905 *((u4 *) ra) = mcode;
907 /* synchronize instruction cache */
909 asm_sync_instruction_cache();
911 /* patch super class' vftbl */
913 *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
915 PATCHER_MARK_PATCHED_MONITOREXIT;
921 /* patcher_clinit **************************************************************
925 *******************************************************************************/
927 bool patcher_clinit(u1 *sp)
930 java_objectheader *o;
934 /* get stuff from the stack */
936 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
937 o = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
938 mcode = *((u4 *) (sp + 3 * 8));
939 c = (classinfo *) *((ptrint *) (sp + 2 * 8));
941 /* calculate and set the new return address */
944 *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
946 PATCHER_MONITORENTER;
948 /* check if the class is initialized */
950 if (!c->initialized) {
951 if (!initialize_class(c)) {
958 /* patch back original code */
960 *((u4 *) ra) = mcode;
962 /* synchronize instruction cache */
964 asm_sync_instruction_cache();
966 PATCHER_MARK_PATCHED_MONITOREXIT;
972 /* patcher_athrow_areturn ******************************************************
976 <patched call position>
978 *******************************************************************************/
980 bool patcher_athrow_areturn(u1 *sp)
983 java_objectheader *o;
985 unresolved_class *uc;
988 /* get stuff from the stack */
990 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
991 o = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
992 mcode = *((u4 *) (sp + 3 * 8));
993 uc = (unresolved_class *) *((ptrint *) (sp + 2 * 8));
995 /* calculate and set the new return address */
998 *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
1000 PATCHER_MONITORENTER;
1002 /* resolve the class */
1004 if (!resolve_class(uc, resolveEager, false, &c)) {
1005 PATCHER_MONITOREXIT;
1010 /* patch back original code */
1012 *((u4 *) ra) = mcode;
1014 /* synchronize instruction cache */
1016 asm_sync_instruction_cache();
1018 PATCHER_MARK_PATCHED_MONITOREXIT;
1024 /* patcher_resolve_native ******************************************************
1028 *******************************************************************************/
1030 #if !defined(ENABLE_STATICVM)
1031 bool patcher_resolve_native(u1 *sp)
1034 java_objectheader *o;
1041 /* get stuff from the stack */
1043 ra = (u1 *) *((ptrint *) (sp + 5 * 8));
1044 o = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
1045 mcode = *((u4 *) (sp + 3 * 8));
1046 m = (methodinfo *) *((ptrint *) (sp + 2 * 8));
1047 disp = *((s4 *) (sp + 1 * 8));
1048 pv = (u1 *) *((ptrint *) (sp + 0 * 8));
1050 /* calculate and set the new return address */
1053 *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
1055 PATCHER_MONITORENTER;
1057 /* resolve native function */
1059 if (!(f = native_resolve_function(m))) {
1060 PATCHER_MONITOREXIT;
1065 /* patch back original code */
1067 *((u4 *) ra) = mcode;
1069 /* synchronize instruction cache */
1071 asm_sync_instruction_cache();
1073 /* patch native function pointer */
1075 *((ptrint *) (pv + disp)) = (ptrint) f;
1077 PATCHER_MARK_PATCHED_MONITOREXIT;
1081 #endif /* !defined(ENABLE_STATICVM) */
1085 * These are local overrides for various environment variables in Emacs.
1086 * Please do not remove this and leave it at the end of the file, where
1087 * Emacs will automagically detect them.
1088 * ---------------------------------------------------------------------
1091 * indent-tabs-mode: t
1095 * vim:noexpandtab:sw=4:ts=4: