* src/vm/builtin.c: Added fast_subtype_check.
authorStefan Ring <stefan@complang.tuwien.ac.at>
Mon, 9 Jun 2008 19:52:41 +0000 (21:52 +0200)
committerStefan Ring <stefan@complang.tuwien.ac.at>
Mon, 9 Jun 2008 19:52:41 +0000 (21:52 +0200)
(builtin_fast_canstore, builtin_fast_canstore_onedim,
builtin_fast_canstore_onedim_class): Using fast subtype check. Don't need
to lock linker_classrenumber_lock anymore.
* src/vm/builtin.h: Added fast_subtype_check.

* src/vm/jit/emit-common.h: Added more branch labels.

* src/vm/jit/x86_64/codegen.c (gen_method): New subtype checking code.
* src/vm/jit/x86_64/codegen.h: Added some new mnemonics.
* src/vm/jit/x86_64/emit.c: New mnemonics.
(emit_classcast_check): New branch modes.
* src/vm/jit/x86_64/emit.h: New mnemonics.
* src/vmcore/class.c (class_isanysubclass): Using fast_subtype_check.

* src/vmcore/linker.c: Removed linker_classrenumber_lock.
(build_display): Implemented.
(link_class_intern, link_array, linker_compute_subclasses): Minor changes.

* src/vmcore/linker.h: Removed linker_compute_subclasses.
Added subtype-related fields to _vftbl.

* src/cacaoh/dummy.c: Added fast_subtype_check (link dependency).

--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 a93f42b5234c24d7bb0165d0663931ecb6419925..07c71c78ad6a20438392ca18a70b239765b9ca2a 100644 (file)
@@ -2486,6 +2486,8 @@ gen_method:
                                classinfo *super;
                                s4         superindex;
 
+                               s4 looptarget;
+
                                if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                        super      = NULL;
                                        superindex = 0;
@@ -2495,9 +2497,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 */
@@ -2567,37 +2566,66 @@ gen_method:
                                                disp = dseg_add_address(cd, super->vftbl);
                                        }
 
-                                       M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
-                                       M_ALD(REG_ITMP3, RIP, disp);
+                                       if (s1 == REG_ITMP1)
+                                               M_AST(REG_ITMP1, REG_SP, -8); /* store in red zone */
+
+                                       M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
+                                       M_ALD(REG_ITMP2, RIP, disp);
+
+                                       if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
+                                       M_ALD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, subtype_offset));
+
+                                       *(cd->mcodeptr++) = 0x4e;
+                                       *(cd->mcodeptr++) = 0x3b;
+                                       *(cd->mcodeptr++) = 0x14;
+                                       *(cd->mcodeptr++) = 0x18;
+                                       /* cmp (ITMP1, ITMP3, 1), ITMP2 */
+
+                                       emit_label_beq(cd, BRANCH_LABEL_6); /* good */
 
-                                       CODEGEN_CRITICAL_SECTION_START;
+                                       M_LCMP_IMM(OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP3);
+                                       emit_classcast_check(cd, iptr, BRANCH_NE, REG_ITMP3, s1);
 
-                                       M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
+                                       /* use red zone */
+                                       M_AST(REG_ITMP2, REG_SP, -16);
+                                       M_AST_IMM32(0, REG_SP, -24);
+                                       M_ALD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, subtype_overflow));
+                                       looptarget = cd->mcodeptr - cd->mcodebase;
 
-                                       /*                                      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); */
+                                       M_ALD(REG_ITMP2, REG_SP, -24);
+                                       M_ICMP_MEMBASE(REG_ITMP1, OFFSET(vftbl_t, subtype_overflow_length), REG_ITMP2);
 
-                                       /*                                      } else { */
+                                       emit_classcast_check(cd, iptr, BRANCH_GE, REG_ITMP3, s1);
 
-                                       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));
-                                       /*                                      } */
+                                       *(cd->mcodeptr++) = 0x4f;
+                                       *(cd->mcodeptr++) = 0x8b;
+                                       *(cd->mcodeptr++) = 0x14;
+                                       *(cd->mcodeptr++) = 0xd3;
+                                       /* movq (ITMP3, ITMP2, 8), ITMP2 */
 
-                                       CODEGEN_CRITICAL_SECTION_END;
+                                       M_LCMP_MEMBASE(REG_SP, -16, REG_ITMP2);
+                                       emit_label_beq(cd, BRANCH_LABEL_7); /* good, pop */
+
+                                       M_LINC_MEMBASE(REG_SP, -24);
+                                       M_JMP_IMM2(looptarget - (cd->mcodeptr - cd->mcodebase) - 2); /* 1 byte displacement */
+
+                                       emit_label(cd, BRANCH_LABEL_7);
+
+                                       emit_label(cd, BRANCH_LABEL_6);
+                                       }
+                                       else {
+                                               assert(super->vftbl->subtype_offset < 0x80);
+                                               *(cd->mcodeptr++) = 0x4c;
+                                               *(cd->mcodeptr++) = 0x3b;
+                                               *(cd->mcodeptr++) = 0x50;
+                                               *(cd->mcodeptr++) = super->vftbl->subtype_offset;
+                                               /* cmp off(ITMP1), ITMP2 */
+
+                                               emit_classcast_check(cd, iptr, BRANCH_NE, REG_ITMP3, s1);
+                                       }
 
