Merged new changes from default (manually: src/vm/jit/i386/codegen.c).
authorStefan Ring <stefan@complang.tuwien.ac.at>
Sun, 12 Oct 2008 10:26:13 +0000 (12:26 +0200)
committerStefan Ring <stefan@complang.tuwien.ac.at>
Sun, 12 Oct 2008 10:26:13 +0000 (12:26 +0200)
--HG--
branch : subtype-trunk

1  2 
src/vm/class.cpp
src/vm/jit/builtin.cpp
src/vm/jit/builtin.hpp
src/vm/jit/i386/codegen.c
src/vm/jit/i386/patcher.c

diff --combined src/vm/class.cpp
index be2ba45845d1f8b01fc3d3f147369635477a3594,1e479529b61ce124f11a7ff33fa9b02a83a24cfe..34c641ded0d9eb67fb4ab36dd00be6b8672cdb1e
@@@ -51,6 -51,7 +51,7 @@@
  #include "vm/global.h"
  #include "vm/globals.hpp"
  #include "vm/javaobjects.hpp"
+ #include "vm/jit/jitcache.hpp"
  #include "vm/linker.h"
  #include "vm/loader.hpp"
  #include "vm/options.h"
@@@ -176,6 -177,9 +177,9 @@@ classinfo *class_create_classinfo(utf *
  
        if (classname != utf_not_named_yet)
                class_set_packagename(c);
+ #if defined (ENABLE_JITCACHE)
+     c->cache_file_fd = 0;
+ #endif
  
        c->object.header.lockword.init();
  
@@@ -720,6 -724,11 +724,11 @@@ void class_free(classinfo *c
        s4 i;
        vftbl_t *v;
  
+ #if defined(ENABLE_JITCACHE)
+ /* TODO: Find a way around the linker problem */
+ /*    jitcache_freeclass(c);*/
+ #endif
        class_freecpool(c);
  
        if (c->interfaces != NULL)
@@@ -1471,7 -1480,12 +1480,7 @@@ bool class_isanysubclass(classinfo *sub
                if (sub->flags & ACC_INTERFACE)
                        return (super == class_java_lang_Object);
  
 -              linker_classrenumber_mutex->lock();
 -
 -              diffval = sub->vftbl->baseval - super->vftbl->baseval;
 -              result  = diffval <= (uint32_t) super->vftbl->diffval;
 -
 -              linker_classrenumber_mutex->unlock();
 +              result = fast_subtype_check(sub->vftbl, super->vftbl);
        }
  
        return result;
diff --combined src/vm/jit/builtin.cpp
index 1b9ccb99c0eb23d4fc18d6df2d62d6d88b848c41,f3ebf0ad7c96900f5821b47c8f770c9885a6300e..06e2d2626779a359e7786a6dbf9adaf0115a37c7
@@@ -267,6 -267,81 +267,81 @@@ bool builtin_init(void
  }
  
  
+ /* builtintable_get_by_key *****************************************************
+    Returns a key for the given builtintable_entry object which is suitable
+    for retrieving the instance again by calling builtintable_get_by_key.
+    The key can be regarded fixed between multiple runs of the JVM.
+ *******************************************************************************/
+ s4 builtintable_get_key(builtintable_entry *bte)
+ {
+       s4 entries;
+ /*
+       int i;
+       entries = sizeof(builtintable_internal) / sizeof(builtintable_entry) - 1;
+       for (i = 0; i < entries; i++)
+               if (&builtintable_internal[i] == bte)
+                       return i + 1;
+       entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
+       for (i = 0; i < entries; i++)
+               if (&builtintable_automatic[i] == bte)
+                       return -i;
+       entries = sizeof(builtintable_function) / sizeof(builtintable_entry) - 1;
+       for (i = 0; i < entries; i++)
+               if (&builtintable_function[i] == bte)
+                       return -1000 - i;
+ */
+       entries = sizeof(builtintable_internal) / sizeof(builtintable_entry) - 1;
+       if (&builtintable_internal[0] <= bte
+               && &builtintable_internal[entries - 1] >= bte)
+       {
+               return (s4) (bte - &builtintable_internal[0]) + 1;
+       }
+       entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
+       if (&builtintable_automatic[0] <= bte
+               && &builtintable_automatic[entries - 1] >= bte)
+       {
+               return -(s4) (bte - &builtintable_automatic[0]);
+       }
+       entries = sizeof(builtintable_function) / sizeof(builtintable_entry) - 1;
+       if (&builtintable_function[0] <= bte
+               && &builtintable_function[entries - 1] >= bte)
+       {
+               return -1000 - (s4) (bte - &builtintable_function[0]);
+       }
+       /* builtintable_entry is not in our tables. */
+       assert (0);
+       return 0;
+ }
+ /* builtintable_get_by_key *****************************************************
+    Retrieves an entry in the internal and automatic builtin functions tables
+    using a key that was retrived previously with builtintable_get_key()
+ *******************************************************************************/
+ builtintable_entry *builtintable_get_by_key(s4 key)
+ {
+       /* If key is positive it is the index into builtintable_internal. If it is
+        * negative it is the index into builtintable_automatic. If it is <= -1000
+      * it is the index into builtintable_function.
+      */
+       return (key > 0)
+               ? &builtintable_internal[key - 1]
+               : (key > -1000 ? &builtintable_automatic[-key] : &builtintable_function[-(1000 + key)]);
+ }
  /* builtintable_get_internal ***************************************************
  
     Finds an entry in the builtintable for internal functions and
@@@ -653,15 -728,6 +728,15 @@@ bool builtin_canstore(java_handle_objec
  
  *******************************************************************************/
  
 +bool fast_subtype_check(struct _vftbl *s, struct _vftbl *t)
 +{
 +      if (s->subtype_display[t->subtype_depth] == t)
 +              return true;
 +      if (t->subtype_offset != OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]))
 +              return false;
 +      return s->subtype_depth >= t->subtype_depth && s->subtype_overflow[t->subtype_depth - DISPLAY_SIZE] == t;
 +}
 +
  bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
  {
        arraydescriptor *desc;
                if (valuevftbl == componentvftbl)
                        return 1;
  
 -              linker_classrenumber_mutex->lock();
 -
                baseval = componentvftbl->baseval;
  
                if (baseval <= 0) {
                                          (valuevftbl->interfacetable[baseval] != NULL));
                }
                else {
 -                      diffval = valuevftbl->baseval - componentvftbl->baseval;
 -                      result  = diffval <= (uint32_t) componentvftbl->diffval;
 +                      result = fast_subtype_check(valuevftbl, componentvftbl);
                }
 -
 -              linker_classrenumber_mutex->unlock();
        }
        else if (valuedesc == NULL) {
                /* {oa has dimension > 1} */
@@@ -756,6 -827,8 +831,6 @@@ bool builtin_fast_canstore_onedim(java_
        if (valuevftbl == elementvftbl)
                return 1;
  
 -      linker_classrenumber_mutex->lock();
 -
        baseval = elementvftbl->baseval;
  
        if (baseval <= 0) {
                                  (valuevftbl->interfacetable[baseval] != NULL));
        }
        else {
 -              diffval = valuevftbl->baseval - elementvftbl->baseval;
 -              result  = diffval <= (uint32_t) elementvftbl->diffval;
 +              result = fast_subtype_check(valuevftbl, elementvftbl);
        }
  
 -      linker_classrenumber_mutex->unlock();
 -
        return result;
  }
  
