* Merged in twisti-branch.
[cacao.git] / src / vm / jit / x86_64 / patcher.c
index ce9df0711b5a579756c6115699e9797962ace2e0..ef812b982cd2936121450e8ce45ff876d12c3d5a 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/x86_64/patcher.c - x86_64 code patching functions
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-
-   Changes:
-
-   $Id: patcher.c 5142 2006-07-17 09:47:02Z twisti $
+   $Id: patcher.c 7590 2007-03-28 18:54:02Z twisti $
 
 */
 
 #include "vm/jit/x86_64/codegen.h"
 
 #include "mm/memory.h"
+
 #include "native/native.h"
+
 #include "vm/builtin.h"
-#include "vm/class.h"
 #include "vm/exceptions.h"
-#include "vm/field.h"
 #include "vm/initialize.h"
-#include "vm/options.h"
-#include "vm/references.h"
-#include "vm/resolve.h"
+
 #include "vm/jit/patcher.h"
+#include "vm/jit/stacktrace.h"
+
+#include "vmcore/class.h"
+#include "vmcore/field.h"
+#include "vmcore/options.h"
+#include "vmcore/references.h"
+#include "vm/resolve.h"
 
 
 /* patcher_wrapper *************************************************************
@@ -99,7 +98,7 @@ java_objectheader *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
 
        /* RA is passed as NULL, but the XPC is correct and can be used in
           stacktrace_create_extern_stackframeinfo for
-          md_codegen_findmethod. */
+          md_codegen_get_pv_from_pc. */
 
        stacktrace_create_extern_stackframeinfo(&sfi, pv, sp + 6 * 8, xpc, xpc);
 
@@ -144,7 +143,6 @@ bool patcher_get_putstatic(u1 *sp)
        unresolved_field *uf;
        s4                disp;
        fieldinfo        *fi;
-       s4                offset;
 
        /* get stuff from the stack */
 
@@ -170,16 +168,12 @@ bool patcher_get_putstatic(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 5;
 
-       /* get RIP offset from machine instruction */
-
-       offset = *((u4 *) (ra + 3));
+       /* patch the field value's address */
 
-       /* patch the field value's address (+ 7: is the size of the RIP move) */
-
-       *((ptrint *) (ra + 7 + offset)) = (ptrint) &(fi->value);
+       *((ptrint *) (ra + 7 + disp)) = (ptrint) &(fi->value);
 
        return true;
 }
