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

18 files changed:
src/vm/class.cpp
src/vm/jit/alpha/codegen.c
src/vm/jit/builtin.cpp
src/vm/jit/builtin.hpp
src/vm/jit/emit-common.cpp
src/vm/jit/emit-common.hpp
src/vm/jit/i386/codegen.c
src/vm/jit/i386/codegen.h
src/vm/jit/i386/emit.c
src/vm/jit/i386/emit.h
src/vm/jit/i386/patcher.c
src/vm/jit/x86_64/codegen.c
src/vm/jit/x86_64/codegen.h
src/vm/jit/x86_64/emit.c
src/vm/jit/x86_64/emit.h
src/vm/linker.c
src/vm/linker.h
src/vm/vftbl.hpp

index 1e479529b61ce124f11a7ff33fa9b02a83a24cfe..34c641ded0d9eb67fb4ab36dd00be6b8672cdb1e 100644 (file)
@@ -1480,12 +1480,7 @@ bool class_isanysubclass(classinfo *sub, classinfo *super)
                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;
index 6dab39a3c128dbdfbec147101fa9faf808534992..d44e2f8d16e005a618f278b9c6e39fcbef83d8cf 100644 (file)
@@ -2722,24 +2722,49 @@ gen_method:
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
                                        M_ALD(REG_ITMP3, REG_PV, disp);
 
-                                       M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
-                                       /*                              if (s1 != REG_ITMP1) { */
-                                       /*                                      M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, baseval)); */
-                                       /*                                      M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); */
-                                       /*  #if defined(ENABLE_THREADS) */
-                                       /*                                      codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase); */
-                                       /*  #endif */
-                                       /*                                      M_ISUB(REG_ITMP2, REG_ITMP1, REG_ITMP2); */
-
-                                       /*                              } else { */
-                                       M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
-                                       M_ISUB(REG_ITMP2, REG_ITMP3, REG_ITMP2);
-                                       M_ALD(REG_ITMP3, REG_PV, disp);
-                                       M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
-
-                                       /*                              } */
-                                       M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3);
-                                       emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP3, s1);
+                                       if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
+                                               M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
+                                               M_LADD(REG_ITMP1, REG_ITMP2, REG_ITMP1);
+                                               M_ALD(REG_ITMP1, REG_ITMP1, 0);
+                                               M_CMPEQ(REG_ITMP1, REG_ITMP3, REG_ITMP1);
+                                               emit_label_bnez(cd, BRANCH_LABEL_6, REG_ITMP1);  /* good */
+
+                                               if (super == NULL) {
+                                                       M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
+                                                       M_CMPEQ_IMM(REG_ITMP1, OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1);
+                                                       emit_label_beqz(cd, BRANCH_LABEL_10, REG_ITMP1);  /* throw */
+                                               }
+
+                                               M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
+                                               M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, subtype_depth));
+                                               M_CMPLE(REG_ITMP1, REG_ITMP3, REG_ITMP3);
+                                               emit_label_beqz(cd, BRANCH_LABEL_9, REG_ITMP3);  /* throw */
+                                               /* reload */
+                                               M_ALD(REG_ITMP3, REG_PV, disp);
+                                               M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
+                                               M_S8ADDQ(REG_ITMP1, REG_ITMP2, REG_ITMP2);
+                                               M_ALD(REG_ITMP1, REG_ITMP2, -DISPLAY_SIZE*8);
+                                               M_CMPEQ(REG_ITMP1, REG_ITMP3, REG_ITMP1);
+                                               emit_label_bnez(cd, BRANCH_LABEL_7, REG_ITMP1);  /* 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_INTERN(s1, REG_ZERO, 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_ALD(REG_ITMP2, REG_ITMP2, super->vftbl->subtype_offset);
+                                               M_CMPEQ(REG_ITMP2, REG_ITMP3, REG_ITMP2);
+                                               emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP2, s1);
+                                       }
 
                                        if (super != NULL)
                                                emit_label(cd, BRANCH_LABEL_5);
@@ -2883,15 +2908,53 @@ gen_method:
                                        emit_label_beqz(cd, BRANCH_LABEL_5, s1);
                                }
 
-                               M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
-                               M_ALD(REG_ITMP2, REG_PV, disp);
+                               M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
+                               M_ALD(REG_ITMP3, REG_PV, disp);
+
+                               if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
+                                       M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
+                                       M_LADD(REG_ITMP1, REG_ITMP2, REG_ITMP1);
+                                       M_ALD(REG_ITMP1, REG_ITMP1, 0);
+                                       M_CMPEQ(REG_ITMP1, REG_ITMP3, REG_ITMP1);
+                                       emit_label_beqz(cd, BRANCH_LABEL_8, REG_ITMP1);
+                                       ICONST(d, 1);
+                                       emit_label_br(cd, BRANCH_LABEL_6);  /* true */
+                                       emit_label(cd, BRANCH_LABEL_8);
+
+                                       if (super == NULL) {
+                                               M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
+                                               M_CMPEQ_IMM(REG_ITMP1, OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1);
+                                               emit_label_beqz(cd, BRANCH_LABEL_10, REG_ITMP1);  /* false */
+                                       }
 