-                                       M_ICMP(REG_ITMP3, REG_ITMP2);
-                                       emit_classcast_check(cd, iptr, BRANCH_UGT, REG_ITMP3, s1);
+                                       if (s1 == REG_ITMP1)
+                                               M_ALD(REG_ITMP1, REG_SP, -8);
 
                                        if (super != NULL)
                                                emit_label(cd, BRANCH_LABEL_5);
@@ -2650,6 +2678,8 @@ gen_method:
                        classinfo *super;
                        s4         superindex;
 
+                       s4 looptarget;
+
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                super      = NULL;
                                superindex = 0;
@@ -2659,9 +2689,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);
 
@@ -2743,18 +2770,67 @@ gen_method:
                                M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
                                M_ALD(REG_ITMP2, RIP, disp);
 
-                               CODEGEN_CRITICAL_SECTION_START;
+                               if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
+                               M_ALD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, subtype_offset));
+
+                               *(cd->mcodeptr++) = 0x4e;
+                               *(cd->mcodeptr++) = 0x3b;
+                               *(cd->mcodeptr++) = 0x14;
+                               *(cd->mcodeptr++) = 0x18;
+                               /* cmp (ITMP1, ITMP3, 1), ITMP2 */
+
+                               emit_label_bne(cd, BRANCH_LABEL_6);
+                               M_LINC(d);
+                               emit_label_br(cd, BRANCH_LABEL_7); /* ende */
+
+                               emit_label(cd, BRANCH_LABEL_6);
+
+                               M_LCMP_IMM(OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP3);
+                               emit_label_bne(cd, BRANCH_LABEL_6); /* ende */
+
+                               /* use the red zone */
+                               M_AST(REG_ITMP2, REG_SP, -16);
+                               M_AST_IMM32(0, REG_SP, -24);
+                               M_ALD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, subtype_overflow));
+                               looptarget = cd->mcodeptr - cd->mcodebase;
 
-                               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_ALD(REG_ITMP2, REG_SP, -24);
+                               M_ICMP_MEMBASE(REG_ITMP1, OFFSET(vftbl_t, subtype_overflow_length), REG_ITMP2);
+                               emit_label_bge(cd, BRANCH_LABEL_8); /* ende pop */
 
-                               CODEGEN_CRITICAL_SECTION_END;
+                               *(cd->mcodeptr++) = 0x4f;
+                               *(cd->mcodeptr++) = 0x8b;
+                               *(cd->mcodeptr++) = 0x14;
+                               *(cd->mcodeptr++) = 0xd3;
+                               /* movq (ITMP3, ITMP2, 8), ITMP2 */
 
-                               M_ISUB(REG_ITMP2, REG_ITMP1);
-                               M_CLR(d); /* may be REG_ITMP2 */
-                               M_ICMP(REG_ITMP3, REG_ITMP1);
-                               M_SETULE(d);
+                               M_LCMP_MEMBASE(REG_SP, -16, REG_ITMP2);
+                               emit_label_bne(cd, BRANCH_LABEL_9);
+                               M_LINC(d);
+                               emit_label_br(cd, BRANCH_LABEL_10); /* ende pop */
+                               emit_label(cd, BRANCH_LABEL_9);
+
+                               M_LINC_MEMBASE(REG_SP, -24);
+                               M_JMP_IMM2(looptarget - (cd->mcodeptr - cd->mcodebase) - 2); /* 1 byte displacement */
+
+                               emit_label(cd, BRANCH_LABEL_8);
+                               emit_label(cd, BRANCH_LABEL_10);
+
+                               emit_label(cd, BRANCH_LABEL_6);
+                               emit_label(cd, BRANCH_LABEL_7);
+                               }
+                               else {
+                                       assert(super->vftbl->subtype_offset < 0x80);
+                                       *(cd->mcodeptr++) = 0x4c;
+                                       *(cd->mcodeptr++) = 0x3b;
+                                       *(cd->mcodeptr++) = 0x50;
+                                       *(cd->mcodeptr++) = super->vftbl->subtype_offset;
+                                       /* cmp off(ITMP1), ITMP2 */
+
+                                       emit_label_bne(cd, BRANCH_LABEL_6);
+                                       M_LINC(d);
+                                       emit_label(cd, BRANCH_LABEL_6);
+                               }
 
                                if (super != NULL)
                                        emit_label(cd, BRANCH_LABEL_5);
index add6b306a1df7f94eabd069e79f4a5db88bca874..aa0770817493dd9a13b7d04a69d8d60b25ccf2ba 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_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 60e5f342d83933740c4e97524b90ef24aaf7622d..935d28c2c2caa2080cce9e34e2489fab89bd399c 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;
@@ -1438,6 +1444,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)
 {
@@ -1446,6 +1464,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) {
@@ -1678,6 +1703,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 24239e431eacba210eb2337368770e55eadb2747..239bf5d1d039ec47c5ffd23a52e65a801cd76dcf 100644 (file)
@@ -251,7 +251,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);