@@ -220,7 +214,7 @@ bool patcher_get_putfield(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 5;
 
        /* patch the field's offset: we check for the field type, because the     */
@@ -284,7 +278,7 @@ bool patcher_putfieldconst(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 5;
 
        /* patch the field's offset */
@@ -347,7 +341,7 @@ bool patcher_aconst(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 5;
 
        /* patch the classinfo pointer */
@@ -395,17 +389,13 @@ bool patcher_builtin_multianewarray(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 5;
 
        /* patch the classinfo pointer */
 
        *((ptrint *) (ra + 10 + 2)) = (ptrint) c;
 
-       /* patch new function address */
-
-       *((ptrint *) (ra + 10 + 10 + 3 + 2)) = (ptrint) BUILTIN_multianewarray;
-
        return true;
 }
 
@@ -445,7 +435,7 @@ bool patcher_builtin_arraycheckcast(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 5;
 
        /* patch the classinfo pointer */
@@ -471,6 +461,7 @@ bool patcher_invokestatic_special(u1 *sp)
        u1                *ra;
        u8                 mcode;
        unresolved_method *um;
+       s4                 disp;
        methodinfo        *m;
 
        /* get stuff from the stack */
@@ -478,6 +469,7 @@ bool patcher_invokestatic_special(u1 *sp)
        ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
        mcode =                       *((u8 *)     (sp + 3 * 8));
        um    = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
+       disp  =                       *((s4 *)     (sp + 1 * 8));
 
        /* get the fieldinfo */
 
@@ -490,12 +482,13 @@ bool patcher_invokestatic_special(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_showdisassemble)
-               ra = ra + 5;
+       if (opt_shownops)
+               ra = ra + PATCHER_CALL_SIZE;
 
        /* patch stubroutine */
 
-       *((ptrint *) (ra + 2)) = (ptrint) m->stubroutine;
+/*     *((ptrint *) (ra + 2)) = (ptrint) m->stubroutine; */
+       *((ptrint *) (ra + 7 + disp)) = (ptrint) m->stubroutine;
 
        return true;
 }
@@ -536,7 +529,7 @@ bool patcher_invokevirtual(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 5;
 
        /* patch vftbl index */
@@ -584,7 +577,7 @@ bool patcher_invokeinterface(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 5;
 
        /* patch interfacetable index */
@@ -636,7 +629,7 @@ bool patcher_checkcast_instanceof_flags(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 5;
 
        /* patch class flags */
@@ -647,20 +640,20 @@ bool patcher_checkcast_instanceof_flags(u1 *sp)
 }
 
 
-/* patcher_checkcast_instanceof_interface **************************************
+/* patcher_checkcast_interface *************************************************
 
    Machine code:
 
    <patched call position>
    45 8b 9a 1c 00 00 00             mov    0x1c(%r10),%r11d
-   49 81 eb 00 00 00 00             sub    $0x0,%r11
-   4d 85 db                         test   %r11,%r11
-   0f 8e 94 04 00 00                jle    0x00002aaaaab018f8
+   41 81 fb 00 00 00 00             cmp    $0x0,%r11d
+   0f 8f 08 00 00 00                jg     0x00002aaaaae511d5
+   48 8b 0c 25 03 00 00 00          mov    0x3,%rcx
    4d 8b 9a 00 00 00 00             mov    0x0(%r10),%r11
 
 *******************************************************************************/
 
-bool patcher_checkcast_instanceof_interface(u1 *sp)
+bool patcher_checkcast_interface(u1 *sp)
 {
        u1                *ra;
        u8                 mcode;
@@ -684,14 +677,14 @@ bool patcher_checkcast_instanceof_interface(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_showdisassemble)
-               ra = ra + 5;
+       if (opt_shownops)
+               ra = ra + PATCHER_CALL_SIZE;
 
        /* patch super class index */
 
        *((s4 *) (ra + 7 + 3)) = (s4) c->index;
 
-       *((s4 *) (ra + 7 + 7 + 3 + 6 + 3)) =
+       *((s4 *) (ra + 7 + 7 + 6 + 8 + 3)) =
                (s4) (OFFSET(vftbl_t, interfacetable[0]) -
                          c->index * sizeof(methodptr*));
 
@@ -736,7 +729,7 @@ bool patcher_checkcast_class(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 5;
 
        /* patch super class' vftbl */
@@ -748,6 +741,57 @@ bool patcher_checkcast_class(u1 *sp)
 }
 
 
+/* patcher_instanceof_interface ************************************************
+
+   Machine code:
+
+   <patched call position>
+   45 8b 9a 1c 00 00 00             mov    0x1c(%r10),%r11d
+   41 81 fb 00 00 00 00             cmp    $0x0,%r11d
+   0f 8e 94 04 00 00                jle    0x00002aaaaab018f8
+   4d 8b 9a 00 00 00 00             mov    0x0(%r10),%r11
+
+*******************************************************************************/
+
+bool patcher_instanceof_interface(u1 *sp)
+{
+       u1                *ra;
+       u8                 mcode;
+       constant_classref *cr;
+       classinfo         *c;
+
+       /* get stuff from the stack */
+
+       ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
+       mcode =                       *((u8 *)     (sp + 3 * 8));
+       cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
+
+       /* get the fieldinfo */
+
+       if (!(c = resolve_classref_eager(cr)))
+               return false;
+
+       /* patch back original code */
+
+       *((u8 *) ra) = mcode;
+
+       /* if we show disassembly, we have to skip the nop's */
+
+       if (opt_shownops)
+               ra = ra + PATCHER_CALL_SIZE;
+
+       /* patch super class index */
+
+       *((s4 *) (ra + 7 + 3)) = (s4) c->index;
+
+       *((s4 *) (ra + 7 + 7 + 6 + 3)) =
+               (s4) (OFFSET(vftbl_t, interfacetable[0]) -
+                         c->index * sizeof(methodptr*));
+
+       return true;
+}
+
+
 /* patcher_instanceof_class ****************************************************
 
    Machine code:
@@ -781,7 +825,7 @@ bool patcher_instanceof_class(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 5;
 
        /* patch super class' vftbl */
@@ -844,7 +888,6 @@ bool patcher_athrow_areturn(u1 *sp)
        u1               *ra;
        u8                mcode;
        unresolved_class *uc;
-       classinfo        *c;
 
        /* get stuff from the stack */
 
@@ -852,9 +895,9 @@ bool patcher_athrow_areturn(u1 *sp)
        mcode =                      *((u8 *)     (sp + 3 * 8));
        uc    = (unresolved_class *) *((ptrint *) (sp + 2 * 8));
 
-       /* resolve the class */
+       /* resolve the class and check subtype constraints */
 
-       if (!resolve_class(uc, resolveEager, false, &c))
+       if (!resolve_class_eager_no_access_check(uc))
                return false;
 
        /* patch back original code */
@@ -901,7 +944,7 @@ bool patcher_resolve_native(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 5;
 
        /* patch native function pointer */