-                               M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
-                               M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
-                               M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
+                                       M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
 
-                               M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
-                               M_CMPULE(REG_ITMP1, REG_ITMP2, d);
+                                       M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, subtype_depth));
+                                       M_CMPLE(REG_ITMP1, REG_ITMP3, REG_ITMP3);
+                                       emit_label_beqz(cd, BRANCH_LABEL_9, REG_ITMP3);  /* false */
+                                       /* reload */
+                                       M_ALD(REG_ITMP3, REG_PV, disp);
+                                       M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
+                                       M_S8ADDQ(REG_ITMP1, REG_ITMP2, REG_ITMP2);
+                                       M_ALD(REG_ITMP1, REG_ITMP2, -DISPLAY_SIZE*8);
+                                       M_CMPEQ(REG_ITMP1, REG_ITMP3, d);
+
+                                       if (d == REG_ITMP2)
+                                               emit_label_br(cd, BRANCH_LABEL_7);
+                                       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_ALD(REG_ITMP2, REG_ITMP2, super->vftbl->subtype_offset);
+                                       M_CMPEQ(REG_ITMP2, REG_ITMP3, d);
+                               }
 
                                if (super != NULL)
                                        emit_label(cd, BRANCH_LABEL_5);
index f3ebf0ad7c96900f5821b47c8f770c9885a6300e..06e2d2626779a359e7786a6dbf9adaf0115a37c7 100644 (file)
@@ -728,6 +728,15 @@ bool builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
 
 *******************************************************************************/
 
+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;
@@ -760,8 +769,6 @@ bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
                if (valuevftbl == componentvftbl)
                        return 1;
 
-               linker_classrenumber_mutex->lock();
-
                baseval = componentvftbl->baseval;
 
                if (baseval <= 0) {
@@ -771,11 +778,8 @@ bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
                                          (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} */
@@ -827,8 +831,6 @@ bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o)
        if (valuevftbl == elementvftbl)
                return 1;
 
-       linker_classrenumber_mutex->lock();
-
        baseval = elementvftbl->baseval;
 
        if (baseval <= 0) {
@@ -837,12 +839,9 @@ bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o)
                                  (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;
 }
 
@@ -876,12 +875,7 @@ bool builtin_fast_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
        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;
 }
index 3a7747dc291bf6702747dfd5b0ffec69f1615a05..2797d5a2d13a73947bb7cebe550657000b95d4b7 100644 (file)
@@ -127,6 +127,8 @@ bool builtintable_replace_function(void *iptr);
  * 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 04bdcbba884ea06d04138b0031fffee4e8650b7c..3bc48fa9cca6b8d2edabb5973c78602118d7db38 100644 (file)
@@ -661,6 +661,11 @@ void emit_label_beqz(codegendata *cd, s4 label, s4 reg)
        emit_label_bccz(cd, label, BRANCH_EQ, reg, BRANCH_OPT_NONE);
 }
 
