Merged PR72 fix.
authorStefan Ring <stefan@complang.tuwien.ac.at>
Mon, 15 Sep 2008 06:59:32 +0000 (08:59 +0200)
committerStefan Ring <stefan@complang.tuwien.ac.at>
Mon, 15 Sep 2008 06:59:32 +0000 (08:59 +0200)
--HG--
branch : subtype

src/cacaoh/dummy.c
src/vm/builtin.c
src/vm/builtin.h
src/vm/jit/emit-common.h
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/vmcore/class.c
src/vmcore/linker.c
src/vmcore/linker.h

index 82c994a2eab6e89703e6e074617bc811ca44475b..6e10e3992b69a89460ab2f34f175178703d00367 100644 (file)
@@ -160,6 +160,12 @@ java_handle_t *builtin_clone(void *env, java_handle_t *o)
        return NULL;
 }
 
+bool fast_subtype_check(struct _vftbl *s, struct _vftbl *t)
+{
+       vm_abort("fast_subtype_check: Not implemented.");
+       return 0;
+}
+
 bool builtin_isanysubclass(classinfo *sub, classinfo *super)
 {
        vm_abort("builtin_isanysubclass: Not implemented.");
index 86ba2e5469a3e06713fa99320f4d0261b315ce6e..4162a6b560e22ae7841cf7e77cf3200eca9326ef 100644 (file)
@@ -667,6 +667,19 @@ bool builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
 
 *******************************************************************************/
 
+bool fast_subtype_check(struct _vftbl *s, struct _vftbl *t)
+{
+       int i;
+       if (s->subtype_display[t->subtype_depth] == t)
+               return true;
+       if (t->subtype_offset != OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]))
+               return false;
+       for (i=0; i<s->subtype_overflow_length; i++)
+               if (s->subtype_overflow[i] == t)
+                       return true;
+       return false;
+}
+
 bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
 {
        arraydescriptor *desc;
@@ -699,8 +712,6 @@ bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
                if (valuevftbl == componentvftbl)
                        return 1;
 
-               LOCK_MONITOR_ENTER(linker_classrenumber_lock);
-
                baseval = componentvftbl->baseval;
 
                if (baseval <= 0) {
@@ -710,11 +721,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);
                }
-
-               LOCK_MONITOR_EXIT(linker_classrenumber_lock);
        }
        else if (valuedesc == NULL) {
                /* {oa has dimension > 1} */
@@ -766,8 +774,6 @@ bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o)
        if (valuevftbl == elementvftbl)
                return 1;
 
-       LOCK_MONITOR_ENTER(linker_classrenumber_lock);
-
        baseval = elementvftbl->baseval;
 
        if (baseval <= 0) {
@@ -776,12 +782,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);
        }
 
-       LOCK_MONITOR_EXIT(linker_classrenumber_lock);
-
        return result;
 }
 
@@ -815,12 +818,7 @@ bool builtin_fast_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
        if (valuevftbl == elementvftbl)
                return 1;
 
-       LOCK_MONITOR_ENTER(linker_classrenumber_lock);
-
-       diffval = valuevftbl->baseval - elementvftbl->baseval;
-       result  = diffval <= (uint32_t) elementvftbl->diffval;
-
-       LOCK_MONITOR_EXIT(linker_classrenumber_lock);
+       result = fast_subtype_check(valuevftbl, elementvftbl);
 
        return result;
 }
index af6fd824aeabf0d1af65c85853413f502e1e9733..773d5c21785afd1c5a25d3276f2fdc27f3e91626 100644 (file)
@@ -120,6 +120,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 *class);
 /* NOT AN OP */
 bool builtin_checkcast(java_handle_t *obj, classinfo *class);
index 34fa5ada147f7abe820421a611c2390f2e544e8d..2707b270ab43e2fbd94973efc5c6d5da97a8158b 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 ******************************************************/
index b81fd9486ecc4f6fdfbd9ef92758e260cb925f5d..5ef87728158078f3e54854a7c9fbfb8702c79ba3 100644 (file)
@@ -2487,6 +2487,8 @@ gen_method:
                                classinfo *super;
                                s4         superindex;
 
+                               s4 looptarget;
+
                                if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                        super      = NULL;
                                        superindex = 0;
@@ -2496,9 +2498,6 @@ gen_method:
                                        superindex = super->index;
                                }
 
-                               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 */
@@ -2571,34 +2570,67 @@ gen_method:
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
                                        M_ALD(REG_ITMP3, RIP, disp);
 
