From: Stefan Ring Date: Sat, 20 Dec 2008 15:06:26 +0000 (+0100) Subject: Merged branch subtype-trunk into default. X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=8c6bb03b79a31fcdb02e2331a91a928d558c2845;hp=4cce6a2426d398775d952d1726a28cf3da8fe990;p=cacao.git Merged branch subtype-trunk into default. --- diff --git a/src/vm/class.cpp b/src/vm/class.cpp index 9ab89073c..698356d11 100644 --- a/src/vm/class.cpp +++ b/src/vm/class.cpp @@ -1471,12 +1471,16 @@ bool class_isanysubclass(classinfo *sub, classinfo *super) if (sub->flags & ACC_INTERFACE) return (super == class_java_lang_Object); - linker_classrenumber_mutex->lock(); +#if USES_NEW_SUBTYPE + result = fast_subtype_check(sub->vftbl, super->vftbl); +#else + LOCK_CLASSRENUMBER_LOCK; diffval = sub->vftbl->baseval - super->vftbl->baseval; result = diffval <= (uint32_t) super->vftbl->diffval; - linker_classrenumber_mutex->unlock(); + UNLOCK_CLASSRENUMBER_LOCK; +#endif } return result; diff --git a/src/vm/jit/alpha/arch.h b/src/vm/jit/alpha/arch.h index f14e210ac..186f1d1b9 100644 --- a/src/vm/jit/alpha/arch.h +++ b/src/vm/jit/alpha/arch.h @@ -105,6 +105,10 @@ #define REPLACEMENT_PATCH_SIZE 4 /* bytes */ +/* subtype ********************************************************************/ + +#define USES_NEW_SUBTYPE 1 + #endif /* _ARCH_H */ diff --git a/src/vm/jit/alpha/codegen.c b/src/vm/jit/alpha/codegen.c index 2c14d21fe..a49b1a0af 100644 --- a/src/vm/jit/alpha/codegen.c +++ b/src/vm/jit/alpha/codegen.c @@ -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); diff --git a/src/vm/jit/builtin.cpp b/src/vm/jit/builtin.cpp index 9e927c39b..491d48ce6 100644 --- a/src/vm/jit/builtin.cpp +++ b/src/vm/jit/builtin.cpp @@ -640,6 +640,28 @@ bool builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o) return result; } +#if USES_NEW_SUBTYPE +/* fast_subtype_check ********************************************************** + + Checks if s is a subtype of t, using both the restricted subtype relation + and the overflow array (see Cliff Click and John Rose: Fast subtype checking + in the Hotspot JVM.) + + RETURN VALUE: + 1......s is a subtype of t. + 0......otherwise + +*******************************************************************************/ + +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; +} +#endif /* builtin_fast_canstore ******************************************************* @@ -685,7 +707,7 @@ bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o) if (valuevftbl == componentvftbl) return 1; - linker_classrenumber_mutex->lock(); + LOCK_CLASSRENUMBER_LOCK; baseval = componentvftbl->baseval; @@ -696,11 +718,15 @@ bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o) (valuevftbl->interfacetable[baseval] != NULL)); } else { +#if USES_NEW_SUBTYPE + result = fast_subtype_check(valuevftbl, componentvftbl); +#else diffval = valuevftbl->baseval - componentvftbl->baseval; result = diffval <= (uint32_t) componentvftbl->diffval; +#endif } - linker_classrenumber_mutex->unlock(); + UNLOCK_CLASSRENUMBER_LOCK; } else if (valuedesc == NULL) { /* {oa has dimension > 1} */ @@ -752,7 +778,7 @@ bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o) if (valuevftbl == elementvftbl) return 1; - linker_classrenumber_mutex->lock(); + LOCK_CLASSRENUMBER_LOCK; baseval = elementvftbl->baseval; @@ -762,11 +788,15 @@ bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o) (valuevftbl->interfacetable[baseval] != NULL)); } else { +#if USES_NEW_SUBTYPE + result = fast_subtype_check(valuevftbl, elementvftbl); +#else diffval = valuevftbl->baseval - elementvftbl->baseval; result = diffval <= (uint32_t) elementvftbl->diffval; +#endif } - linker_classrenumber_mutex->unlock(); + UNLOCK_CLASSRENUMBER_LOCK; return result; } @@ -801,12 +831,16 @@ bool builtin_fast_canstore_onedim_class(java_objectarray_t *a, java_object_t *o) if (valuevftbl == elementvftbl) return 1; - linker_classrenumber_mutex->lock(); + LOCK_CLASSRENUMBER_LOCK; +#if USES_NEW_SUBTYPE + result = fast_subtype_check(valuevftbl, elementvftbl); +#else diffval = valuevftbl->baseval - elementvftbl->baseval; result = diffval <= (uint32_t) elementvftbl->diffval; +#endif - linker_classrenumber_mutex->unlock(); + UNLOCK_CLASSRENUMBER_LOCK; return result; } diff --git a/src/vm/jit/builtin.hpp b/src/vm/jit/builtin.hpp index fdb958d7d..60b58e25c 100644 --- a/src/vm/jit/builtin.hpp +++ b/src/vm/jit/builtin.hpp @@ -125,6 +125,10 @@ bool builtintable_replace_function(void *iptr); * ICMD_BUILTIN3.) */ +#if USES_NEW_SUBTYPE +bool fast_subtype_check(struct _vftbl *, struct _vftbl *); +#endif + bool builtin_instanceof(java_handle_t *obj, classinfo *c); /* NOT AN OP */ bool builtin_checkcast(java_handle_t *obj, classinfo *c); diff --git a/src/vm/jit/emit-common.hpp b/src/vm/jit/emit-common.hpp index e499f557e..611eca43d 100644 --- a/src/vm/jit/emit-common.hpp +++ b/src/vm/jit/emit-common.hpp @@ -43,6 +43,10 @@ #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 ******************************************************/ diff --git a/src/vm/jit/i386/arch.h b/src/vm/jit/i386/arch.h index d5d71e803..a154f54cc 100644 --- a/src/vm/jit/i386/arch.h +++ b/src/vm/jit/i386/arch.h @@ -122,6 +122,10 @@ #define REPLACEMENT_PATCH_SIZE 2 /* bytes */ +/* subtype ********************************************************************/ + +#define USES_NEW_SUBTYPE 1 + #endif /* _ARCH_H */ diff --git a/src/vm/jit/i386/codegen.c b/src/vm/jit/i386/codegen.c index 7ac8e26e9..8eab0fbf0 100644 --- a/src/vm/jit/i386/codegen.c +++ b/src/vm/jit/i386/codegen.c @@ -3178,35 +3178,49 @@ gen_method: } M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl)); - if (super == NULL) { patcher_add_patch_ref(jd, PATCHER_checkcast_class, iptr->sx.s23.s3.c.ref, 0); } - M_MOV_IMM(supervftbl, REG_ITMP3); - 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); - 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); @@ -3337,24 +3351,72 @@ gen_method: emit_label_beq(cd, BRANCH_LABEL_5); } - M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl)); - + M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl)); if (super == NULL) { patcher_add_patch_ref(jd, PATCHER_instanceof_class, iptr->sx.s23.s3.c.ref, 0); } + M_MOV_IMM(supervftbl, REG_ITMP3); + + if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) { + M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset)); + M_CMP_MEMINDEX(REG_ITMP2, 0, REG_ITMP1, 0, REG_ITMP3); + emit_label_bne(cd, BRANCH_LABEL_8); /* jump over INC/SETE */ + if (d == REG_ITMP2) { + M_SETE(d); + M_BSEXT(d, d); + } else + M_IINC(d); + emit_label_br(cd, BRANCH_LABEL_6); /* true */ + emit_label(cd, BRANCH_LABEL_8); - M_MOV_IMM(supervftbl, REG_ITMP2); + if (super == NULL) { + M_ICMP_IMM(OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1); + emit_label_bne(cd, BRANCH_LABEL_10); /* false */ + } - M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval)); - M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, diffval)); - M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval)); + M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_depth)); + M_CMP_MEMBASE(REG_ITMP2, OFFSET(vftbl_t, subtype_depth), REG_ITMP1); + emit_label_bgt(cd, BRANCH_LABEL_9); /* false */ - 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); + M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow)); + M_CMP_MEMINDEX(REG_ITMP2, -4*DISPLAY_SIZE, REG_ITMP1, 2, REG_ITMP3); + if (d >= 4) { + M_SETE(REG_ITMP1); + M_BSEXT(REG_ITMP1, d); + } + else { + M_SETE(d); + if (d == REG_ITMP2) { + M_BSEXT(d, d); + + emit_label_br(cd, BRANCH_LABEL_7); /* jump over M_CLR */ + } + } + + emit_label(cd, BRANCH_LABEL_9); + if (super == NULL) + emit_label(cd, BRANCH_LABEL_10); + if (d == REG_ITMP2) { + M_CLR(d); + + emit_label(cd, BRANCH_LABEL_7); + } + emit_label(cd, BRANCH_LABEL_6); + } + else { + M_CMP_MEMBASE(REG_ITMP2, super->vftbl->subtype_offset, REG_ITMP3); + + if (d >= 4) { + M_SETE(REG_ITMP1); + M_BSEXT(REG_ITMP1, d); + } + else { + M_SETE(d); + if (d == REG_ITMP2) + M_BSEXT(d, d); + } + } if (super != NULL) emit_label(cd, BRANCH_LABEL_5); diff --git a/src/vm/jit/i386/codegen.h b/src/vm/jit/i386/codegen.h index 2efb24532..ef28c2465 100644 --- a/src/vm/jit/i386/codegen.h +++ b/src/vm/jit/i386/codegen.h @@ -247,6 +247,8 @@ #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)) @@ -283,6 +285,7 @@ #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)) @@ -315,6 +318,8 @@ #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)) @@ -329,6 +334,8 @@ #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)) diff --git a/src/vm/jit/i386/emit.c b/src/vm/jit/i386/emit.c index 784942aa7..3a264f162 100644 --- a/src/vm/jit/i386/emit.c +++ b/src/vm/jit/i386/emit.c @@ -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; @@ -1296,6 +1313,7 @@ void emit_jcc(codegendata *cd, s4 opc, s4 imm) */ void emit_setcc_reg(codegendata *cd, s4 opc, s4 reg) { + assert(reg < 4); /* Can only operate on al, bl, cl, dl. */ *(cd->mcodeptr++) = 0x0f; *(cd->mcodeptr++) = 0x90 + (u1) (opc); emit_reg(0,(reg)); diff --git a/src/vm/jit/i386/emit.h b/src/vm/jit/i386/emit.h index 56bd05a65..a99eaeeb3 100644 --- a/src/vm/jit/i386/emit.h +++ b/src/vm/jit/i386/emit.h @@ -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); diff --git a/src/vm/jit/i386/patcher.c b/src/vm/jit/i386/patcher.c index ff67f972a..fb04b86c4 100644 --- a/src/vm/jit/i386/patcher.c +++ b/src/vm/jit/i386/patcher.c @@ -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; } diff --git a/src/vm/jit/x86_64/arch.h b/src/vm/jit/x86_64/arch.h index f31db1429..7bd7d809d 100644 --- a/src/vm/jit/x86_64/arch.h +++ b/src/vm/jit/x86_64/arch.h @@ -112,6 +112,10 @@ #define REPLACEMENT_PATCH_SIZE 2 /* bytes */ +/* subtype ********************************************************************/ + +#define USES_NEW_SUBTYPE 1 + #endif /* _ARCH_H */ diff --git a/src/vm/jit/x86_64/codegen.c b/src/vm/jit/x86_64/codegen.c index ef10ece73..80c81af88 100644 --- a/src/vm/jit/x86_64/codegen.c +++ b/src/vm/jit/x86_64/codegen.c @@ -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); diff --git a/src/vm/jit/x86_64/codegen.h b/src/vm/jit/x86_64/codegen.h index 53e005f2c..cb073729d 100644 --- a/src/vm/jit/x86_64/codegen.h +++ b/src/vm/jit/x86_64/codegen.h @@ -188,6 +188,7 @@ #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) \ @@ -267,12 +268,14 @@ #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)) @@ -286,6 +289,7 @@ #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)) @@ -306,6 +310,7 @@ #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) @@ -355,6 +360,7 @@ #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)) diff --git a/src/vm/jit/x86_64/emit.c b/src/vm/jit/x86_64/emit.c index 60b37d916..5f6f0d87a 100644 --- a/src/vm/jit/x86_64/emit.c +++ b/src/vm/jit/x86_64/emit.c @@ -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)); diff --git a/src/vm/jit/x86_64/emit.h b/src/vm/jit/x86_64/emit.h index 1669fd520..4a1cb4c98 100644 --- a/src/vm/jit/x86_64/emit.h +++ b/src/vm/jit/x86_64/emit.h @@ -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); diff --git a/src/vm/linker.cpp b/src/vm/linker.cpp index 84672cfb1..b1bd60a42 100644 --- a/src/vm/linker.cpp +++ b/src/vm/linker.cpp @@ -94,7 +94,9 @@ 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; +#if !USES_NEW_SUBTYPE +Mutex *linker_classrenumber_lock; +#endif #if defined(__cplusplus) extern "C" { @@ -125,10 +127,10 @@ void linker_preinit(void) interfaceindex = 0; -#if defined(ENABLE_THREADS) +#if defined(ENABLE_THREADS) && !USES_NEW_SUBTYPE /* create the global mutex */ - linker_classrenumber_mutex = new Mutex(); + linker_classrenumber_lock = new Mutex(); #endif /* Link the most basic classes. */ @@ -519,6 +521,77 @@ static bool linker_overwrite_method(methodinfo *mg, } +#if USES_NEW_SUBTYPE +/* build_display *************************************************************** + + Builds the entire display for a class. This entails filling the fixed part + as well as allocating and initializing the overflow part. + + See Cliff Click and John Rose: Fast subtype checking in the Hotspot JVM. + +*******************************************************************************/ + +static classinfo *build_display(classinfo *c) +{ + int depth, i; + int depth_fixed; + classinfo *super; + + do { + /* Handle arrays. */ + 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; ndimension; n++) + cls = class_array_of(cls, true); + super = cls; + break; + } + if (a->componentvftbl && a->elementvftbl) { + super = a->componentvftbl->clazz; + break; + } + } + /* Normal classes. */ + super = c->super; + } while (false); + if (super) { + if (!link_class(super)) + return NULL; + depth = super->vftbl->subtype_depth + 1; + } else + /* java.lang.Object doesn't have a super class. */ + depth = 0; + + /* Now copy super's display, append c->vftbl and initialize the remaining fields. */ + if (depth >= DISPLAY_SIZE) { + c->vftbl->subtype_overflow = MNEW(vftbl_t *, depth - DISPLAY_SIZE + 1); +#if defined(ENABLE_STATISTICS) + if (opt_stat) + count_vftbl_len += sizeof(vftbl_t*) * (depth - DISPLAY_SIZE + 1); +#endif + memcpy(c->vftbl->subtype_overflow, super->vftbl->subtype_overflow, sizeof(vftbl_t*) * (depth - DISPLAY_SIZE)); + c->vftbl->subtype_overflow[depth - DISPLAY_SIZE] = c->vftbl; + depth_fixed = DISPLAY_SIZE; + } + else { + depth_fixed = depth; + c->vftbl->subtype_display[depth] = c->vftbl; + } + + if (super) + memcpy(c->vftbl->subtype_display, super->vftbl->subtype_display, sizeof(vftbl_t*) * depth_fixed); + for (i=depth_fixed+1; i<=DISPLAY_SIZE; i++) + c->vftbl->subtype_display[i] = NULL; + c->vftbl->subtype_offset = OFFSET(vftbl_t, subtype_display[0]) + sizeof(vftbl_t*) * depth_fixed; + c->vftbl->subtype_depth = depth; + + return c; +} +#endif + /* link_class_intern *********************************************************** Tries to link a class. The function calculates the length in bytes @@ -921,8 +994,14 @@ static classinfo *link_class_intern(classinfo *c) linker_compute_subclasses(c); + /* FIXME: this is completely useless now */ RT_TIMING_GET_TIME(time_subclasses); +#if USES_NEW_SUBTYPE + if (!build_display(c)) + return NULL; +#endif + /* revert the linking state and class is linked */ c->state = (c->state & ~CLASS_LINKING) | CLASS_LINKED; @@ -1122,11 +1201,15 @@ static arraydescriptor *link_array(classinfo *c) static void linker_compute_subclasses(classinfo *c) { - linker_classrenumber_mutex->lock(); + + LOCK_CLASSRENUMBER_LOCK; if (!(c->flags & ACC_INTERFACE)) { c->nextsub = NULL; c->sub = NULL; +#if USES_NEW_SUBTYPE + c->vftbl->baseval = 1; /* so it does not look like an interface */ +#endif } if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) { @@ -1136,11 +1219,14 @@ static void linker_compute_subclasses(classinfo *c) classvalue = 0; +#if !USES_NEW_SUBTYPE /* compute class values */ linker_compute_class_values(class_java_lang_Object); +#endif + + UNLOCK_CLASSRENUMBER_LOCK; - linker_classrenumber_mutex->unlock(); } diff --git a/src/vm/linker.hpp b/src/vm/linker.hpp index 43dce68ed..2142ef893 100644 --- a/src/vm/linker.hpp +++ b/src/vm/linker.hpp @@ -66,7 +66,18 @@ struct arraydescriptor { /* This lock must be taken while renumbering classes or while atomically */ /* accessing classes. */ -extern Mutex *linker_classrenumber_mutex; +#if USES_NEW_SUBTYPE + +#define LOCK_CLASSRENUMBER_LOCK /* nothing */ +#define UNLOCK_CLASSRENUMBER_LOCK /* nothing */ + +#else +extern Mutex *linker_classrenumber_lock; + +#define LOCK_CLASSRENUMBER_LOCK linker_classrenumber_lock->lock() +#define UNLOCK_CLASSRENUMBER_LOCK linker_classrenumber_lock->unlock() + +#endif /* function prototypes ********************************************************/ diff --git a/src/vm/vftbl.hpp b/src/vm/vftbl.hpp index ace6dc734..0d47ad10f 100644 --- a/src/vm/vftbl.hpp +++ b/src/vm/vftbl.hpp @@ -94,6 +94,10 @@ typedef struct _vftbl vftbl_t; #include "vm/class.hpp" #include "vm/references.h" +#if USES_NEW_SUBTYPE +#define DISPLAY_SIZE 4 +#endif + struct _vftbl { methodptr *interfacetable[1]; /* interface table (access via macro) */ classinfo *clazz; /* class, the vtbl belongs to */ @@ -103,6 +107,14 @@ struct _vftbl { s4 baseval; /* base for runtime type check */ /* (-index for interfaces) */ s4 diffval; /* high - base for runtime type check */ + +#if USES_NEW_SUBTYPE + s4 subtype_depth; + s4 subtype_offset; + struct _vftbl *subtype_display[DISPLAY_SIZE+1]; /* the last one is cache */ + struct _vftbl **subtype_overflow; +#endif + s4 *interfacevftbllength; /* length of interface vftbls */ methodptr table[1]; /* class vftbl */ };