+void emit_label_bnez(codegendata *cd, s4 label, s4 reg)
+{
+       emit_label_bccz(cd, label, BRANCH_NE, reg, BRANCH_OPT_NONE);
+}
+
 #endif /* SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER */
 
 
index 880f633cd648caffac9e3be970f8e3947da0a451..b96bc08ea213fe19a7c355b3dfde5cdf9d8f6ae5 100644 (file)
 #define BRANCH_LABEL_4    4
 #define BRANCH_LABEL_5    5
 #define BRANCH_LABEL_6    6
+#define BRANCH_LABEL_7    7
+#define BRANCH_LABEL_8    8
+#define BRANCH_LABEL_9    9
+#define BRANCH_LABEL_10  10
 
 
 /* constant range macros ******************************************************/
@@ -160,6 +164,7 @@ void emit_label_br(codegendata *cd, s4 label);
 
 #if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
 void emit_label_beqz(codegendata *cd, s4 label, s4 reg);
+void emit_label_bnez(codegendata *cd, s4 label, s4 reg);
 #endif
 
 #if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
index b7e808cabc8f7ecaa927bb0ea5b0bb89c9e6e26a..bdedf5b6459f6c813c9f85ff1099689106b164ad 100644 (file)
@@ -3231,37 +3231,50 @@ 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);
 
-                                       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);
@@ -3404,24 +3417,61 @@ 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_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);
index 2efb24532981093b2619f8ef40198b84ae0c039c..ef28c246583b33a92fcc18363a20281d8f8e91ba 100644 (file)
 
 #define M_ISUB_IMM_MEMABS(a,b)  emit_alu_imm_memabs(cd, ALU_SUB, (a), (b))
 
+#define M_IINC(a)               emit_inc_reg(cd, (a))
+
 #define M_IADDC(a,b)            emit_alu_reg_reg(cd, ALU_ADC, (a), (b))
 #define M_ISUBB(a,b)            emit_alu_reg_reg(cd, ALU_SBB, (a), (b))
 
 
 #define M_CMP(a,b)              emit_alu_reg_reg(cd, ALU_CMP, (a), (b))
 #define M_CMP_MEMBASE(a,b,c)    emit_alu_membase_reg(cd, ALU_CMP, (a), (b), (c))
+#define M_CMP_MEMINDEX(a,b,c,d,e)    emit_alu_memindex_reg(cd, ALU_CMP, (b), (a), (c), (d), (e))
 
 #define M_CMP_IMM(a,b)          emit_alu_imm_reg(cd, ALU_CMP, (a), (b))
 #define M_CMP_IMM_MEMBASE(a,b,c) emit_alu_imm_membase(cd, ALU_CMP, (a), (b), (c))
 #define M_CALL_IMM(a)           emit_call_imm(cd, (a))
 #define M_RET                   M_BYTE1(0xc3)
 
+#define M_ICMP_IMM(a,b)         emit_alu_imm_reg(cd, ALU_CMP, (a), (b))
+
 #define M_BEQ(a)                emit_jcc(cd, CC_E, (a))
 #define M_BNE(a)                emit_jcc(cd, CC_NE, (a))
 #define M_BLT(a)                emit_jcc(cd, CC_L, (a))
 #define M_BNS(a)                emit_jcc(cd, CC_NS, (a))
 #define M_BS(a)                 emit_jcc(cd, CC_S, (a))
 
+#define M_SETE(a)               emit_setcc_reg(cd, CC_E, (a))
+
 #define M_JMP(a)                emit_jmp_reg(cd, (a))
 #define M_JMP_IMM(a)            emit_jmp_imm(cd, (a))
 
index ca730f3b60a944af9ec7af715c3196a8bb11b25f..c3bf7e4eebdbd6a314776363d80a4aebcaba3de5 100644 (file)
@@ -458,9 +458,15 @@ void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 r
                case BRANCH_LE:
                        M_BGT(6);
                        break;
+               case BRANCH_GE:
+                       M_BLT(6);
+                       break;
                case BRANCH_EQ:
                        M_BNE(6);
                        break;
