* src/vm/jit/powerpc64/arch.h: Added USES_NEW_SUBTYPE.
authorStefan Ring <stefan@complang.tuwien.ac.at>
Mon, 20 Apr 2009 10:10:53 +0000 (12:10 +0200)
committerStefan Ring <stefan@complang.tuwien.ac.at>
Mon, 20 Apr 2009 10:10:53 +0000 (12:10 +0200)
* src/vm/jit/powerpc64/codegen.c: New subtype code for ppc64, brought closer
in line with the Alpha version.
* src/vm/jit/powerpc64/codegen.h: Added M_RLDICL, M_CNTLZ.
* src/vm/jit/powerpc64/emit.c (emit_classcast_check): Slightly extended.

src/vm/jit/powerpc64/arch.h
src/vm/jit/powerpc64/codegen.c
src/vm/jit/powerpc64/codegen.h
src/vm/jit/powerpc64/emit.c

index 33651985ca75c0977c2b1ae805475f0d7a753ea0..b10b650f98b727148204850c91fa05f9f586cb6e 100644 (file)
 
 #define REPLACEMENT_PATCH_SIZE           4 /* bytes */
 
+/* subtype ********************************************************************/
+
+#define USES_NEW_SUBTYPE                 1
+
 #endif /* _ARCH_H */
 
 
index 4bfc7120698e3ece4147896d3accd50ec5c28e5d..445195d5da0ac105c0de7bebfda70b2370e9d20c 100644 (file)
@@ -2269,25 +2269,54 @@ gen_method:
                                        }
 
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
-
-                                       M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
-                                       M_ALD(REG_ITMP2, REG_PV, disp);
-                                       if (s1 != REG_ITMP1) {
-                                               M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, baseval));
-                                               M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
-
-                                               M_SUB(REG_ITMP3, REG_ITMP1, REG_ITMP3);
-                                               M_EXTSW(REG_ITMP3, REG_ITMP3);
-                                       } else {
-                                               M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
-                                               M_SUB(REG_ITMP3, REG_ITMP2, REG_ITMP3);
-                                               M_EXTSW(REG_ITMP3, REG_ITMP3);
-                                               M_ALD(REG_ITMP2, REG_PV, disp);
-                                               M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
+                                       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_CMP(REG_ITMP1, REG_ITMP3);
+                                               emit_label_beq(cd, BRANCH_LABEL_6);  /* good */
+
+                                               if (super == NULL) {
+                                                       M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
+                                                       M_CMPI(REG_ITMP1, OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]));
+                                                       emit_label_bne(cd, BRANCH_LABEL_10);  /* throw */
+                                               }
+
+                                               M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
+                                               M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, subtype_depth));
+                                               M_CMP(REG_ITMP1, REG_ITMP3);
+                                               emit_label_bgt(cd, BRANCH_LABEL_9);  /* throw */
+                                               /* reload */
+                                               M_ALD(REG_ITMP3, REG_PV, disp);
+                                               M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
+
+                                               M_SLL_IMM(REG_ITMP1, 3, REG_ITMP1);
+                                               M_IADD_IMM(REG_ITMP2, -DISPLAY_SIZE*8, REG_ITMP2);
+                                               M_ALDX(REG_ITMP1, REG_ITMP2, REG_ITMP1);
+                                               M_CMP(REG_ITMP1, 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_LWZ(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);
                                        }
-                                       M_CMPU(REG_ITMP3, REG_ITMP2);
-                                       emit_classcast_check(cd, iptr, BRANCH_GT, REG_ITMP3, s1);
-                                       
+                                       else {
+                                               M_ALD(REG_ITMP2, REG_ITMP2, super->vftbl->subtype_offset);
+                                               M_CMP(REG_ITMP2, REG_ITMP3);
+                                               emit_classcast_check(cd, iptr, BRANCH_NE, REG_ITMP2, s1);
+                                       }
+
                                        if (super != NULL)
                                                emit_label(cd, BRANCH_LABEL_5);
                                }
@@ -2367,12 +2396,11 @@ gen_method:
                                s1 = REG_ITMP1;
                        }
 
