Merged branch subtype-trunk into default.
[cacao.git] / src / vm / jit / i386 / codegen.c
index 6c08b9cfb756126d328766c526eda5546a7468ee..8eab0fbf0511a4cce0d56cac92d930db7c06b8ed 100644 (file)
 #include "vm/jit/i386/codegen.h"
 #include "vm/jit/i386/emit.h"
 
-#include "mm/memory.h"
-#include "native/jni.h"
-#include "native/localref.h"
-#include "native/native.h"
+#include "mm/memory.hpp"
 
-#include "threads/lock-common.h"
+#include "native/localref.hpp"
+#include "native/native.hpp"
 
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
+#include "threads/lock.hpp"
+
+#include "vm/jit/builtin.hpp"
+#include "vm/exceptions.hpp"
 #include "vm/global.h"
-#include "vm/primitive.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
+#include "vm/loader.hpp"
+#include "vm/options.h"
+#include "vm/primitive.hpp"
+#include "vm/utf8.h"
+#include "vm/vm.hpp"
 
 #include "vm/jit/abi.h"
 #include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
 #include "vm/jit/dseg.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/linenumbertable.h"
-#include "vm/jit/parse.h"
-#include "vm/jit/patcher-common.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/linenumbertable.hpp"
+#include "vm/jit/parse.hpp"
+#include "vm/jit/patcher-common.hpp"
 #include "vm/jit/reg.h"
-#include "vm/jit/replace.h"
-#include "vm/jit/stacktrace.h"
-
-#include "vm/jit/jitcache.h"
+#include "vm/jit/replace.hpp"
+#include "vm/jit/stacktrace.hpp"
 #include "vm/jit/trap.h"
 
 #if defined(ENABLE_SSA)
 # include "vm/jit/allocator/lsra.h"
 #endif
 
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-#include "vmcore/utf8.h"
-
 
 /* codegen_emit ****************************************************************
 
@@ -138,6 +134,7 @@ bool codegen_emit(jitdata *jd)
        savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
 
        cd->stackframesize = rd->memuse + savedregs_num;
+
           
 #if defined(ENABLE_THREADS)
        /* space to save argument of monitor_enter */
@@ -156,12 +153,7 @@ bool codegen_emit(jitdata *jd)
 
        align_off = cd->stackframesize ? 4 : 0;
 
-#if defined(ENABLE_JITCACHE)
-       disp = dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
-       jitcache_add_cached_ref(code, CRT_CODEINFO, 0, disp);
-#else
        (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
-#endif
        (void) dseg_add_unique_s4(
                cd, cd->stackframesize * 8 + align_off);           /* FrameSize       */
 
@@ -184,8 +176,6 @@ bool codegen_emit(jitdata *jd)
                /* count frequency */
 
                M_MOV_IMM(code, REG_ITMP3);
-               JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CODEINFO, NULL);
-
                M_IADD_IMM_MEMBASE(1, REG_ITMP3, OFFSET(codeinfo, frequency));
        }
 #endif
@@ -364,7 +354,6 @@ bool codegen_emit(jitdata *jd)
 
                if (m->flags & ACC_STATIC) {
                        M_MOV_IMM(&m->clazz->object.header, REG_ITMP1);
-                       JITCACHE_ADD_CACHED_REF_JD(jd, CRT_OBJECT_HEADER, m->clazz);
                }
                else {
                        M_ALD(REG_ITMP1, REG_SP, cd->stackframesize * 8 + 4 + align_off);
@@ -376,8 +365,6 @@ bool codegen_emit(jitdata *jd)
                M_AST(REG_ITMP1, REG_SP, s1 * 8);
                M_AST(REG_ITMP1, REG_SP, 0 * 4);
                M_MOV_IMM(LOCK_monitor_enter, REG_ITMP3);
-               JITCACHE_ADD_CACHED_REF_JD(jd, CRT_BUILTIN_FP,
-                                                         builtintable_get_internal(LOCK_monitor_enter));
                M_CALL(REG_ITMP3);
        }                       
 #endif
