Merged trunk and subtype.
authorStefan Ring <stefan@complang.tuwien.ac.at>
Wed, 17 Sep 2008 11:39:41 +0000 (13:39 +0200)
committerStefan Ring <stefan@complang.tuwien.ac.at>
Wed, 17 Sep 2008 11:39:41 +0000 (13:39 +0200)
--HG--
branch : subtype-trunk
rename : src/vm/builtin.c => src/vm/jit/builtin.cpp
rename : src/vm/jit/emit-common.c => src/vm/jit/emit-common.cpp
rename : src/vm/jit/emit-common.h => src/vm/jit/emit-common.hpp
rename : src/vmcore/linker.c => src/vm/linker.c
rename : src/vmcore/linker.h => src/vm/linker.h

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

index 72f5dae71ee413a5dabc391f27fddf4891f1c81a..e52bb2c97d91664324b3c689917e4b3f0cdd3a63 100644 (file)
@@ -2778,24 +2778,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);
@@ -2939,15 +2964,53 @@ gen_method:
                                        emit_label_beqz(cd, BRANCH_LABEL_5, s1);
                                }
 
-                               M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
-                               M_ALD(REG_ITMP2, REG_PV, disp);
+                               M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
+                               M_ALD(REG_ITMP3, REG_PV, disp);
+
+                               if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
+                                       M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
+                                       M_LADD(REG_ITMP1, REG_ITMP2, REG_ITMP1);
+                                       M_ALD(REG_ITMP1, REG_ITMP1, 0);
+                                       M_CMPEQ(REG_ITMP1, REG_ITMP3, REG_ITMP1);
+                                       emit_label_beqz(cd, BRANCH_LABEL_8, REG_ITMP1);
+                                       ICONST(d, 1);
+                                       emit_label_br(cd, BRANCH_LABEL_6);  /* true */
+                                       emit_label(cd, BRANCH_LABEL_8);
+
+                                       if (super == NULL) {
+                                               M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
+                                               M_CMPEQ_IMM(REG_ITMP1, OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1);
+                                               emit_label_beqz(cd, BRANCH_LABEL_10, REG_ITMP1);  /* false */
+                                       }
 
-                               M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
-                               M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
-                               M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
+                                       M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
 
-                               M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
-                               M_CMPULE(REG_ITMP1, REG_ITMP2, d);
+                                       M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, subtype_depth));
+                                       M_CMPLE(REG_ITMP1, REG_ITMP3, REG_ITMP3);
+                                       emit_label_beqz(cd, BRANCH_LABEL_9, REG_ITMP3);  /* false */
+                                       /* reload */
+                                       M_ALD(REG_ITMP3, REG_PV, disp);
+                                       M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
+                                       M_S8ADDQ(REG_ITMP1, REG_ITMP2, REG_ITMP2);
+                                       M_ALD(REG_ITMP1, REG_ITMP2, -DISPLAY_SIZE*8);
+                                       M_CMPEQ(REG_ITMP1, REG_ITMP3, d);
+
+                                       if (d == REG_ITMP2)
+                                               emit_label_br(cd, BRANCH_LABEL_7);
+                                       emit_label(cd, BRANCH_LABEL_9);
+                                       if (super == NULL)
+                                               emit_label(cd, BRANCH_LABEL_10);
+                                       if (d == REG_ITMP2) {
+                                               M_CLR(d);
+
+                                               emit_label(cd, BRANCH_LABEL_7);
+                                       }
+                                       emit_label(cd, BRANCH_LABEL_6);
+                               }
+                               else {
+                                       M_ALD(REG_ITMP2, REG_ITMP2, super->vftbl->subtype_offset);
+                                       M_CMPEQ(REG_ITMP2, REG_ITMP3, d);
+                               }
 
                                if (super != NULL)
                                        emit_label(cd, BRANCH_LABEL_5);
index 5dbd12a7520dda46fab14008d0e0265fefdd58d2..cd53c03dd4c51e11d7391c256fefc82b9085a596 100644 (file)
@@ -655,15 +655,11 @@ 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;
+       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)
index a5fa481e3b2ef35f89683c8fe21cdc19fb628b6a..f6cb5d5acd8d9f6298db44f1a3e7531deeebe9f9 100644 (file)
@@ -672,6 +672,11 @@ void emit_label_beqz(codegendata *cd, s4 label, s4 reg)
        emit_label_bccz(cd, label, BRANCH_EQ, reg, BRANCH_OPT_NONE);
 }
 