@@@ -800,7 -876,12 +875,7 @@@ bool builtin_fast_canstore_onedim_class
        if (valuevftbl == elementvftbl)
                return 1;
  
 -      linker_classrenumber_mutex->lock();
 -
 -      diffval = valuevftbl->baseval - elementvftbl->baseval;
 -      result  = diffval <= (uint32_t) elementvftbl->diffval;
 -
 -      linker_classrenumber_mutex->unlock();
 +      result = fast_subtype_check(valuevftbl, elementvftbl);
  
        return result;
  }
diff --combined src/vm/jit/builtin.hpp
index becb10858e060860736edfc4ecbed268d97920e3,3a7747dc291bf6702747dfd5b0ffec69f1615a05..2797d5a2d13a73947bb7cebe550657000b95d4b7
@@@ -94,6 -94,8 +94,8 @@@ extern "C" 
  
  bool builtin_init(void);
  
+ s4                                    builtintable_get_key(builtintable_entry *);
+ builtintable_entry *builtintable_get_by_key(s4 key);
  builtintable_entry *builtintable_get_internal(functionptr fp);
  builtintable_entry *builtintable_get_automatic(s4 opcode);
  
@@@ -115,7 -117,7 +117,7 @@@ bool builtintable_replace_function(voi
   *
   * IMPORTANT:
   * For each builtin function which is used in a BUILTIN* opcode there
-  * must be an entry in the builtin_desc table in jit/jit.c.
+  * must be an entry in the tables in vm/builtintable.inc.
   *
   * Below each prototype is either the BUILTIN_ macro definition or a
   * comment specifiying that this function is not used in BUILTIN*
   * ICMD_BUILTIN3.)
   */
  
 +bool fast_subtype_check(struct _vftbl *, struct _vftbl *);
 +
  bool builtin_instanceof(java_handle_t *obj, classinfo *c);
  /* NOT AN OP */
  bool builtin_checkcast(java_handle_t *obj, classinfo *c);
index eb6a518c55da4971b4f92b587cffba4dd7fb6a0f,b7e808cabc8f7ecaa927bb0ea5b0bb89c9e6e26a..bdedf5b6459f6c813c9f85ff1099689106b164ad
@@@ -58,6 -58,7 +58,7 @@@
  #include "vm/jit/dseg.h"
  #include "vm/jit/emit-common.hpp"
  #include "vm/jit/jit.hpp"