@@ -419,9 +406,7 @@ bool codegen_emit(jitdata *jd)
                if (bptr->bitflags & BBFLAG_REPLACEMENT) {
                        if (cd->replacementpoint[-1].flags & RPLPOINT_FLAG_COUNTDOWN) {
                                MCODECHECK(32);
-                               disp = (s4) &(m->hitcountdown);
-                               M_ISUB_IMM_MEMABS(1, disp);
-                               M_BS(0);
+                               emit_trap_countdown(cd, &(m->hitcountdown));
                        }
                }
 #endif
@@ -581,7 +566,6 @@ bool codegen_emit(jitdata *jd)
                                disp = dseg_add_float(cd, iptr->sx.val.f);
                                emit_mov_imm_reg(cd, 0, REG_ITMP1);
                                dseg_adddata(cd);
-                               JITCACHE_ADD_CACHED_REF_JD(jd, CRT_ENTRYPOINT, NULL);
                                emit_flds_membase(cd, REG_ITMP1, disp);
                        }
                        emit_store_dst(jd, iptr, d);
@@ -610,7 +594,6 @@ bool codegen_emit(jitdata *jd)
                                disp = dseg_add_double(cd, iptr->sx.val.d);
                                emit_mov_imm_reg(cd, 0, REG_ITMP1);
                                dseg_adddata(cd);
-                               JITCACHE_ADD_CACHED_REF_JD(jd, CRT_ENTRYPOINT, NULL);
                                emit_fldl_membase(cd, REG_ITMP1, disp);
                        }
                        emit_store_dst(jd, iptr, d);
@@ -630,15 +613,7 @@ bool codegen_emit(jitdata *jd)
                                if (iptr->sx.val.anyptr == NULL)
                                        M_CLR(d);
                                else
-                               {
                                        M_MOV_IMM(iptr->sx.val.anyptr, d);
-                                       JITCACHE_ADD_CACHED_REF_JD(
-                                               jd,
-                                               (iptr->flags.bits & INS_FLAG_CLASS) ? CRT_CLASSINFO
-                                                                                                                       : CRT_STRING,
-                                               (iptr->flags.bits & INS_FLAG_CLASS) ? iptr->sx.val.c.cls
-                                                                                                                       : iptr->sx.val.stringconst);
-                               }
                        }
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1020,7 +995,6 @@ bool codegen_emit(jitdata *jd)
                        M_LST(s1, REG_SP, 0 * 4);
 
                        M_MOV_IMM(bte->fp, REG_ITMP3);
-                       JITCACHE_ADD_CACHED_REF_JD(jd, CRT_BUILTIN_FP, bte);
                        M_CALL(REG_ITMP3);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1588,7 +1562,6 @@ bool codegen_emit(jitdata *jd)
                                disp = dseg_add_unique_s4(cd, 0);
                                emit_mov_imm_reg(cd, 0, REG_ITMP1);
                                dseg_adddata(cd);
-                               JITCACHE_ADD_CACHED_REF_JD(jd, CRT_ENTRYPOINT, NULL);
                                emit_mov_reg_membase(cd, var->vv.regoff, REG_ITMP1, disp);
                                emit_fildl_membase(cd, REG_ITMP1, disp);
                        }
@@ -1618,7 +1591,6 @@ bool codegen_emit(jitdata *jd)
 
                        emit_mov_imm_reg(cd, 0, REG_ITMP1);
                        dseg_adddata(cd);
-                       JITCACHE_ADD_CACHED_REF_JD(jd, CRT_ENTRYPOINT, NULL);
 
                        /* Round to zero, 53-bit mode, exception masked */
                        disp = dseg_add_s4(cd, 0x0e7f);
@@ -1664,8 +1636,6 @@ bool codegen_emit(jitdata *jd)
                        /* XXX: change this when we use registers */
                        emit_flds_membase(cd, REG_SP, var1->vv.regoff);
                        emit_mov_imm_reg(cd, (ptrint) asm_builtin_f2i, REG_ITMP1);
