Merged trunk and subtype.
[cacao.git] / src / vm / jit / x86_64 / codegen.c
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);