-                                       CODEGEN_CRITICAL_SECTION_START;
+                                       if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
+                                       M_AADD_IMM(-32, REG_SP); /* need some stack */
+                                       if (s1 == REG_ITMP1)
+                                               M_AST(REG_ITMP1, REG_SP, -8 + 32);
 
-                                       M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
+                                       M_ALD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
 
-                                       /*                                      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); */
+                                       *(cd->mcodeptr++) = 0x4d;
+                                       *(cd->mcodeptr++) = 0x3b;
+                                       *(cd->mcodeptr++) = 0x1c;
+                                       *(cd->mcodeptr++) = 0x02;
+                                       /* cmp (ITMP2, ITMP1, 1), ITMP3 */
 
-                                       /*                                      } else { */
+                                       emit_label_beq(cd, BRANCH_LABEL_6);  /* good */
 
-                                       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_LCMP_IMM(OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1);
+                                       emit_classcast_check(cd, iptr, BRANCH_NE, REG_ITMP3, s1);
+
+                                       M_AST(REG_ITMP3, REG_SP, -16 + 32);
+                                       M_AST_IMM32(0, REG_SP, -24 + 32);
+                                       M_ALD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
+                                       looptarget = cd->mcodeptr - cd->mcodebase;
+
+                                       M_ALD(REG_ITMP3, REG_SP, -24 + 32);
+                                       M_ICMP_MEMBASE(REG_ITMP2, OFFSET(vftbl_t, subtype_overflow_length), REG_ITMP3);
+                                       emit_label_bge(cd, BRANCH_LABEL_9);  /* throw */
+
+                                       *(cd->mcodeptr++) = 0x4e;
+                                       *(cd->mcodeptr++) = 0x8b;
+                                       *(cd->mcodeptr++) = 0x1c;
+                                       *(cd->mcodeptr++) = 0xd8;
+                                       /* movq (ITMP1, ITMP3, 8), ITMP3 */
 
-                                       CODEGEN_CRITICAL_SECTION_END;
+                                       M_LCMP_MEMBASE(REG_SP, -16 + 32, REG_ITMP3);
+                                       emit_label_beq(cd, BRANCH_LABEL_7);  /* good */
 
-                                       M_ICMP(REG_ITMP3, REG_ITMP2);
-                                       emit_classcast_check(cd, iptr, BRANCH_UGT, REG_ITMP3, s1);
+                                       M_LINC_MEMBASE(REG_SP, -24 + 32);
+                                       M_JMP_IMM2(looptarget - (cd->mcodeptr - cd->mcodebase) - 2); /* 1 byte displacement */
+
+                                       emit_label(cd, BRANCH_LABEL_9);
+                                       M_AADD_IMM(32, REG_SP); /* restore stack frame */
+                                       M_ALD_MEM(REG_ITMP3, TRAP_ClassCastException);
+
+                                       emit_label(cd, BRANCH_LABEL_7);
+
+                                       emit_label(cd, BRANCH_LABEL_6);
+
+                                       if (s1 == REG_ITMP1)
+                                               M_ALD(REG_ITMP1, REG_SP, -8 + 32);
+                                       M_AADD_IMM(32, REG_SP);
+                                       }
+                                       else {
+                                               assert(super->vftbl->subtype_offset < 0x80);
+                                               *(cd->mcodeptr++) = 0x4d;
+                                               *(cd->mcodeptr++) = 0x3b;
+                                               *(cd->mcodeptr++) = 0x5a;
+                                               *(cd->mcodeptr++) = super->vftbl->subtype_offset;
+                                               /* cmp off(ITMP1), ITMP2 */
+
+                                               emit_classcast_check(cd, iptr, BRANCH_NE, REG_ITMP3, s1);
+                                       }
 
                                        if (super != NULL)
                                                emit_label(cd, BRANCH_LABEL_5);
@@ -2651,6 +2683,8 @@ gen_method:
                        classinfo *super;
                        s4         superindex;
 
+                       s4 looptarget;
+
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                super      = NULL;
                                superindex = 0;
@@ -2660,9 +2694,6 @@ gen_method:
                                superindex = super->index;
                        }
 
-                       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);
 