-                       JITCACHE_ADD_CACHED_REF_JD(jd, CRT_BUILTIN_FP,
-                                                                 builtintable_get_internal(BUILTIN_f2i));
                        emit_call_reg(cd, REG_ITMP1);
 
                        if (var->flags & INMEMORY) {
@@ -1683,7 +1653,6 @@ bool codegen_emit(jitdata *jd)
 
                        emit_mov_imm_reg(cd, 0, REG_ITMP1);
                        dseg_adddata(cd);
-                       JITCACHE_ADD_CACHED_REF_JD(jd, CRT_ENTRYPOINT, NULL);
 
                        /* Round to zero, 53-bit mode, exception masked */
                        disp = dseg_add_s4(cd, 0x0e7f);
@@ -1729,8 +1698,6 @@ bool codegen_emit(jitdata *jd)
                        /* XXX: change this when we use registers */
                        emit_fldl_membase(cd, REG_SP, var1->vv.regoff);
                        emit_mov_imm_reg(cd, (ptrint) asm_builtin_d2i, REG_ITMP1);
-                       JITCACHE_ADD_CACHED_REF_JD(jd, CRT_BUILTIN_FP,
-                                                                 builtintable_get_internal(BUILTIN_d2i));
                        emit_call_reg(cd, REG_ITMP1);
 
                        if (var->flags & INMEMORY) {
@@ -1747,7 +1714,6 @@ bool codegen_emit(jitdata *jd)
 
                        emit_mov_imm_reg(cd, 0, REG_ITMP1);
                        dseg_adddata(cd);
-                       JITCACHE_ADD_CACHED_REF_JD(jd, CRT_ENTRYPOINT, NULL);
 
                        /* Round to zero, 53-bit mode, exception masked */
                        disp = dseg_add_s4(cd, 0x0e7f);
@@ -1791,8 +1757,6 @@ bool codegen_emit(jitdata *jd)
                                /* XXX: change this when we use registers */
                                emit_flds_membase(cd, REG_SP, var1->vv.regoff);
                                emit_mov_imm_reg(cd, (ptrint) asm_builtin_f2l, REG_ITMP1);
-                               JITCACHE_ADD_CACHED_REF_JD(jd, CRT_BUILTIN_FP,
-                                                                 builtintable_get_internal(BUILTIN_f2l));
                                emit_call_reg(cd, REG_ITMP1);
                                emit_mov_reg_membase(cd, REG_RESULT, REG_SP, var->vv.regoff);
                                emit_mov_reg_membase(cd, REG_RESULT2, 
@@ -1811,7 +1775,6 @@ bool codegen_emit(jitdata *jd)
 
                        emit_mov_imm_reg(cd, 0, REG_ITMP1);
                        dseg_adddata(cd);
-                       JITCACHE_ADD_CACHED_REF_JD(jd, CRT_ENTRYPOINT, NULL);
 
                        /* Round to zero, 53-bit mode, exception masked */
                        disp = dseg_add_s4(cd, 0x0e7f);
@@ -1854,8 +1817,6 @@ bool codegen_emit(jitdata *jd)
                                /* XXX: change this when we use registers */
                                emit_fldl_membase(cd, REG_SP, var1->vv.regoff);
                                emit_mov_imm_reg(cd, (ptrint) asm_builtin_d2l, REG_ITMP1);
-                               JITCACHE_ADD_CACHED_REF_JD(jd, CRT_BUILTIN_FP,
-                                                                 builtintable_get_internal(BUILTIN_d2l));
                                emit_call_reg(cd, REG_ITMP1);
                                emit_mov_reg_membase(cd, REG_RESULT, REG_SP, var->vv.regoff);
                                emit_mov_reg_membase(cd, REG_RESULT2, 
@@ -2142,8 +2103,6 @@ bool codegen_emit(jitdata *jd)
                        M_AST(s1, REG_SP, 0 * 4);
                        M_AST(s3, REG_SP, 1 * 4);
                        M_MOV_IMM(BUILTIN_FAST_canstore, REG_ITMP1);
-                       JITCACHE_ADD_CACHED_REF_JD(jd, CRT_BUILTIN_FP,
-                                                                 builtintable_get_internal(BUILTIN_FAST_canstore));
                        M_CALL(REG_ITMP1);
                        emit_arraystore_check(cd, iptr);
 
@@ -2232,7 +2191,6 @@ bool codegen_emit(jitdata *jd)
                        else {
                                fi        = iptr->sx.s23.s3.fmiref->p.field;
                                fieldtype = fi->type;
-
                                disp      = (intptr_t) fi->value;
 
                                if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
@@ -2240,7 +2198,6 @@ bool codegen_emit(jitdata *jd)
                        }
 
                        M_MOV_IMM(disp, REG_ITMP1);
-                       JITCACHE_ADD_CACHED_REF_JD_COND(jd, CRT_FIELDINFO_VALUE, fi, disp);
                        switch (fieldtype) {
                        case TYPE_INT:
                        case TYPE_ADR:
@@ -2264,7 +2221,7 @@ bool codegen_emit(jitdata *jd)
                        break;
 
                case ICMD_PUTSTATIC:  /* ..., value  ==> ...                          */
-
+                       
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                uf        = iptr->sx.s23.s3.uf;
                                fieldtype = uf->fieldref->parseddesc.fd->type;
@@ -2275,14 +2232,13 @@ bool codegen_emit(jitdata *jd)
                        else {
                                fi        = iptr->sx.s23.s3.fmiref->p.field;
                                fieldtype = fi->type;
-
                                disp      = (intptr_t) fi->value;
 
                                if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
                                        patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, 0);
                        }
+
                        M_MOV_IMM(disp, REG_ITMP1);
-                       JITCACHE_ADD_CACHED_REF_JD_COND(jd, CRT_FIELDINFO_VALUE, fi, disp);
                        switch (fieldtype) {
                        case TYPE_INT:
                        case TYPE_ADR:
@@ -2318,7 +2274,6 @@ bool codegen_emit(jitdata *jd)
                        else {
                                fi        = iptr->sx.s23.s3.fmiref->p.field;
                                fieldtype = fi->type;
-
                                disp      = (intptr_t) fi->value;
 
                                if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
@@ -2326,7 +2281,6 @@ bool codegen_emit(jitdata *jd)
                        }
 
                        M_MOV_IMM(disp, REG_ITMP1);
-                       JITCACHE_ADD_CACHED_REF_JD_COND(jd, CRT_FIELDINFO_VALUE, fi, disp);
                        switch (fieldtype) {
                        case TYPE_INT:
                        case TYPE_ADR:
@@ -2361,9 +2315,7 @@ bool codegen_emit(jitdata *jd)
                        else {
                                fi        = iptr->sx.s23.s3.fmiref->p.field;
                                fieldtype = fi->type;
-
                                disp      = fi->offset;
-
                        }
 
                        switch (fieldtype) {
@@ -2497,7 +2449,6 @@ bool codegen_emit(jitdata *jd)
                        M_POP(REG_ITMP2_XPC);
 
                        M_MOV_IMM(asm_handle_exception, REG_ITMP3);
-                       JITCACHE_ADD_CACHED_REF_JD(jd, CRT_ASM_HANDLE_EXCEPTION, 1);
                        M_JMP(REG_ITMP3);
                        break;
 
@@ -2812,8 +2763,6 @@ nowperformreturn:
 
                                M_AST(REG_ITMP2, REG_SP, 0);
                                M_MOV_IMM(LOCK_monitor_exit, REG_ITMP3);
-                               JITCACHE_ADD_CACHED_REF_JD(jd, CRT_BUILTIN_FP,
-                                                                 builtintable_get_internal(LOCK_monitor_exit));
                                M_CALL(REG_ITMP3);
 
                                /* and now restore the proper return value */
@@ -2903,7 +2852,6 @@ nowperformreturn:
 
                                M_MOV_IMM(0, REG_ITMP2);
                                dseg_adddata(cd);
-                               JITCACHE_ADD_CACHED_REF_JD(jd, CRT_ENTRYPOINT, NULL);
                                emit_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 2, REG_ITMP1);
                                M_JMP(REG_ITMP1);
                        }
@@ -2939,6 +2887,21 @@ nowperformreturn:
 
                        bte = iptr->sx.s23.s3.bte;
                        md = bte->md;
+
+#if defined(ENABLE_ESCAPE_REASON)
+                       if (bte->fp == BUILTIN_escape_reason_new) {
+                               void set_escape_reasons(void *);
+                               M_ASUB_IMM(8, REG_SP);
+                               M_MOV_IMM(iptr->escape_reasons, REG_ITMP1);
+                               M_AST(EDX, REG_SP, 4);
+                               M_AST(REG_ITMP1, REG_SP, 0);
+                               M_MOV_IMM(set_escape_reasons, REG_ITMP1);
+                               M_CALL(REG_ITMP1);
+                               M_ALD(EDX, REG_SP, 4);
+                               M_AADD_IMM(8, REG_SP);
+                       }
+#endif
+
                        goto gen_method;
 
                case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
@@ -3012,7 +2975,6 @@ gen_method:
                                else {
                                        M_MOV_IMM(bte->stub, REG_ITMP1);
                                }
-                               JITCACHE_ADD_CACHED_REF_JD(jd, CRT_BUILTIN, bte);
                                M_CALL(REG_ITMP1);
 
 #if defined(ENABLE_ESCAPE_CHECK)
@@ -3039,11 +3001,10 @@ gen_method:
                                }
                                else {
                                        disp = (ptrint) lm->stubroutine;
-
                                        d = lm->parseddesc->returntype.type;
                                }
+
                                M_MOV_IMM(disp, REG_ITMP2);
-                               JITCACHE_ADD_CACHED_REF_JD(jd, CRT_METHODINFO_STUBROUTINE, lm);
                                M_CALL(REG_ITMP2);
                                break;
 
@@ -3062,14 +3023,12 @@ gen_method:
                                else {
                                        s1 = OFFSET(vftbl_t, table[0]) +
                                                sizeof(methodptr) * lm->vftblindex;
-
                                        d = md->returntype.type;
                                }
 
                                M_ALD(REG_METHODPTR, REG_ITMP1,
                                          OFFSET(java_object_t, vftbl));
                                M_ALD32(REG_ITMP3, REG_METHODPTR, s1);
-                               JITCACHE_ADD_CACHED_REF_JD(jd, CRT_METHODINFO_TABLE, lm);
                                M_CALL(REG_ITMP3);
                                break;
 
@@ -3098,9 +3057,7 @@ gen_method:
                                M_ALD(REG_METHODPTR, REG_ITMP1,
                                          OFFSET(java_object_t, vftbl));
                                M_ALD32(REG_METHODPTR, REG_METHODPTR, s1);
-                               JITCACHE_ADD_CACHED_REF_JD(jd, CRT_METHODINFO_INTERFACETABLE, lm);
                                M_ALD32(REG_ITMP3, REG_METHODPTR, s2);
-                               JITCACHE_ADD_CACHED_REF_JD(jd, CRT_METHODINFO_METHODOFFSET, lm);
                                M_CALL(REG_ITMP3);
                                break;
                        }
@@ -3157,13 +3114,11 @@ gen_method:
                                        superindex = super->index;
                                        supervftbl = super->vftbl;
                                }
-
-                               if ((super == NULL) || !(super->flags & ACC_INTERFACE))
-                                       CODEGEN_CRITICAL_SECTION_NEW;
-
+                       
                                s1 = emit_load_s1(jd, iptr, REG_ITMP1);
 
                                /* if class is not resolved, check which code to call */
+
                                if (super == NULL) {
                                        M_TEST(s1);
                                        emit_label_beq(cd, BRANCH_LABEL_1);
@@ -3195,7 +3150,6 @@ gen_method:
                                        M_ILD32(REG_ITMP3,
                                                        REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
                                        M_ISUB_IMM32(superindex, REG_ITMP3);
-                                       JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CLASSINFO_INDEX, super);
                                        /* XXX do we need this one? */
                                        M_TEST(REG_ITMP3);
                                        emit_classcast_check(cd, iptr, BRANCH_LE, REG_ITMP3, s1);
@@ -3203,7 +3157,6 @@ gen_method:
                                        M_ALD32(REG_ITMP3, REG_ITMP2,
                                                        OFFSET(vftbl_t, interfacetable[0]) -
                                                        superindex * sizeof(methodptr*));
-                                       JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CLASSINFO_INTERFACETABLE, super);
                                        M_TEST(REG_ITMP3);
                                        emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP3, s1);
 
@@ -3225,41 +3178,49 @@ gen_method:
                                        }
 
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
-
                                        if (super == NULL) {
                                                patcher_add_patch_ref(jd, PATCHER_checkcast_class,
                                                                                        iptr->sx.s23.s3.c.ref,
                                                                                        0);
                                        }