+               case BRANCH_NE:
+                       M_BEQ(6);
+                       break;
                case BRANCH_ULE:
                        M_BBE(6);
                        break;
@@ -1084,6 +1090,11 @@ void emit_alu_imm_memabs(codegendata *cd, s4 opc, s4 imm, s4 disp)
        }
 }
 
+void emit_alu_memindex_reg(codegendata *cd, s4 opc, s4 disp, s4 basereg, s4 indexreg, s4 scale, s4 reg)
+{
+       *(cd->mcodeptr++) = (((u1) (opc)) << 3) + 3;
+       emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
+}
 
 void emit_test_reg_reg(codegendata *cd, s4 reg, s4 dreg)
 {
@@ -1104,6 +1115,12 @@ void emit_test_imm_reg(codegendata *cd, s4 imm, s4 reg)
 /*
  * inc, dec operations
  */
+void emit_inc_reg(codegendata *cd, s4 reg)
+{
+       *(cd->mcodeptr++) = 0xff;
+       emit_reg(0,(reg));
+}
+
 void emit_dec_mem(codegendata *cd, s4 mem)
 {
        *(cd->mcodeptr++) = 0xff;
index 56bd05a6547aa1b9ac10b18319d4055ed7dbdfc5..a99eaeeb386c471a5b496f9b3ba67d2c9860ce0f 100644 (file)
@@ -187,6 +187,8 @@ void emit_alu_imm_reg(codegendata *cd, s4 opc, s4 imm, s4 reg);
 void emit_alu_imm32_reg(codegendata *cd, s4 opc, s4 imm, s4 reg);
 void emit_alu_imm_membase(codegendata *cd, s4 opc, s4 imm, s4 basereg, s4 disp);
 void emit_alu_imm_memabs(codegendata *cd, s4 opc, s4 imm, s4 disp);
+void emit_alu_memindex_reg(codegendata *cd, s4 opc, s4 disp, s4 basereg, s4 indexreg, s4 scale, s4 reg);
+void emit_inc_reg(codegendata *cd, s4 reg);
 void emit_test_reg_reg(codegendata *cd, s4 reg, s4 dreg);
 void emit_test_imm_reg(codegendata *cd, s4 imm, s4 dreg);
 void emit_dec_mem(codegendata *cd, s4 mem);
index b2297fcd2cf0b801bb941b9d32a1b43fef024b5b..5b00e789ab59176011c4818968732ee2a4cb23db 100644 (file)
@@ -633,7 +633,6 @@ bool patcher_checkcast_class(patchref_t *pr)
        /* patch super class' vftbl */
 
        *((ptrint *) (ra + 1)) = (ptrint) c->vftbl;
-       *((ptrint *) (ra + 5 + 6 + 6 + 2 + 1)) = (ptrint) c->vftbl;
 
        return true;
 }
index c2cbea33fb035eb017d512e0ec0540e6992cc246..ff7bf884adf8c04bf84fa4e75f8dba34c68e03af 100644 (file)
@@ -2567,30 +2567,41 @@ gen_method:
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
                                        M_ALD(REG_ITMP3, RIP, disp);
 
-                                       M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
-
-                                       /*                                      if (s1 != REG_ITMP1) { */
-                                       /*                                              emit_movl_membase_reg(cd, REG_ITMP3, */
-                                       /*                                                                                              OFFSET(vftbl_t, baseval), */
-                                       /*                                                                                              REG_ITMP1); */
-                                       /*                                              emit_movl_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); */
-
-                                       /*                                      } else { */
-
-                                       M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
-                                       M_ISUB(REG_ITMP3, REG_ITMP2);
-                                       M_ALD(REG_ITMP3, RIP, disp);
-                                       M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
-                                       /*                                      } */
-
-                                       M_ICMP(REG_ITMP3, REG_ITMP2);
-                                       emit_classcast_check(cd, iptr, BRANCH_UGT, REG_ITMP3, s1);
+                                       if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
+                                               M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
+                                               M_LCMP_MEMINDEX(REG_ITMP2, 0, REG_ITMP1, 0, REG_ITMP3);
+                                               emit_label_beq(cd, BRANCH_LABEL_6);  /* good */
+
+                                               if (super == NULL) {
+                                                       M_LCMP_IMM(OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1);
+                                                       emit_label_bne(cd, BRANCH_LABEL_10);  /* throw */
+                                               }
+
+                                               M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
+                                               M_ICMP_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_LCMP_MEMINDEX(REG_ITMP2, -8*DISPLAY_SIZE, REG_ITMP1, 3, 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_LCMP_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);
@@ -2730,17 +2741,55 @@ gen_method:
                                        disp = dseg_add_address(cd, super->vftbl);
                                }
 