+void emit_label_bnez(codegendata *cd, s4 label, s4 reg)
+{
+       emit_label_bccz(cd, label, BRANCH_NE, reg, BRANCH_OPT_NONE);
+}
+
 #endif /* SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER */
 
 
index 02e90d6b7c900ed353c7ff5bf939f13b678ff4cd..b96bc08ea213fe19a7c355b3dfde5cdf9d8f6ae5 100644 (file)
@@ -164,6 +164,7 @@ void emit_label_br(codegendata *cd, s4 label);
 
 #if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
 void emit_label_beqz(codegendata *cd, s4 label, s4 reg);
+void emit_label_bnez(codegendata *cd, s4 label, s4 reg);
 #endif
 
 #if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
index 5b0cd8a7f11e000b3c6a7d71179dcd0f91766fd7..a5f09828d93868345d8466f24a8e3feb62a1709a 100644 (file)
@@ -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 */
 
-                                       M_CMP(REG_ITMP3, REG_ITMP2);
-                                       emit_classcast_check(cd, iptr, BRANCH_ULE, REG_ITMP3, s1);
+                                               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);
+
+                                               emit_classcast_check(cd, iptr, BRANCH_NE, REG_ITMP3, s1);
+                                       }
 
                                        if (super != NULL)
                                                emit_label(cd, BRANCH_LABEL_5);
@@ -3337,24 +3351,60 @@ 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);
+                                       M_SETE(d);
+                                       if (d == REG_ITMP2) {
+                                               M_BSEXT(d, d);
+
+                                               emit_label_br(cd, BRANCH_LABEL_7); /* jump over M_CLR */
+                                       }
+
+                                       emit_label(cd, BRANCH_LABEL_9);
+                                       if (super == NULL)
+                                               emit_label(cd, BRANCH_LABEL_10);
+                                       if (d == REG_ITMP2) {
+                                               M_CLR(d);
+
+                                               emit_label(cd, BRANCH_LABEL_7);
+                                       }
+                                       emit_label(cd, BRANCH_LABEL_6);
+                               }
+                               else {
+                                       M_CMP_MEMBASE(REG_ITMP2, super->vftbl->subtype_offset, REG_ITMP3);
+
+                                       M_SETE(d);
+                                       if (d == REG_ITMP2)
+                                               M_BSEXT(d, d);
+                               }
 
                                if (super != NULL)
                                        emit_label(cd, BRANCH_LABEL_5);
index 2efb24532981093b2619f8ef40198b84ae0c039c..ef28c246583b33a92fcc18363a20281d8f8e91ba 100644 (file)
 
 #define M_ISUB_IMM_MEMABS(a,b)  emit_alu_imm_memabs(cd, ALU_SUB, (a), (b))
 
+#define M_IINC(a)               emit_inc_reg(cd, (a))
+
 #define M_IADDC(a,b)            emit_alu_reg_reg(cd, ALU_ADC, (a), (b))
 #define M_ISUBB(a,b)            emit_alu_reg_reg(cd, ALU_SBB, (a), (b))
 
 
 #define M_CMP(a,b)              emit_alu_reg_reg(cd, ALU_CMP, (a), (b))
 #define M_CMP_MEMBASE(a,b,c)    emit_alu_membase_reg(cd, ALU_CMP, (a), (b), (c))
+#define M_CMP_MEMINDEX(a,b,c,d,e)    emit_alu_memindex_reg(cd, ALU_CMP, (b), (a), (c), (d), (e))
 
 #define M_CMP_IMM(a,b)          emit_alu_imm_reg(cd, ALU_CMP, (a), (b))
 #define M_CMP_IMM_MEMBASE(a,b,c) emit_alu_imm_membase(cd, ALU_CMP, (a), (b), (c))
 #define M_CALL_IMM(a)           emit_call_imm(cd, (a))
 #define M_RET                   M_BYTE1(0xc3)
 
+#define M_ICMP_IMM(a,b)         emit_alu_imm_reg(cd, ALU_CMP, (a), (b))
+
 #define M_BEQ(a)                emit_jcc(cd, CC_E, (a))
 #define M_BNE(a)                emit_jcc(cd, CC_NE, (a))
 #define M_BLT(a)                emit_jcc(cd, CC_L, (a))
 #define M_BNS(a)                emit_jcc(cd, CC_NS, (a))
 #define M_BS(a)                 emit_jcc(cd, CC_S, (a))
 
+#define M_SETE(a)               emit_setcc_reg(cd, CC_E, (a))
+
 #define M_JMP(a)                emit_jmp_reg(cd, (a))
 #define M_JMP_IMM(a)            emit_jmp_imm(cd, (a))
 