-
                                        M_MOV_IMM(supervftbl, REG_ITMP3);
-                                       JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CLASSINFO_VFTBL, super);
 
-                                       CODEGEN_CRITICAL_SECTION_START;
+                                       if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
+                                               M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
+                                               M_CMP_MEMINDEX(REG_ITMP2, 0, REG_ITMP1, 0, REG_ITMP3);
+                                               emit_label_beq(cd, BRANCH_LABEL_6);  /* good */
 
-                                       M_ILD32(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
+                                               if (super == NULL) {
+                                                       M_ICMP_IMM(OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1);
+                                                       emit_label_bne(cd, BRANCH_LABEL_10);  /* throw */
+                                               }
 
-                                       /*                              if (s1 != REG_ITMP1) { */
-                                       /*                                      emit_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, baseval), REG_ITMP1); */
-                                       /*                                      emit_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, diffval), REG_ITMP3); */
-                                       /* #if defined(ENABLE_THREADS) */
-                                       /*                                      codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); */
-                                       /* #endif */
-                                       /*                                      emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP1, REG_ITMP2); */
+                                               M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
+                                               M_CMP_MEMBASE(REG_ITMP2, OFFSET(vftbl_t, subtype_depth), REG_ITMP1);
+                                               emit_label_bgt(cd, BRANCH_LABEL_9);  /* throw */
 
-                                       /*                              } else { */
-                                       M_ILD32(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
-                                       M_ISUB(REG_ITMP3, REG_ITMP2);
-                                       M_MOV_IMM(supervftbl, REG_ITMP3);
-                                       JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CLASSINFO_VFTBL, super);
-                                       M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
+                                               M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
+                                               M_CMP_MEMINDEX(REG_ITMP2, -4*DISPLAY_SIZE, REG_ITMP1, 2, REG_ITMP3);
+                                               emit_label_beq(cd, BRANCH_LABEL_7);  /* good */
 
-                                       CODEGEN_CRITICAL_SECTION_END;
+                                               emit_label(cd, BRANCH_LABEL_9);
+                                               if (super == NULL)
+                                                       emit_label(cd, BRANCH_LABEL_10);
 
-                                       /*                              } */
+                                               /* reload s1, might have been destroyed */
+                                               emit_load_s1(jd, iptr, REG_ITMP1);
+                                               M_ALD_MEM(s1, TRAP_ClassCastException);
 
-                                       M_CMP(REG_ITMP3, REG_ITMP2);
-                                       emit_classcast_check(cd, iptr, BRANCH_ULE, REG_ITMP3, s1);
+                                               emit_label(cd, BRANCH_LABEL_7);
+                                               emit_label(cd, BRANCH_LABEL_6);
+                                               /* reload s1, might have been destroyed */
+                                               emit_load_s1(jd, iptr, REG_ITMP1);
+                                       }
+                                       else {
+                                               M_CMP_MEMBASE(REG_ITMP2, super->vftbl->subtype_offset, REG_ITMP3);
+
+                                               emit_classcast_check(cd, iptr, BRANCH_NE, REG_ITMP3, s1);
+                                       }
 
                                        if (super != NULL)
                                                emit_label(cd, BRANCH_LABEL_5);