-                               M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
-                               M_ALD(REG_ITMP2, RIP, disp);
+                               M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
+                               M_ALD(REG_ITMP3, RIP, disp);
+
+                               if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
+                                       M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
+                                       M_LCMP_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_LINC(d);
+                                       emit_label_br(cd, BRANCH_LABEL_6);  /* true */
+                                       emit_label(cd, BRANCH_LABEL_8);
+
+                                       if (super == NULL) {
+                                               M_LCMP_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_ICMP_MEMBASE(REG_ITMP2, OFFSET(vftbl_t, subtype_depth), REG_ITMP1);
+                                       emit_label_bgt(cd, BRANCH_LABEL_9);  /* false */
 
-                               M_ISUB(REG_ITMP2, REG_ITMP1);
-                               M_CLR(d); /* may be REG_ITMP2 */
-                               M_ICMP(REG_ITMP3, REG_ITMP1);
-                               M_SETULE(d);
+                                       M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
+                                       M_LCMP_MEMINDEX(REG_ITMP2, -8*DISPLAY_SIZE, REG_ITMP1, 3, 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_LCMP_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);
index 53e005f2cf60d4beaaae2b7e379ef0177641a8e9..cb073729dd0d69d438a67e1263d05e340a0d4f3a 100644 (file)
 #define M_LMUL_IMM(a,b,c)       emit_imul_imm_reg_reg(cd, (b), (a), (c))
 
 #define M_IINC(a)               emit_incl_reg(cd, (a))
+#define M_LINC(a)               emit_incq_reg(cd, (a))
 #define M_IDEC(a)               emit_decl_reg(cd, (a))
 
 #define M_ALD(a,b,disp) \
 #define M_LCMP_IMM(a,b)         emit_alu_imm_reg(cd, ALU_CMP, (a), (b))
 #define M_LCMP_IMM_MEMBASE(a,b,c) emit_alu_imm_membase(cd, ALU_CMP, (a), (b), (c))
 #define M_LCMP_MEMBASE(a,b,c)   emit_alu_membase_reg(cd, ALU_CMP, (a), (b), (c))
+#define M_LCMP_MEMINDEX(a,b,c,d,e) emit_alul_memindex_reg(cd, ALU_CMP, (b), (a), (c), (d), (e))
 
 #define M_ICMP(a,b)             emit_alul_reg_reg(cd, ALU_CMP, (a), (b))
 #define M_ICMP_IMM(a,b)         emit_alul_imm_reg(cd, ALU_CMP, (a), (b))
 #define M_ICMP_IMM32(a,b)       emit_alul_imm32_reg(cd, ALU_CMP, (a), (b))
 #define M_ICMP_IMM_MEMBASE(a,b,c) emit_alul_imm_membase(cd, ALU_CMP, (a), (b), (c))
 #define M_ICMP_MEMBASE(a,b,c)   emit_alul_membase_reg(cd, ALU_CMP, (a), (b), (c))
+#define M_ICMP_MEMINDEX(a,b,c,d,e) emit_alu_memindex_reg(cd, ALU_CMP, (b), (a), (c), (d), (e))
 
 #define M_BEQ(disp)             emit_jcc(cd, CC_E, (disp))
 #define M_BNE(disp)             emit_jcc(cd, CC_NE, (disp))
 #define M_BUGE(disp)            emit_jcc(cd, CC_AE, (disp))
 #define M_BUGT(disp)            emit_jcc(cd, CC_A, (disp))
 
+#define M_SETE(a)               emit_setcc_reg(cd, CC_E, (a))
 #define M_SETNE(a)              emit_setcc_reg(cd, CC_NE, (a))
 #define M_SETULE(a)             emit_setcc_reg(cd, CC_BE, (a))
 
 
 #define M_JMP(a)                emit_jmp_reg(cd, (a))
 #define M_JMP_IMM(a)            emit_jmp_imm(cd, (a))
+#define M_JMP_IMM2(a)           emit_jmp_imm2(cd, (a))
 #define M_CALL(a)               emit_call_reg(cd, (a))
 #define M_CALL_IMM(a)           emit_call_imm(cd, (a))
 #define M_RET                   M_BYTE1(0xc3)
 #define M_RDTSC                 emit_rdtsc(cd)
 
 #define M_IINC_MEMBASE(a,b)     emit_incl_membase(cd, (a), (b))
+#define M_LINC_MEMBASE(a,b)     emit_incq_membase(cd, (a), (b))
 
 #define M_IADD_MEMBASE(a,b,c)   emit_alul_reg_membase(cd, ALU_ADD, (a), (b), (c))
 #define M_IADC_MEMBASE(a,b,c)   emit_alul_reg_membase(cd, ALU_ADC, (a), (b), (c))
index 906a01e89d213e52f76d8435c77c2949852174c2..9c777fb54a558b0545c5177ea11a2fdea6107ae3 100644 (file)
@@ -359,9 +359,15 @@ void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 r
                case BRANCH_LE:
                        M_BGT(8);
                        break;
+               case BRANCH_GE:
+                       M_BLT(8);
+                       break;
                case BRANCH_EQ:
                        M_BNE(8);
                        break;
+               case BRANCH_NE:
+                       M_BEQ(8);
+                       break;
                case BRANCH_UGT:
                        M_BULE(8);
                        break;
@@ -1395,6 +1401,19 @@ void emit_alul_imm_membase(codegendata *cd, s8 opc, s8 imm, s8 basereg, s8 disp)
        }
 }
 