index 68e8a9e114a38db521328867bc1c43792ab6a227..66fba15ffcc36d30922e8c46422529126a58388c 100644 (file)
@@ -458,9 +458,15 @@ void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 r
                case BRANCH_LE:
                        M_BGT(6);
                        break;
+               case BRANCH_GE:
+                       M_BLT(6);
+                       break;
                case BRANCH_EQ:
                        M_BNE(6);
                        break;
+               case BRANCH_NE:
+                       M_BEQ(6);
+                       break;
                case BRANCH_ULE:
                        M_BBE(6);
                        break;
@@ -1084,6 +1090,11 @@ void emit_alu_imm_memabs(codegendata *cd, s4 opc, s4 imm, s4 disp)
        }
 }
 
+void emit_alu_memindex_reg(codegendata *cd, s4 opc, s4 disp, s4 basereg, s4 indexreg, s4 scale, s4 reg)
+{
+       *(cd->mcodeptr++) = (((u1) (opc)) << 3) + 3;
+       emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
+}
 
 void emit_test_reg_reg(codegendata *cd, s4 reg, s4 dreg)
 {
@@ -1104,6 +1115,12 @@ void emit_test_imm_reg(codegendata *cd, s4 imm, s4 reg)
 /*
  * inc, dec operations
  */
+void emit_inc_reg(codegendata *cd, s4 reg)
+{
+       *(cd->mcodeptr++) = 0xff;
+       emit_reg(0,(reg));
+}
+
 void emit_dec_mem(codegendata *cd, s4 mem)
 {
        *(cd->mcodeptr++) = 0xff;
index 56bd05a6547aa1b9ac10b18319d4055ed7dbdfc5..a99eaeeb386c471a5b496f9b3ba67d2c9860ce0f 100644 (file)
@@ -187,6 +187,8 @@ void emit_alu_imm_reg(codegendata *cd, s4 opc, s4 imm, s4 reg);
 void emit_alu_imm32_reg(codegendata *cd, s4 opc, s4 imm, s4 reg);
 void emit_alu_imm_membase(codegendata *cd, s4 opc, s4 imm, s4 basereg, s4 disp);
 void emit_alu_imm_memabs(codegendata *cd, s4 opc, s4 imm, s4 disp);
+void emit_alu_memindex_reg(codegendata *cd, s4 opc, s4 disp, s4 basereg, s4 indexreg, s4 scale, s4 reg);
+void emit_inc_reg(codegendata *cd, s4 reg);
 void emit_test_reg_reg(codegendata *cd, s4 reg, s4 dreg);
 void emit_test_imm_reg(codegendata *cd, s4 imm, s4 dreg);
 void emit_dec_mem(codegendata *cd, s4 mem);
index b2146eae5672c4265838c89a9bc45497f8fcf6ea..034ca21ef2239421c87fcad37a950f382a7e9550 100644 (file)
@@ -633,7 +633,6 @@ bool patcher_checkcast_class(patchref_t *pr)
        /* patch super class' vftbl */
 
        *((ptrint *) (ra + 1)) = (ptrint) c->vftbl;
-       *((ptrint *) (ra + 5 + 6 + 6 + 2 + 1)) = (ptrint) c->vftbl;
 
        return true;
 }
index 03bb1faf407726116c6bb6d84e17abb211aa783f..dc42a9a966075f1b9cb7a297edadb8102c9785d2 100644 (file)
@@ -2486,8 +2486,6 @@ gen_method:
                                classinfo *super;
                                s4         superindex;
 
-                               s4 looptarget;
-
                                if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                        super      = NULL;
                                        superindex = 0;
@@ -2570,64 +2568,38 @@ gen_method:
                                        M_ALD(REG_ITMP3, RIP, disp);
 
                                        if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
-                                       M_AADD_IMM(-32, REG_SP); /* need some stack */
-                                       if (s1 == REG_ITMP1)
-                                               M_AST(REG_ITMP1, REG_SP, -8 + 32);
-
-                                       M_ALD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
-
-                                       *(cd->mcodeptr++) = 0x4d;
-                                       *(cd->mcodeptr++) = 0x3b;
-                                       *(cd->mcodeptr++) = 0x1c;
-                                       *(cd->mcodeptr++) = 0x02;
-                                       /* cmp (ITMP2, ITMP1, 1), ITMP3 */
-
-                                       emit_label_beq(cd, BRANCH_LABEL_6);  /* good */
-
-                                       M_LCMP_IMM(OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1);
-                                       emit_classcast_check(cd, iptr, BRANCH_NE, REG_ITMP3, s1);
-
-                                       M_AST(REG_ITMP3, REG_SP, -16 + 32);
-                                       M_AST_IMM32(0, REG_SP, -24 + 32);
-                                       M_ALD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
-                                       looptarget = cd->mcodeptr - cd->mcodebase;
-
-                                       M_ALD(REG_ITMP3, REG_SP, -24 + 32);
-                                       M_ICMP_MEMBASE(REG_ITMP2, OFFSET(vftbl_t, subtype_overflow_length), REG_ITMP3);
-                                       emit_label_bge(cd, BRANCH_LABEL_9);  /* throw */
-
-                                       *(cd->mcodeptr++) = 0x4e;
-                                       *(cd->mcodeptr++) = 0x8b;
-                                       *(cd->mcodeptr++) = 0x1c;
-                                       *(cd->mcodeptr++) = 0xd8;
-                                       /* movq (ITMP1, ITMP3, 8), ITMP3 */
-
-                                       M_LCMP_MEMBASE(REG_SP, -16 + 32, REG_ITMP3);
-                                       emit_label_beq(cd, BRANCH_LABEL_7);  /* good */
-
-                                       M_LINC_MEMBASE(REG_SP, -24 + 32);
-                                       M_JMP_IMM2(looptarget - (cd->mcodeptr - cd->mcodebase) - 2); /* 1 byte displacement */
-
-                                       emit_label(cd, BRANCH_LABEL_9);
-                                       M_AADD_IMM(32, REG_SP); /* restore stack frame */
-                                       M_ALD_MEM(REG_ITMP3, TRAP_ClassCastException);
-
-                                       emit_label(cd, BRANCH_LABEL_7);
-
-                                       emit_label(cd, BRANCH_LABEL_6);
-
-                                       if (s1 == REG_ITMP1)
-                                               M_ALD(REG_ITMP1, REG_SP, -8 + 32);
-                                       M_AADD_IMM(32, REG_SP);
+                                               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 {
-                                               assert(super->vftbl->subtype_offset < 0x80);
-                                               *(cd->mcodeptr++) = 0x4d;
-                                               *(cd->mcodeptr++) = 0x3b;
-                                               *(cd->mcodeptr++) = 0x5a;
-                                               *(cd->mcodeptr++) = super->vftbl->subtype_offset;
-                                               /* cmp off(ITMP1), ITMP2 */
-
+                                               M_LCMP_MEMBASE(REG_ITMP2, super->vftbl->subtype_offset, REG_ITMP3);
                                                emit_classcast_check(cd, iptr, BRANCH_NE, REG_ITMP3, s1);
                                        }
 
@@ -2682,8 +2654,6 @@ gen_method:
                        classinfo *super;
                        s4         superindex;
 
-                       s4 looptarget;
-
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                super      = NULL;
                                superindex = 0;
@@ -2775,74 +2745,47 @@ gen_method:
                                M_ALD(REG_ITMP3, RIP, disp);
 
                                if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
-                               M_AADD_IMM(-32, REG_SP); /* need some stack */
-                               M_ALD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
+                                       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 */
+                                       }
 