@@ -3281,18 +3242,10 @@ gen_method:
                                if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                        patcher_add_patch_ref(jd, PATCHER_builtin_arraycheckcast,
                                                                                iptr->sx.s23.s3.c.ref, 0);
-                                       disp = 0;
-                               }
-                               else {
-                                       disp = iptr->sx.s23.s3.c.cls;
                                }
 
-                               M_AST_IMM(disp, REG_SP, 1 * 4);
-                               JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CLASSINFO, disp);
-
+                               M_AST_IMM(iptr->sx.s23.s3.c.cls, REG_SP, 1 * 4);
                                M_MOV_IMM(BUILTIN_arraycheckcast, REG_ITMP3);
-                               JITCACHE_ADD_CACHED_REF_JD(jd, CRT_BUILTIN_FP,
-                                                                          builtintable_get_internal(BUILTIN_arraycheckcast));
                                M_CALL(REG_ITMP3);
 
                                s1 = emit_load_s1(jd, iptr, REG_ITMP2);
@@ -3324,9 +3277,6 @@ gen_method:
                                supervftbl = super->vftbl;
                        }
                        
-                       if ((super == NULL) || !(super->flags & ACC_INTERFACE))
-                               CODEGEN_CRITICAL_SECTION_NEW;
-
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
 