+void emit_alu_memindex_reg(codegendata *cd, s8 opc, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 reg)
+{
+       emit_rex(1,(reg),(indexreg),(basereg));
+       *(cd->mcodeptr++) = (((opc)) << 3) + 3;
+       emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
+}
+
+void emit_alul_memindex_reg(codegendata *cd, s8 opc, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 reg)
+{
+       emit_rex(0,(reg),(indexreg),(basereg));
+       *(cd->mcodeptr++) = (((opc)) << 3) + 3;
+       emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
+}
 
 void emit_test_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
        emit_rex(1,(reg),0,(dreg));
@@ -1446,6 +1465,18 @@ void emit_leal_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 reg) {
 }
 
 
+void emit_incl_reg(codegendata *cd, s8 reg)
+{
+       *(cd->mcodeptr++) = 0xff;
+       emit_reg(0,(reg));
+}
+
+void emit_incq_reg(codegendata *cd, s8 reg)
+{
+       emit_rex(1,0,0,(reg));
+       *(cd->mcodeptr++) = 0xff;
+       emit_reg(0,(reg));
+}
 
 void emit_incl_membase(codegendata *cd, s8 basereg, s8 disp)
 {
@@ -1454,6 +1485,13 @@ void emit_incl_membase(codegendata *cd, s8 basereg, s8 disp)
        emit_membase(cd, (basereg),(disp),0);
 }
 