-                               *(cd->mcodeptr++) = 0x4d;
-                               *(cd->mcodeptr++) = 0x3b;
-                               *(cd->mcodeptr++) = 0x1c;
-                               *(cd->mcodeptr++) = 0x02;
-                               /* cmp (ITMP2, ITMP1, 1), ITMP3 */
+                                       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 */
 
-                               emit_label_bne(cd, BRANCH_LABEL_6);
-                               if (d == REG_ITMP2) {
+                                       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);
-                                       M_BSEXT(d, d);
-                               } else
-                                       M_LINC(d);
-                               emit_label_br(cd, BRANCH_LABEL_7);    /* done, true */
-
-                               emit_label(cd, BRANCH_LABEL_6);
-
-                               M_LCMP_IMM(OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1);
-                               emit_label_bne(cd, BRANCH_LABEL_6);   /* done, false */
-
-                               M_AST(REG_ITMP3, REG_SP, -16 + 32);
-                               M_AST_IMM32(0, REG_SP, -24 + 32);
-                               M_ALD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
-                               looptarget = cd->mcodeptr - cd->mcodebase;
-
-                               M_ALD(REG_ITMP3, REG_SP, -24 + 32);
-                               M_ICMP_MEMBASE(REG_ITMP2, OFFSET(vftbl_t, subtype_overflow_length), REG_ITMP3);
-                               emit_label_bge(cd, BRANCH_LABEL_8);   /* done, false */
-
-                               *(cd->mcodeptr++) = 0x4e;
-                               *(cd->mcodeptr++) = 0x8b;
-                               *(cd->mcodeptr++) = 0x1c;
-                               *(cd->mcodeptr++) = 0xd8;
-                               /* movq (ITMP1, ITMP3, 8), ITMP3 */
-
-                               M_LCMP_MEMBASE(REG_SP, -16 + 32, REG_ITMP3);
-                               emit_label_bne(cd, BRANCH_LABEL_9);
-                               if (d == REG_ITMP2) {
-                                       M_SETE(d);
-                                       M_BSEXT(d, d);
-                               } else
-                                       M_LINC(d);
-                               emit_label_br(cd, BRANCH_LABEL_10);   /* done, true */
-                               emit_label(cd, BRANCH_LABEL_9);
-
-                               M_LINC_MEMBASE(REG_SP, -24 + 32);
-                               M_JMP_IMM2(looptarget - (cd->mcodeptr - cd->mcodebase) - 2); /* 1 byte displacement */
+                                       if (d == REG_ITMP2) {
+                                               M_BSEXT(d, d);
 
-                               emit_label(cd, BRANCH_LABEL_8);
-                               emit_label(cd, BRANCH_LABEL_6);
+                                               emit_label_br(cd, BRANCH_LABEL_7); /* jump over M_CLR */
+                                       }
 