@@ -3359,7 +3309,6 @@ gen_method:
                                        emit_label_beq(cd, BRANCH_LABEL_3);
                                }
 
-
                                M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
 
                                if (super == NULL) {
@@ -3370,8 +3319,6 @@ gen_method:
                                M_ILD32(REG_ITMP3,
                                                REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
                                M_ISUB_IMM32(superindex, REG_ITMP3);
-                               JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CLASSINFO_INDEX, super);
-
                                M_TEST(REG_ITMP3);
 
                                disp = (2 + 4 /* mov_membase32_reg */ + 2 /* test */ +
@@ -3381,7 +3328,6 @@ gen_method:
                                M_ALD32(REG_ITMP1, REG_ITMP1,
                                                OFFSET(vftbl_t, interfacetable[0]) -
                                                superindex * sizeof(methodptr*));
-                               JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CLASSINFO_INTERFACETABLE, super);
                                M_TEST(REG_ITMP1);
 /*                                     emit_setcc_reg(cd, CC_A, d); */
 /*                                     emit_jcc(cd, CC_BE, 5); */
@@ -3405,28 +3351,72 @@ gen_method:
                                        emit_label_beq(cd, BRANCH_LABEL_5);
                                }
 
-                               M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
-
+                               M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
                                if (super == NULL) {
                                        patcher_add_patch_ref(jd, PATCHER_instanceof_class,
                                                                                iptr->sx.s23.s3.c.ref, 0);
                                }
