From: Stefan Ring Date: Mon, 13 Oct 2008 14:34:46 +0000 (+0200) Subject: Merged new changes from default (manually: src/vm/jit/emit-common.cpp, src/vm/ji X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=0809f4a711ccc2537204c735daa18017680ced86;hp=fd19b6bdd0d4941183c469bfad32dae65c8370b4;p=cacao.git Merged new changes from default (manually: src/vm/jit/emit-common.cpp, src/vm/ji t/emit-common.hpp) --HG-- branch : subtype-trunk --- diff --git a/src/vm/class.cpp b/src/vm/class.cpp index 1e479529b..34c641ded 100644 --- a/src/vm/class.cpp +++ b/src/vm/class.cpp @@ -1480,12 +1480,7 @@ bool class_isanysubclass(classinfo *sub, classinfo *super) if (sub->flags & ACC_INTERFACE) return (super == class_java_lang_Object); - linker_classrenumber_mutex->lock(); - - diffval = sub->vftbl->baseval - super->vftbl->baseval; - result = diffval <= (uint32_t) super->vftbl->diffval; - - linker_classrenumber_mutex->unlock(); + result = fast_subtype_check(sub->vftbl, super->vftbl); } return result; diff --git a/src/vm/jit/alpha/codegen.c b/src/vm/jit/alpha/codegen.c index bb5f050f8..b136fd4dc 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 f3ebf0ad7..06e2d2626 100644 --- a/src/vm/jit/builtin.cpp +++ b/src/vm/jit/builtin.cpp @@ -728,6 +728,15 @@ bool builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o) *******************************************************************************/ +bool fast_subtype_check(struct _vftbl *s, struct _vftbl *t) +{ + if (s->subtype_display[t->subtype_depth] == t) + return true; + if (t->subtype_offset != OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE])) + return false; + return s->subtype_depth >= t->subtype_depth && s->subtype_overflow[t->subtype_depth - DISPLAY_SIZE] == t; +} + bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o) { arraydescriptor *desc; @@ -760,8 +769,6 @@ bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o) if (valuevftbl == componentvftbl) return 1; - linker_classrenumber_mutex->lock(); - baseval = componentvftbl->baseval; if (baseval <= 0) { @@ -771,11 +778,8 @@ bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o) (valuevftbl->interfacetable[baseval] != NULL)); } else { - diffval = valuevftbl->baseval - componentvftbl->baseval; - result = diffval <= (uint32_t) componentvftbl->diffval; + result = fast_subtype_check(valuevftbl, componentvftbl); } - - linker_classrenumber_mutex->unlock(); } else if (valuedesc == NULL) { /* {oa has dimension > 1} */ @@ -827,8 +831,6 @@ bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o) if (valuevftbl == elementvftbl) return 1; - linker_classrenumber_mutex->lock(); - baseval = elementvftbl->baseval; if (baseval <= 0) { @@ -837,12 +839,9 @@ bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o) (valuevftbl->interfacetable[baseval] != NULL)); } else { - diffval = valuevftbl->baseval - elementvftbl->baseval; - result = diffval <= (uint32_t) elementvftbl->diffval; + result = fast_subtype_check(valuevftbl, elementvftbl); } - linker_classrenumber_mutex->unlock(); - return result; } @@ -876,12 +875,7 @@ bool builtin_fast_canstore_onedim_class(java_objectarray_t *a, java_object_t *o) if (valuevftbl == elementvftbl) return 1; - linker_classrenumber_mutex->lock(); - - diffval = valuevftbl->baseval - elementvftbl->baseval; - result = diffval <= (uint32_t) elementvftbl->diffval; - - linker_classrenumber_mutex->unlock(); + result = fast_subtype_check(valuevftbl, elementvftbl); return result; } diff --git a/src/vm/jit/builtin.hpp b/src/vm/jit/builtin.hpp index 3a7747dc2..2797d5a2d 100644 --- a/src/vm/jit/builtin.hpp +++ b/src/vm/jit/builtin.hpp @@ -127,6 +127,8 @@ bool builtintable_replace_function(void *iptr); * ICMD_BUILTIN3.) */ +bool fast_subtype_check(struct _vftbl *, struct _vftbl *); + bool builtin_instanceof(java_handle_t *obj, classinfo *c); /* NOT AN OP */ bool builtin_checkcast(java_handle_t *obj, classinfo *c); 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/codegen.c b/src/vm/jit/i386/codegen.c index 3d667c726..c7adf83a5 100644 --- a/src/vm/jit/i386/codegen.c +++ b/src/vm/jit/i386/codegen.c @@ -3231,37 +3231,50 @@ gen_method: } M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl)); - if (super == NULL) { patcher_add_patch_ref(jd, PATCHER_checkcast_class, iptr->sx.s23.s3.c.ref, 0); } - M_MOV_IMM(supervftbl, REG_ITMP3); JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CLASSINFO_VFTBL, super); - M_ILD32(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval)); + if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) { + M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset)); + M_CMP_MEMINDEX(REG_ITMP2, 0, REG_ITMP1, 0, REG_ITMP3); + emit_label_beq(cd, BRANCH_LABEL_6); /* good */ - /* if (s1 != REG_ITMP1) { */ - /* emit_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, baseval), REG_ITMP1); */ - /* emit_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, diffval), REG_ITMP3); */ - /* #if defined(ENABLE_THREADS) */ - /* codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); */ - /* #endif */ - /* emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP1, REG_ITMP2); */ + if (super == NULL) { + M_ICMP_IMM(OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1); + emit_label_bne(cd, BRANCH_LABEL_10); /* throw */ + } - /* } else { */ - M_ILD32(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval)); - M_ISUB(REG_ITMP3, REG_ITMP2); - M_MOV_IMM(supervftbl, REG_ITMP3); - JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CLASSINFO_VFTBL, super); - M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); + M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_depth)); + M_CMP_MEMBASE(REG_ITMP2, OFFSET(vftbl_t, subtype_depth), REG_ITMP1); + emit_label_bgt(cd, BRANCH_LABEL_9); /* throw */ + + M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow)); + M_CMP_MEMINDEX(REG_ITMP2, -4*DISPLAY_SIZE, REG_ITMP1, 2, REG_ITMP3); + emit_label_beq(cd, BRANCH_LABEL_7); /* good */ + + emit_label(cd, BRANCH_LABEL_9); + if (super == NULL) + emit_label(cd, BRANCH_LABEL_10); + + /* reload s1, might have been destroyed */ + emit_load_s1(jd, iptr, REG_ITMP1); + M_ALD_MEM(s1, TRAP_ClassCastException); - /* } */ + emit_label(cd, BRANCH_LABEL_7); + emit_label(cd, BRANCH_LABEL_6); + /* reload s1, might have been destroyed */ + emit_load_s1(jd, iptr, REG_ITMP1); + } + else { + M_CMP_MEMBASE(REG_ITMP2, super->vftbl->subtype_offset, REG_ITMP3); - M_CMP(REG_ITMP3, REG_ITMP2); - emit_classcast_check(cd, iptr, BRANCH_ULE, REG_ITMP3, s1); + emit_classcast_check(cd, iptr, BRANCH_NE, REG_ITMP3, s1); + } if (super != NULL) emit_label(cd, BRANCH_LABEL_5); @@ -3404,24 +3417,61 @@ gen_method: emit_label_beq(cd, BRANCH_LABEL_5); } - M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl)); - + M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl)); if (super == NULL) { patcher_add_patch_ref(jd, PATCHER_instanceof_class, iptr->sx.s23.s3.c.ref, 0); } - - M_MOV_IMM(supervftbl, REG_ITMP2); + M_MOV_IMM(supervftbl, REG_ITMP3); JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CLASSINFO_VFTBL, super); - M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval)); - M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, diffval)); - M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval)); - - M_ISUB(REG_ITMP2, REG_ITMP1); - M_CLR(d); /* may be REG_ITMP2 */ - M_CMP(REG_ITMP3, REG_ITMP1); - M_BA(5); - M_MOV_IMM(1, d); + + if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) { + M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset)); + M_CMP_MEMINDEX(REG_ITMP2, 0, REG_ITMP1, 0, REG_ITMP3); + emit_label_bne(cd, BRANCH_LABEL_8); /* jump over INC/SETE */ + if (d == REG_ITMP2) { + M_SETE(d); + M_BSEXT(d, d); + } else + M_IINC(d); + emit_label_br(cd, BRANCH_LABEL_6); /* true */ + emit_label(cd, BRANCH_LABEL_8); + + if (super == NULL) { + M_ICMP_IMM(OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1); + emit_label_bne(cd, BRANCH_LABEL_10); /* false */ + } + + M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_depth)); + M_CMP_MEMBASE(REG_ITMP2, OFFSET(vftbl_t, subtype_depth), REG_ITMP1); + emit_label_bgt(cd, BRANCH_LABEL_9); /* false */ + + M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow)); + M_CMP_MEMINDEX(REG_ITMP2, -4*DISPLAY_SIZE, REG_ITMP1, 2, REG_ITMP3); + M_SETE(d); + if (d == REG_ITMP2) { + M_BSEXT(d, d); + + emit_label_br(cd, BRANCH_LABEL_7); /* jump over M_CLR */ + } + + emit_label(cd, BRANCH_LABEL_9); + if (super == NULL) + emit_label(cd, BRANCH_LABEL_10); + if (d == REG_ITMP2) { + M_CLR(d); + + emit_label(cd, BRANCH_LABEL_7); + } + emit_label(cd, BRANCH_LABEL_6); + } + else { + M_CMP_MEMBASE(REG_ITMP2, super->vftbl->subtype_offset, REG_ITMP3); + + M_SETE(d); + if (d == REG_ITMP2) + M_BSEXT(d, d); + } if (super != NULL) emit_label(cd, BRANCH_LABEL_5); 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 ca730f3b6..c3bf7e4ee 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; 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 b2297fcd2..5b00e789a 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/codegen.c b/src/vm/jit/x86_64/codegen.c index 18e86af09..96f4967bc 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 906a01e89..9c777fb54 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.c b/src/vm/linker.c index e5883f091..346ce8e1e 100644 --- a/src/vm/linker.c +++ b/src/vm/linker.c @@ -94,8 +94,6 @@ classinfo *resolve_classref_or_classinfo_eager(classref_or_classinfo cls, bool c static s4 interfaceindex; /* sequential numbering of interfaces */ static s4 classvalue; -Mutex *linker_classrenumber_mutex; - /* private functions **********************************************************/ @@ -122,12 +120,6 @@ void linker_preinit(void) interfaceindex = 0; -#if defined(ENABLE_THREADS) - /* create the global mutex */ - - linker_classrenumber_mutex = Mutex_new(); -#endif - /* Link the most basic classes. */ if (!link_class(class_java_lang_Object)) @@ -524,6 +516,68 @@ static bool linker_overwrite_method(methodinfo *mg, *******************************************************************************/ +static int build_display_inner(classinfo *topc, classinfo *c, int i) +{ + int depth; + if (!c) + return 0; + do { + if (c->vftbl->arraydesc) + { + arraydescriptor *a = c->vftbl->arraydesc; + if (a->elementvftbl && a->elementvftbl->clazz->super) + { + classinfo *cls = a->elementvftbl->clazz->super; + int n; + for (n=0; ndimension; n++) + cls = class_array_of(cls, true); + depth = build_display_inner(topc, cls, i+1); + break; + } + if (a->componentvftbl && a->elementvftbl) + { + depth = build_display_inner(topc, a->componentvftbl->clazz, i+1); + break; + } + } + depth = build_display_inner(topc, c->super, i+1); + } while (false); + if (depth >= DISPLAY_SIZE) + { + if (depth == DISPLAY_SIZE) + { + topc->vftbl->subtype_overflow = malloc(sizeof(void*) * (i+1)); +#if defined(ENABLE_STATISTICS) + if (opt_stat) + count_vftbl_len += sizeof(void*) * (i+1); +#endif + } + topc->vftbl->subtype_overflow[depth - DISPLAY_SIZE] = c->vftbl; + return depth + 1; + } + topc->vftbl->subtype_display[depth] = c->vftbl; + return depth + 1; +} + +static void build_display(classinfo *c) +{ + int depth; + int i; + + depth = build_display_inner(c, c, 0) - 1; + c->vftbl->subtype_depth = depth; + if (depth >= DISPLAY_SIZE) + { + c->vftbl->subtype_offset = OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]); + } + else + { + c->vftbl->subtype_offset = OFFSET(vftbl_t, subtype_display[0]) + sizeof(void*) * depth; + for (i=depth+1; i<=DISPLAY_SIZE; i++) + c->vftbl->subtype_display[i] = NULL; + } +} + static classinfo *link_class_intern(classinfo *c) { classinfo *super; /* super class */ @@ -918,8 +972,11 @@ static classinfo *link_class_intern(classinfo *c) linker_compute_subclasses(c); + /* FIXME: this is completely useless now */ RT_TIMING_GET_TIME(time_subclasses); + build_display(c); + /* revert the linking state and class is linked */ c->state = (c->state & ~CLASS_LINKING) | CLASS_LINKED; @@ -1119,11 +1176,11 @@ static arraydescriptor *link_array(classinfo *c) static void linker_compute_subclasses(classinfo *c) { - Mutex_lock(linker_classrenumber_mutex); if (!(c->flags & ACC_INTERFACE)) { c->nextsub = NULL; c->sub = NULL; + c->vftbl->baseval = 1; /* so it does not look like an interface */ } if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) { @@ -1133,11 +1190,6 @@ static void linker_compute_subclasses(classinfo *c) classvalue = 0; - /* compute class values */ - - linker_compute_class_values(class_java_lang_Object); - - Mutex_unlock(linker_classrenumber_mutex); } diff --git a/src/vm/linker.h b/src/vm/linker.h index 43dce68ed..7f4c6326f 100644 --- a/src/vm/linker.h +++ b/src/vm/linker.h @@ -61,14 +61,6 @@ struct arraydescriptor { }; -/* global variables ***********************************************************/ - -/* This lock must be taken while renumbering classes or while atomically */ -/* accessing classes. */ - -extern Mutex *linker_classrenumber_mutex; - - /* function prototypes ********************************************************/ #ifdef __cplusplus diff --git a/src/vm/vftbl.hpp b/src/vm/vftbl.hpp index ace6dc734..6f5bed5f5 100644 --- a/src/vm/vftbl.hpp +++ b/src/vm/vftbl.hpp @@ -94,6 +94,8 @@ typedef struct _vftbl vftbl_t; #include "vm/class.hpp" #include "vm/references.h" +#define DISPLAY_SIZE 4 + struct _vftbl { methodptr *interfacetable[1]; /* interface table (access via macro) */ classinfo *clazz; /* class, the vtbl belongs to */ @@ -103,6 +105,12 @@ struct _vftbl { s4 baseval; /* base for runtime type check */ /* (-index for interfaces) */ s4 diffval; /* high - base for runtime type check */ + + s4 subtype_depth; + s4 subtype_offset; + struct _vftbl *subtype_display[DISPLAY_SIZE+1]; /* the last one is cache */ + struct _vftbl **subtype_overflow; + s4 *interfacevftbllength; /* length of interface vftbls */ methodptr table[1]; /* class vftbl */ };