@@ -2741,21 +2772,82 @@ 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);
-
-                               CODEGEN_CRITICAL_SECTION_START;
-
-                               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));
-
-                               CODEGEN_CRITICAL_SECTION_END;
+                               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_AADD_IMM(-32, REG_SP); /* need some stack */
+                               M_ALD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
+
+                               *(cd->mcodeptr++) = 0x4d;
+                               *(cd->mcodeptr++) = 0x3b;
+                               *(cd->mcodeptr++) = 0x1c;
+                               *(cd->mcodeptr++) = 0x02;
+                               /* cmp (ITMP2, ITMP1, 1), ITMP3 */
+
+                               emit_label_bne(cd, BRANCH_LABEL_6);
+                               if (d == REG_ITMP2) {
+                                       M_SETE(d);
+                                       M_BSEXT(d, d);
+                               } else
+                                       M_LINC(d);
+                               emit_label_br(cd, BRANCH_LABEL_7);    /* done, true */
+
+                               emit_label(cd, BRANCH_LABEL_6);
+
+                               M_LCMP_IMM(OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1);
+                               emit_label_bne(cd, BRANCH_LABEL_6);   /* done, false */
+
+                               M_AST(REG_ITMP3, REG_SP, -16 + 32);
+                               M_AST_IMM32(0, REG_SP, -24 + 32);
+                               M_ALD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
+                               looptarget = cd->mcodeptr - cd->mcodebase;
+
+                               M_ALD(REG_ITMP3, REG_SP, -24 + 32);
+                               M_ICMP_MEMBASE(REG_ITMP2, OFFSET(vftbl_t, subtype_overflow_length), REG_ITMP3);
+                               emit_label_bge(cd, BRANCH_LABEL_8);   /* done, false */
+
+                               *(cd->mcodeptr++) = 0x4e;
+                               *(cd->mcodeptr++) = 0x8b;
+                               *(cd->mcodeptr++) = 0x1c;
+                               *(cd->mcodeptr++) = 0xd8;
+                               /* movq (ITMP1, ITMP3, 8), ITMP3 */
+
+                               M_LCMP_MEMBASE(REG_SP, -16 + 32, REG_ITMP3);
+                               emit_label_bne(cd, BRANCH_LABEL_9);
+                               if (d == REG_ITMP2) {
+                                       M_SETE(d);
+                                       M_BSEXT(d, d);
+                               } else
+                                       M_LINC(d);
+                               emit_label_br(cd, BRANCH_LABEL_10);   /* done, true */
+                               emit_label(cd, BRANCH_LABEL_9);
+
+                               M_LINC_MEMBASE(REG_SP, -24 + 32);
+                               M_JMP_IMM2(looptarget - (cd->mcodeptr - cd->mcodebase) - 2); /* 1 byte displacement */
+
+                               emit_label(cd, BRANCH_LABEL_8);
+                               emit_label(cd, BRANCH_LABEL_6);
+
+                               if (d == REG_ITMP2)
+                                       M_CLR(d);
 
-                               M_ISUB(REG_ITMP2, REG_ITMP1);
-                               M_CLR(d); /* may be REG_ITMP2 */
-                               M_ICMP(REG_ITMP3, REG_ITMP1);
-                               M_SETULE(d);
+                               emit_label(cd, BRANCH_LABEL_10);
+                               emit_label(cd, BRANCH_LABEL_7);
+                               M_AADD_IMM(32, REG_SP);
+                               }
+                               else {
+                                       assert(super->vftbl->subtype_offset < 0x80);
+                                       *(cd->mcodeptr++) = 0x4d;
+                                       *(cd->mcodeptr++) = 0x3b;
+                                       *(cd->mcodeptr++) = 0x5a;
+                                       *(cd->mcodeptr++) = super->vftbl->subtype_offset;
+                                       /* cmp off(ITMP1), ITMP2 */
+
+                                       M_SETE(d);
+                                       if (d == REG_ITMP2)
+                                               M_BSEXT(d, d);
+                               }
 
                                if (super != NULL)
                                        emit_label(cd, BRANCH_LABEL_5);