+                               M_MOV_IMM(supervftbl, REG_ITMP3);
+
+                               if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
+                                       M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
+                                       M_CMP_MEMINDEX(REG_ITMP2, 0, REG_ITMP1, 0, REG_ITMP3);
+                                       emit_label_bne(cd, BRANCH_LABEL_8); /* jump over INC/SETE */
+                                       if (d == REG_ITMP2) {
+                                               M_SETE(d);
+                                               M_BSEXT(d, d);
+                                       } else
+                                               M_IINC(d);
+                                       emit_label_br(cd, BRANCH_LABEL_6);  /* true */
+                                       emit_label(cd, BRANCH_LABEL_8);
 
-                               M_MOV_IMM(supervftbl, REG_ITMP2);
-                               JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CLASSINFO_VFTBL, super);
-                               CODEGEN_CRITICAL_SECTION_START;
+                                       if (super == NULL) {
+                                               M_ICMP_IMM(OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1);
+                                               emit_label_bne(cd, BRANCH_LABEL_10);  /* false */
+                                       }
 
-                               M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
-                               M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, diffval));
-                               M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
+                                       M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
+                                       M_CMP_MEMBASE(REG_ITMP2, OFFSET(vftbl_t, subtype_depth), REG_ITMP1);
+                                       emit_label_bgt(cd, BRANCH_LABEL_9);  /* false */
 