+ #include "vm/jit/jitcache.hpp"
  #include "vm/jit/linenumbertable.hpp"
  #include "vm/jit/parse.h"
  #include "vm/jit/patcher-common.hpp"
@@@ -134,7 -135,6 +135,6 @@@ 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 */
  
        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       */
  
                /* 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
  
                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);
                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
                                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);
                                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);
                                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) ? (void*) iptr->sx.val.c.cls
+                                                                                                                       : (void*) iptr->sx.val.stringconst);
+                               }
                        }
                        emit_store_dst(jd, iptr, d);
                        break;
                        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;
                                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);
                        }
  
                        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);
                        /* 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) {
  
                        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);
                        /* 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) {
  
                        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);
                                /* 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, 
  
                        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);
                                /* 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, 
                        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);
  
                        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))
                        }
  
                        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:
                        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:
                        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))
                        }
  
                        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:
                        else {
                                fi        = iptr->sx.s23.s3.fmiref->p.field;
                                fieldtype = fi->type;
                                disp      = fi->offset;
                        }
  
                        switch (fieldtype) {
                        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;
  
@@@ -2763,6 -2807,8 +2807,8 @@@ 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 */
  
                                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);
                        }
@@@ -2975,6 -3022,7 +3022,7 @@@ 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)
                                }
                                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;
  
                                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;
  
                                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;
                        }
                                        superindex = super->index;
                                        supervftbl = super->vftbl;
                                }
-                       
                                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);
                                        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);
                                        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);
  
                                        }
  
                                        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);
  
 -                                      M_ILD32(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
 +                                      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 */
  
 -                                      /*                              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); */
 +                                              if (super == NULL) {
 +                                                      M_ICMP_IMM(OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1);
 +                                                      emit_label_bne(cd, BRANCH_LABEL_10);  /* 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_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 */
 +
 +                                              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 */
 +
 +                                              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);
  
 -                                      /*                              } */
 +                                              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);
  
 -                                      M_CMP(REG_ITMP3, REG_ITMP2);
 -                                      emit_classcast_check(cd, iptr, BRANCH_ULE, REG_ITMP3, s1);
 +                                              emit_classcast_check(cd, iptr, BRANCH_NE, REG_ITMP3, s1);
 +                                      }
  
                                        if (super != NULL)
                                                emit_label(cd, BRANCH_LABEL_5);
                                if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                        patcher_add_patch_ref(jd, PATCHER_builtin_arraycheckcast,
                                                                                iptr->sx.s23.s3.c.ref, 0);
+                                       disp = 0;
                                }
+                               else {
+                                       disp = (ptrint) 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);
                                        emit_label_beq(cd, BRANCH_LABEL_3);
                                }
  
                                M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
  
                                if (super == NULL) {
                                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 */ +
                                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); */
                                        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_ITMP2);
 +                              M_MOV_IMM(supervftbl, REG_ITMP3);
+                               JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CLASSINFO_VFTBL, super);
 -                              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_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);
 +
 +                              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);
 +
 +                                      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_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 */
 +
 +                                      M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
 +                                      M_CMP_MEMINDEX(REG_ITMP2, -4*DISPLAY_SIZE, REG_ITMP1, 2, REG_ITMP3);
 +                                      M_SETE(d);
 +                                      if (d == REG_ITMP2) {
 +                                              M_BSEXT(d, 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);
 +
 +                                      M_SETE(d);
 +                                      if (d == REG_ITMP2)
 +                                              M_BSEXT(d, d);
 +                              }
  
                                if (super != NULL)
                                        emit_label(cd, BRANCH_LABEL_5);
                        /* 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 */
  
                        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 */
@@@ -3588,6 -3608,7 +3658,7 @@@ void codegen_emit_stub_native(jitdata *
  
                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
  
index 3eecac97ed221fe0b0a2956aef2876cd1ab686b1,b2297fcd2cf0b801bb941b9d32a1b43fef024b5b..5b00e789ab59176011c4818968732ee2a4cb23db
@@@ -245,7 -245,7 +245,7 @@@ bool patcher_putfieldconst(patchref_t *
  
     Machine code:
  
-    <patched call postition>
+    <patched call position>
     c7 04 24 00 00 00 00       movl   $0x0000000,(%esp)
     b8 00 00 00 00             mov    $0x0000000,%eax
  
@@@ -380,7 -380,7 +380,7 @@@ bool patcher_invokestatic_special(patch
        ra    = (u1 *)                pr->mpc;
        um    = (unresolved_method *) pr->ref;
  
-       /* get the fieldinfo */
+       /* get the methodinfo */
  
        if (!(m = resolve_method_eager(um)))
                return false;
@@@ -633,6 -633,7 +633,6 @@@ bool patcher_checkcast_class(patchref_
        /* patch super class' vftbl */
  
        *((ptrint *) (ra + 1)) = (ptrint) c->vftbl;
 -      *((ptrint *) (ra + 5 + 6 + 6 + 2 + 1)) = (ptrint) c->vftbl;
  
        return true;
  }