-                               if (d == REG_ITMP2)
-                                       M_CLR(d);
+                                       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_10);
-                               emit_label(cd, BRANCH_LABEL_7);
-                               M_AADD_IMM(32, REG_SP);
+                                               emit_label(cd, BRANCH_LABEL_7);
+                                       }
+                                       emit_label(cd, BRANCH_LABEL_6);
                                }
                                else {
-                                       assert(super->vftbl->subtype_offset < 0x80);
-                                       *(cd->mcodeptr++) = 0x4d;
-                                       *(cd->mcodeptr++) = 0x3b;
-                                       *(cd->mcodeptr++) = 0x5a;
-                                       *(cd->mcodeptr++) = super->vftbl->subtype_offset;
-                                       /* cmp off(ITMP1), ITMP2 */
-
+                                       M_LCMP_MEMBASE(REG_ITMP2, super->vftbl->subtype_offset, REG_ITMP3);
                                        M_SETE(d);
                                        if (d == REG_ITMP2)
                                                M_BSEXT(d, d);
index c17d0138b8aaba6f81111d119c42a56d4fc82219..cb073729dd0d69d438a67e1263d05e340a0d4f3a 100644 (file)
 #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))
index 9c32e9b4a819943d351c4d63449159bc9660e079..a30f7ec45b63d6117cfdea09437538086191b1b0 100644 (file)
@@ -1401,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));
index 8d0d0ae918144309621887339d6e920c62200b71..4a1cb4c9884a8998b53b94a92ec8c6321a13abee 100644 (file)
@@ -244,6 +244,8 @@ void emit_alul_imm32_reg(codegendata *cd, s4 opc, s4 imm, s4 dreg);
 void emit_alul_imm_reg(codegendata *cd, s8 opc, s8 imm, s8 dreg);
 void emit_alu_imm_membase(codegendata *cd, s8 opc, s8 imm, s8 basereg, s8 disp);
 void emit_alul_imm_membase(codegendata *cd, s8 opc, s8 imm, s8 basereg, s8 disp);
+void emit_alu_memindex_reg(codegendata *cd, s8 opc, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 reg);
+void emit_alul_memindex_reg(codegendata *cd, s8 opc, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 reg);
 void emit_test_reg_reg(codegendata *cd, s8 reg, s8 dreg);
 void emit_testl_reg_reg(codegendata *cd, s8 reg, s8 dreg);
 void emit_test_imm_reg(codegendata *cd, s8 imm, s8 reg);
index c1b00e40b199f8a605f4a6249c62db6b88851c9f..438c7eec65a68946d4b80d2545382df13d648303 100644 (file)
@@ -546,7 +546,6 @@ static int build_display_inner(classinfo *topc, classinfo *c, int i)
        {
                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)
@@ -576,7 +575,6 @@ static void build_display(classinfo *c)
                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;
        }
 }
 
index 124f8b73161f7030beebc2ad1b6f22c1c5c57a66..b9dc1876ff4dda700a2553f243bd0cd9dbf113f7 100644 (file)
@@ -113,9 +113,8 @@ struct _vftbl {
        s4           diffval;              /* high - base for runtime type check  */
 
        s4 subtype_depth;
-       ptrint subtype_offset;
+       s4 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          */