-                               CODEGEN_CRITICAL_SECTION_END;
+                                       M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
+                                       M_CMP_MEMINDEX(REG_ITMP2, -4*DISPLAY_SIZE, REG_ITMP1, 2, REG_ITMP3);
+                                       if (d >= 4) {
+                                               M_SETE(REG_ITMP1);
+                                               M_BSEXT(REG_ITMP1, d);
+                                       }
+                                       else {
+                                               M_SETE(d);
+                                               if (d == REG_ITMP2) {
+                                                       M_BSEXT(d, d);
 
-                               M_ISUB(REG_ITMP2, REG_ITMP1);
-                               M_CLR(d);                                 /* may be REG_ITMP2 */
-                               M_CMP(REG_ITMP3, REG_ITMP1);
-                               M_BA(5);
-                               M_MOV_IMM(1, d);
+                                                       emit_label_br(cd, BRANCH_LABEL_7); /* jump over M_CLR */
+                                               }
+                                       }
+
+                                       emit_label(cd, BRANCH_LABEL_9);
+                                       if (super == NULL)
+                                               emit_label(cd, BRANCH_LABEL_10);
+                                       if (d == REG_ITMP2) {
+                                               M_CLR(d);
+
+                                               emit_label(cd, BRANCH_LABEL_7);
+                                       }
+                                       emit_label(cd, BRANCH_LABEL_6);
+                               }
+                               else {
+                                       M_CMP_MEMBASE(REG_ITMP2, super->vftbl->subtype_offset, REG_ITMP3);
+
+                                       if (d >= 4) {
+                                               M_SETE(REG_ITMP1);
+                                               M_BSEXT(REG_ITMP1, d);
+                                       }
+                                       else {
+                                               M_SETE(d);
+                                               if (d == REG_ITMP2)
+                                                       M_BSEXT(d, d);
+                                       }
+                               }
 
                                if (super != NULL)
                                        emit_label(cd, BRANCH_LABEL_5);
@@ -3481,7 +3471,6 @@ gen_method:
                        /* a1 = arraydescriptor */
 
                        M_IST_IMM(disp, REG_SP, 1 * 4);
-                       JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CLASSINFO, disp);
 
                        /* a2 = pointer to dimensions = stack pointer */
 
@@ -3490,8 +3479,6 @@ gen_method:
                        M_AST(REG_ITMP1, REG_SP, 2 * 4);
 
                        M_MOV_IMM(BUILTIN_multianewarray, REG_ITMP1);
-                       JITCACHE_ADD_CACHED_REF_JD(jd, CRT_BUILTIN_FP,
-                                                                 builtintable_get_internal(BUILTIN_multianewarray));
                        M_CALL(REG_ITMP1);
 
                        /* check for exception before result assignment */
@@ -3613,7 +3600,6 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int s
 
                M_MOV_IMM(code, REG_ITMP1);
                M_IADD_IMM_MEMBASE(1, REG_ITMP1, OFFSET(codeinfo, frequency));
-               JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CODEINFO, 0);
        }
 #endif
 
@@ -3695,7 +3681,7 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int s
 
                /* put env into first argument */
 
-               M_AST_IMM(_Jv_env, REG_SP, 0 * 4);
+               M_AST_IMM(VM_get_jnienv(), REG_SP, 0 * 4);
        }
 
        /* Call the native function. */
@@ -3711,7 +3697,7 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int s
        switch (md->returntype.type) {
        case TYPE_INT:
        case TYPE_ADR:
-               switch (md->returntype.decltype) {
+               switch (md->returntype.primitivetype) {
                case PRIMITIVETYPE_BOOLEAN:
                        M_BZEXT(REG_RESULT, REG_RESULT);
                        break;