+void emit_incq_membase(codegendata *cd, s8 basereg, s8 disp)
+{
+       emit_rex(1,0,0,(basereg));
+       *(cd->mcodeptr++) = 0xff;
+       emit_membase(cd, (basereg),(disp),0);
+}
+
 
 
 void emit_cltd(codegendata *cd) {
@@ -1686,6 +1724,18 @@ void emit_jmp_imm(codegendata *cd, s8 imm) {
        emit_imm32((imm));
 }
 
+/* like emit_jmp_imm but allows 8 bit optimization */
+void emit_jmp_imm2(codegendata *cd, s8 imm) {
+       if (IS_IMM8(imm)) {
+               *(cd->mcodeptr++) = 0xeb;
+               emit_imm8((imm));
+       }
+       else {
+               *(cd->mcodeptr++) = 0xe9;
+               emit_imm32((imm));
+       }
+}
+
 
 void emit_jmp_reg(codegendata *cd, s8 reg) {
        emit_rex(0,0,0,(reg));
index 1669fd52046742272e7478993237ad9713227bf8..4a1cb4c9884a8998b53b94a92ec8c6321a13abee 100644 (file)
@@ -244,6 +244,8 @@ void emit_alul_imm32_reg(codegendata *cd, s4 opc, s4 imm, s4 dreg);
 void emit_alul_imm_reg(codegendata *cd, s8 opc, s8 imm, s8 dreg);
 void emit_alu_imm_membase(codegendata *cd, s8 opc, s8 imm, s8 basereg, s8 disp);
 void emit_alul_imm_membase(codegendata *cd, s8 opc, s8 imm, s8 basereg, s8 disp);
+void emit_alu_memindex_reg(codegendata *cd, s8 opc, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 reg);
+void emit_alul_memindex_reg(codegendata *cd, s8 opc, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 reg);
 void emit_test_reg_reg(codegendata *cd, s8 reg, s8 dreg);
 void emit_testl_reg_reg(codegendata *cd, s8 reg, s8 dreg);
 void emit_test_imm_reg(codegendata *cd, s8 imm, s8 reg);
@@ -252,7 +254,10 @@ void emit_testb_imm_reg(codegendata *cd, s8 imm, s8 reg);
 void emit_lea_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 reg);
 void emit_leal_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 reg);
 
+void emit_incl_reg(codegendata *cd, s8 reg);
+void emit_incq_reg(codegendata *cd, s8 reg);
 void emit_incl_membase(codegendata *cd, s8 basereg, s8 disp);
+void emit_incq_membase(codegendata *cd, s8 basereg, s8 disp);
 
 void emit_cltd(codegendata *cd);
 void emit_cqto(codegendata *cd);
