* src/vm/jit/powerpc/arch.h: Added USES_NEW_SUBTYPE.
authorStefan Ring <stefan@complang.tuwien.ac.at>
Thu, 30 Apr 2009 08:27:57 +0000 (10:27 +0200)
committerStefan Ring <stefan@complang.tuwien.ac.at>
Thu, 30 Apr 2009 08:27:57 +0000 (10:27 +0200)
* src/vm/jit/powerpc/codegen.c: New subtype code for ppc, almost identical to
the ppc64 code.
* src/vm/jit/powerpc/codegen.h: Added M_CNTLZ.
* src/vm/jit/powerpc/emit.c (emit_classcast_check): Slightly extended.

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

index ca0efa5a4512997f72f226678d00135147e684d8..e9259c4afe7c44985e96af7cc091e73d4d1cac39 100644 (file)
 
 #define REPLACEMENT_PATCH_SIZE           4 /* bytes */
 
+/* subtype ********************************************************************/
+
+#define USES_NEW_SUBTYPE                 1
+
 #endif /* _ARCH_H */
 
 
index 832958f6b990731e06a83d98b066aa10f921f228..53d4a37d852fb23465391fbded2fc451aa089f98 100644 (file)
@@ -2508,23 +2508,53 @@ 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_ISUB(REG_ITMP3, REG_ITMP1, REG_ITMP3);
+                                       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_IADD(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, 2, REG_ITMP1);
+                                               M_IADD_IMM(REG_ITMP2, -DISPLAY_SIZE*4, REG_ITMP2);
+                                               M_LWZX(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_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_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
-                                               M_ISUB(REG_ITMP3, REG_ITMP2, REG_ITMP3);
-                                               M_ALD(REG_ITMP2, REG_PV, disp);
-                                               M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
+                                               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);
                                        }
-                                       M_CMPU(REG_ITMP3, REG_ITMP2);
-                                       emit_classcast_check(cd, iptr, BRANCH_GT, REG_ITMP3, s1);
 
                                        if (super != NULL)
                                                emit_label(cd, BRANCH_LABEL_5);
@@ -2591,12 +2621,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 */
@@ -2613,25 +2642,31 @@ 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);
+
+                               M_ADDIC(REG_ITMP1, -1, d);
+                               M_SUBE(REG_ITMP1, d, d);
 
                                if (super == NULL)
                                        emit_label_br(cd, BRANCH_LABEL_4);
@@ -2655,21 +2690,65 @@ gen_method:
                                        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_IADD(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_ISUB(REG_ITMP1, REG_ITMP3, 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, 2, REG_ITMP1);
+                                       M_IADD_IMM(REG_ITMP2, -DISPLAY_SIZE*4, REG_ITMP2);
+                                       M_LWZX(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_RLWINM(d, 27, 5, 31, 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_RLWINM(d, 27, 5, 31, d);
+                               }
 
                                if (super != NULL)
                                        emit_label(cd, BRANCH_LABEL_5);
index 8ed75e85cb5c91cacd3420f036c4c2830930059c..6081382ea554d3723318b6912fa339e8a041c552 100644 (file)
 #define M_CMPI(a,b)                     M_OP2_IMM(11, 0, a, b)
 #define M_CMPU(a,b)                     M_OP3(31, 32, 0, 0, 0, a, b)
 #define M_CMPUI(a,b)                    M_OP2_IMM(10, 0, a, b)
+#define M_CNTLZ(a,b)                    M_OP3(31, 26, 0, 0, a, b, 0)
 #define M_CZEXT(a,b)                    M_RLWINM(a,0,16,31,b)
 #define M_IADD(a,b,c)                   M_OP3(31, 266, 0, 0, c, a, b)
 #define M_IADD_IMM(a,b,c)               M_OP2_IMM(14, c, a, b)
index 6065246b943c8de4a401b28c7f928537b8adee51..74adff082fc03ab3c668b84d410b659823448cf4 100644 (file)
@@ -480,6 +480,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;