-                       M_CLR(d);
-
                        /* if class is not resolved, check which code to call */
 
                        if (super == NULL) {
                                M_TST(s1);
+                               M_CLR(d);
                                emit_label_beq(cd, BRANCH_LABEL_1);
                                disp = dseg_add_unique_s4(cd, 0);                     /* super->flags */
 
@@ -2388,25 +2416,32 @@ gen_method:
 
                        if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
                                if (super == NULL) {
+                                       /* If d == REG_ITMP2, then it's destroyed in check
+                                          code above. */
+                                       if (d == REG_ITMP2)
+                                               M_CLR(d);
+
                                        patcher_add_patch_ref(jd,
                                                                                PATCHER_instanceof_interface,
                                                                                iptr->sx.s23.s3.c.ref, 0);
 
                                } else {
                                        M_TST(s1);
+                                       M_CLR(d);
                                        emit_label_beq(cd, BRANCH_LABEL_3);
                                }
 
                                M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
                                M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
                                M_LDATST(REG_ITMP3, REG_ITMP3, -superindex);
-                               M_BLE(4);
+                               M_BLE(3);
                                M_ALD(REG_ITMP1, REG_ITMP1,
                                          OFFSET(vftbl_t, interfacetable[0]) -
                                          superindex * sizeof(methodptr*));
-                               M_TST(REG_ITMP1);
-                               M_BEQ(1);
-                               M_IADD_IMM(REG_ZERO, 1, d);
+                               /* This seems to be the canonical sequence to emulate
+                                * the Alpha instruction M_CMPULT(zero,x) (check for non-null). */
+                               M_ADDIC(REG_ITMP1, -1, d);
+                               M_SUBE(REG_ITMP1, d, d);
 
                                if (super == NULL)      {
                                        emit_label_br(cd, BRANCH_LABEL_4);
@@ -2429,23 +2464,67 @@ gen_method:
 
                                } else {
                                        disp = dseg_add_address(cd, super->vftbl);
+
                                        M_TST(s1);
+                                       M_CLR(d);
                                        emit_label_beq(cd, BRANCH_LABEL_5);
                                }
 
-                               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);
 
-                               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));
+                               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_CMP(REG_ITMP1, REG_ITMP3);
+                                       emit_label_bne(cd, BRANCH_LABEL_8);
+                                       ICONST(d, 1);
+                                       emit_label_br(cd, BRANCH_LABEL_6);  /* true */
+                                       emit_label(cd, BRANCH_LABEL_8);
 
-                               M_SUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
-                               M_EXTSW(REG_ITMP1, REG_ITMP1);
-                               M_CMPU(REG_ITMP1, REG_ITMP2);
-                               M_CLR(d);
-                               M_BGT(1);
-                               M_IADD_IMM(REG_ZERO, 1, d);
+                                       if (super == NULL) {
+                                               M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
+                                               M_CMPI(REG_ITMP1, OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]));
+                                               emit_label_bne(cd, BRANCH_LABEL_10);  /* false */
+                                       }
+
+                                       M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
+
+                                       M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, subtype_depth));
+                                       M_CMP(REG_ITMP1, REG_ITMP3);
+                                       emit_label_bgt(cd, BRANCH_LABEL_9);  /* false */
+                                       /* reload */
+                                       M_ALD(REG_ITMP3, REG_PV, disp);
+                                       M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
+
+                                       M_SLL_IMM(REG_ITMP1, 3, REG_ITMP1);
+                                       M_IADD_IMM(REG_ITMP2, -DISPLAY_SIZE*8, REG_ITMP2);
+                                       M_ALDX(REG_ITMP1, REG_ITMP2, REG_ITMP1);
+                                       /* This seems to be the canonical sequence to emulate
+                                        * the Alpha instruction M_CMPEQ. */
+                                       M_XOR(REG_ITMP1, REG_ITMP3, d);
+                                       M_CNTLZ(d, d);
+                                       M_RLDICL(d, 58, 6, 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_XOR(REG_ITMP2, REG_ITMP3, d);
+                                       M_CNTLZ(d, d);
+                                       M_RLDICL(d, 58, 6, d);
+                               }
 
                                if (super != NULL)
                                        emit_label(cd, BRANCH_LABEL_5);
index df9120f088af2393c10f792277c962306969c9c5..ca1a20a0d0d1822c4833818a702c39bc1bf1d83c 100644 (file)
 #define M_SRL_IMM(a,b,c)                M_OP3(30, ((64-(b))&0x20 ? 1:0), 0, (((((b))&0x1f)<<6) | ((((b))&0x20 ? 1:0)<<5) | 0x00), a, c, (64-(b))&0x1f);
 #define M_SRA(a,b,c)                    M_OP3(31, 794, 0, 0, a, c, b)
 #define M_SRA_IMM(a,b,c)                M_OP3(31, (826 | ((b)&0x20?1:0)), 0, 0, a, c, ((b)&0x1f))
+#define M_RLDICL(a,b,c,d)               M_OP4(30, ((b)&0x20 ? 1:0), 0, a, d, (b)&0x1f, c)
+#define M_CNTLZ(a,b)                    M_OP3(31, 58, 0, 0, a, b, 0)
 
 #define M_MUL(a,b,c)                   M_OP3(31, 233, 0, 0, c, a, b)
 #define M_MUL_IMM(a,b,c)               M_OP2_IMM(7, c, a, b)
index 3009eac9843545bcee8773b63c6a65f490127c61..a969a3bc5688f0814e54ba698d278fba64cfbba7 100644 (file)
@@ -569,6 +569,9 @@ void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 r
                case BRANCH_EQ:
                        M_BNE(1);
                        break;
+               case BRANCH_NE:
+                       M_BEQ(1);
+                       break;
                case BRANCH_GT:
                        M_BLE(1);
                        break;