- M_ALD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, subtype_offset));
-
- *(cd->mcodeptr++) = 0x4e;
- *(cd->mcodeptr++) = 0x3b;
- *(cd->mcodeptr++) = 0x14;
- *(cd->mcodeptr++) = 0x18;
- /* cmp (ITMP1, ITMP3, 1), ITMP2 */
-
- emit_label_beq(cd, BRANCH_LABEL_6); /* good */
-
- M_LCMP_IMM(OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP3);
- emit_classcast_check(cd, iptr, BRANCH_NE, REG_ITMP3, s1);
-
- /* use red zone */
- M_AST(REG_ITMP2, REG_SP, -16);
- M_AST_IMM32(0, REG_SP, -24);
- M_ALD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, subtype_overflow));
- looptarget = cd->mcodeptr - cd->mcodebase;
-
- M_ALD(REG_ITMP2, REG_SP, -24);
- M_ICMP_MEMBASE(REG_ITMP1, OFFSET(vftbl_t, subtype_overflow_length), REG_ITMP2);
-
- emit_classcast_check(cd, iptr, BRANCH_GE, REG_ITMP3, s1);
-
- *(cd->mcodeptr++) = 0x4f;
- *(cd->mcodeptr++) = 0x8b;
- *(cd->mcodeptr++) = 0x14;
- *(cd->mcodeptr++) = 0xd3;
- /* movq (ITMP3, ITMP2, 8), ITMP2 */
-
- M_LCMP_MEMBASE(REG_SP, -16, REG_ITMP2);
- emit_label_beq(cd, BRANCH_LABEL_7); /* good, pop */
-
- M_LINC_MEMBASE(REG_SP, -24);
- M_JMP_IMM2(looptarget - (cd->mcodeptr - cd->mcodebase) - 2); /* 1 byte displacement */
-
- emit_label(cd, BRANCH_LABEL_7);
-
- emit_label(cd, BRANCH_LABEL_6);
+ 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);