index 17d4edbd748369d93070e0fa29d4b40922262ddf..8262812b0420187411b3e08da0558cae58094cb0 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_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 68437334bc9361083f5ef19a682d75a60116d567..b63551e54a85747db5d5bcc581154732169dbcf6 100644 (file)
@@ -361,9 +361,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;
@@ -1448,6 +1454,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)
 {
@@ -1456,6 +1474,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) {
@@ -1688,6 +1713,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 34bb44d055f219a0e1007c07b77387609160ddf6..f75ac208efda1871979526a904028222430c9c1c 100644 (file)
@@ -252,7 +252,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 ec8432278550d6e33f5e891ddb9c62c6088d9716..c680d0a0ffbb9393ae5732d86ef4ceb5ecccfb8b 100644 (file)
@@ -1591,12 +1591,7 @@ bool class_isanysubclass(classinfo *sub, classinfo *super)
                if (sub->flags & ACC_INTERFACE)
                        return (super == class_java_lang_Object);
 
-               LOCK_MONITOR_ENTER(linker_classrenumber_lock);
-
-               diffval = sub->vftbl->baseval - super->vftbl->baseval;
-               result  = diffval <= (uint32_t) super->vftbl->diffval;
-
-               LOCK_MONITOR_EXIT(linker_classrenumber_lock);
+               result = fast_subtype_check(sub->vftbl, super->vftbl);
        }
 
        return result;
index cee3866ee312c30c30532673bb8c05ce7f379e57..3a76622c59e5f17cf6d81ee5e64911c0769d873d 100644 (file)
@@ -92,8 +92,6 @@ classinfo *resolve_classref_or_classinfo_eager(classref_or_classinfo cls, bool c
 static s4 interfaceindex;       /* sequential numbering of interfaces         */
 static s4 classvalue;
 
-java_object_t *linker_classrenumber_lock;
-
 
 /* private functions **********************************************************/
 
@@ -165,14 +163,6 @@ void linker_preinit(void)
 
        interfaceindex = 0;
 
-#if defined(ENABLE_THREADS)
-       /* create the global lock object */
-
-       linker_classrenumber_lock = NEW(java_object_t);
-
-       LOCK_INIT_OBJECT_LOCK(linker_classrenumber_lock);
-#endif
-
        /* Link the most basic classes. */
 
        if (!link_class(class_java_lang_Object))
@@ -557,6 +547,70 @@ 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_length = i+1;
+                       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;
+               c->vftbl->subtype_overflow_length = 0;
+       }
+}
+
 static classinfo *link_class_intern(classinfo *c)
 {
        classinfo *super;             /* super class                              */
@@ -973,8 +1027,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;
@@ -1174,8 +1231,6 @@ static arraydescriptor *link_array(classinfo *c)
 
 static void linker_compute_subclasses(classinfo *c)
 {
-       LOCK_MONITOR_ENTER(linker_classrenumber_lock);
-
 #if 0 && defined(ENABLE_THREADS) && !defined(DISABLE_GC)
        threads_stopworld();
 #endif
@@ -1183,6 +1238,7 @@ static void linker_compute_subclasses(classinfo *c)
        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)) {
@@ -1192,12 +1248,6 @@ static void linker_compute_subclasses(classinfo *c)
 
        classvalue = 0;
 
-       /* compute class values */
-
-       linker_compute_class_values(class_java_lang_Object);
-
-       LOCK_MONITOR_EXIT(linker_classrenumber_lock);
-
 #if 0 && defined(ENABLE_THREADS) && !defined(DISABLE_GC)
        threads_startworld();
 #endif
index ad95bcccc824c6c9129e7a6bbcf84896cbc6c003..e78dd19aca7bccd4804c626facf1e8d33d36fdf2 100644 (file)
@@ -100,6 +100,8 @@ typedef struct primitivetypeinfo primitivetypeinfo;
 
 *******************************************************************************/
 
+#define DISPLAY_SIZE 4
+
 struct _vftbl {
        methodptr   *interfacetable[1];    /* interface table (access via macro)  */
        classinfo   *clazz;                /* class, the vtbl belongs to          */
@@ -109,6 +111,13 @@ struct _vftbl {
        s4           baseval;              /* base for runtime type check         */
                                           /* (-index for interfaces)             */
        s4           diffval;              /* high - base for runtime type check  */
+
+       s4 subtype_depth;
+       ptrint subtype_offset;
+       struct _vftbl *subtype_display[DISPLAY_SIZE+1];  /* the last one is cache */
+       s4 subtype_overflow_length;
+       struct _vftbl **subtype_overflow;
+
        s4          *interfacevftbllength; /* length of interface vftbls          */
        methodptr    table[1];             /* class vftbl                         */
 };
@@ -133,14 +142,6 @@ struct arraydescriptor {
 };
 
 
-/* global variables ***********************************************************/
-
-/* This lock must be taken while renumbering classes or while atomically      */
-/* accessing classes.                                                         */
-
-extern java_object_t *linker_classrenumber_lock;
-
-
 /* function prototypes ********************************************************/
 
 void       linker_preinit(void);