index e5883f0911d25fe8d1ac5967c3ab5f1495295084..346ce8e1e0ca9c07dd853ca370b47790d843c63a 100644 (file)
@@ -94,8 +94,6 @@ classinfo *resolve_classref_or_classinfo_eager(classref_or_classinfo cls, bool c
 static s4 interfaceindex;       /* sequential numbering of interfaces         */
 static s4 classvalue;
 
-Mutex *linker_classrenumber_mutex;
-
 
 /* private functions **********************************************************/
 
@@ -122,12 +120,6 @@ void linker_preinit(void)
 
        interfaceindex = 0;
 
-#if defined(ENABLE_THREADS)
-       /* create the global mutex */
-
-       linker_classrenumber_mutex = Mutex_new();
-#endif
-
        /* Link the most basic classes. */
 
        if (!link_class(class_java_lang_Object))
@@ -524,6 +516,68 @@ static bool linker_overwrite_method(methodinfo *mg,
        
 *******************************************************************************/
 
+static int build_display_inner(classinfo *topc, classinfo *c, int i)
+{
+       int depth;
+       if (!c)
+               return 0;
+       do {
+               if (c->vftbl->arraydesc)
+               {
+                       arraydescriptor *a = c->vftbl->arraydesc;
+                       if (a->elementvftbl && a->elementvftbl->clazz->super)
+                       {
+                               classinfo *cls = a->elementvftbl->clazz->super;
+                               int n;
+                               for (n=0; n<a->dimension; n++)
+                                       cls = class_array_of(cls, true);
+                               depth = build_display_inner(topc, cls, i+1);
+                               break;
+                       }
+                       if (a->componentvftbl && a->elementvftbl)
+                       {
+                               depth = build_display_inner(topc, a->componentvftbl->clazz, i+1);
+                               break;
+                       }
+               }
+               depth = build_display_inner(topc, c->super, i+1);
+       } while (false);
+       if (depth >= DISPLAY_SIZE)
+       {
+               if (depth == DISPLAY_SIZE)
+               {
+                       topc->vftbl->subtype_overflow = malloc(sizeof(void*) * (i+1));
+#if defined(ENABLE_STATISTICS)
+                       if (opt_stat)
+                               count_vftbl_len += sizeof(void*) * (i+1);
+#endif
+               }
+               topc->vftbl->subtype_overflow[depth - DISPLAY_SIZE] = c->vftbl;
+               return depth + 1;
+       }
+       topc->vftbl->subtype_display[depth] = c->vftbl;
+       return depth + 1;
+}
+
+static void build_display(classinfo *c)
+{
+       int depth;
+       int i;
+
+       depth = build_display_inner(c, c, 0) - 1;
+       c->vftbl->subtype_depth = depth;
+       if (depth >= DISPLAY_SIZE)
+       {
+               c->vftbl->subtype_offset = OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]);
+       }
+       else
+       {
+               c->vftbl->subtype_offset = OFFSET(vftbl_t, subtype_display[0]) + sizeof(void*) * depth;
+               for (i=depth+1; i<=DISPLAY_SIZE; i++)
+                       c->vftbl->subtype_display[i] = NULL;
+       }
+}
+
 static classinfo *link_class_intern(classinfo *c)
 {
        classinfo *super;             /* super class                              */
@@ -918,8 +972,11 @@ static classinfo *link_class_intern(classinfo *c)
 
        linker_compute_subclasses(c);
 
+       /* FIXME: this is completely useless now */
        RT_TIMING_GET_TIME(time_subclasses);
 
+       build_display(c);
+
        /* revert the linking state and class is linked */
 
        c->state = (c->state & ~CLASS_LINKING) | CLASS_LINKED;
@@ -1119,11 +1176,11 @@ static arraydescriptor *link_array(classinfo *c)
 
 static void linker_compute_subclasses(classinfo *c)
 {
-       Mutex_lock(linker_classrenumber_mutex);
 
        if (!(c->flags & ACC_INTERFACE)) {
                c->nextsub = NULL;
                c->sub     = NULL;
+               c->vftbl->baseval = 1; /* so it does not look like an interface */
        }
 
        if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
@@ -1133,11 +1190,6 @@ static void linker_compute_subclasses(classinfo *c)
 
        classvalue = 0;
 
-       /* compute class values */
-
-       linker_compute_class_values(class_java_lang_Object);
-
-       Mutex_unlock(linker_classrenumber_mutex);
 }
 
 
index 43dce68ed02be70d55cde024277bbcf992c9defd..7f4c6326f675eff953952ab5d0234d083265b967 100644 (file)
@@ -61,14 +61,6 @@ struct arraydescriptor {
 };
 
 
-/* global variables ***********************************************************/
-
-/* This lock must be taken while renumbering classes or while atomically      */
-/* accessing classes.                                                         */
-
-extern Mutex *linker_classrenumber_mutex;
-
-
 /* function prototypes ********************************************************/
 
 #ifdef __cplusplus
index ace6dc7346ee4fde35288c2fdc5e675b66524d29..6f5bed5f53fb5fd41b929e675f5fa8e4496371c9 100644 (file)
@@ -94,6 +94,8 @@ typedef struct _vftbl vftbl_t;
 #include "vm/class.hpp"
 #include "vm/references.h"
 
+#define DISPLAY_SIZE 4
+
 struct _vftbl {
        methodptr   *interfacetable[1];    /* interface table (access via macro)  */
        classinfo   *clazz;                /* class, the vtbl belongs to          */
@@ -103,6 +105,12 @@ struct _vftbl {
        s4           baseval;              /* base for runtime type check         */
                                           /* (-index for interfaces)             */
        s4           diffval;              /* high - base for runtime type check  */
+
+       s4 subtype_depth;
+       s4 subtype_offset;
+       struct _vftbl *subtype_display[DISPLAY_SIZE+1];  /* the last one is cache */
+       struct _vftbl **subtype_overflow;
+
        s4          *interfacevftbllength; /* length of interface vftbls          */
        methodptr    table[1];             /* class vftbl                         */
 };