< prev index next >

test/compiler/valhalla/valuetypes/ValueTypeTestBench.java

Print this page

        

@@ -30,17 +30,20 @@
  * @build compiler.valhalla.valuetypes.ValueTypeTestBench
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  * @run main ClassFileInstaller jdk.test.lib.Platform
  * @run main/othervm -ea -noverify -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
  *                   -XX:+UnlockExperimentalVMOptions -XX:+ValueTypePassFieldsAsArgs -XX:+ValueArrayFlatten -XX:+VerifyAdapterSharing
- *                   -XX:-TieredCompilation compiler.valhalla.valuetypes.ValueTypeTestBench
+ *                   -XX:ValueArrayElemMaxFlatSize=-1 -XX:ValueArrayElemMaxFlatOops=-1 -XX:-TieredCompilation
+ *                   compiler.valhalla.valuetypes.ValueTypeTestBench
  * @run main/othervm -ea -noverify -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
  *                   -XX:+UnlockExperimentalVMOptions -XX:-ValueTypePassFieldsAsArgs -XX:-ValueArrayFlatten
- *                   -XX:-TieredCompilation compiler.valhalla.valuetypes.ValueTypeTestBench
+ *                   -XX:ValueArrayElemMaxFlatSize=-1 -XX:ValueArrayElemMaxFlatOops=-1 -XX:-TieredCompilation
+ *                   compiler.valhalla.valuetypes.ValueTypeTestBench
  * @run main/othervm -ea -noverify -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
  *                   -XX:+UnlockExperimentalVMOptions -XX:+AlwaysIncrementalInline -XX:+ValueArrayFlatten
- *                   -XX:-TieredCompilation compiler.valhalla.valuetypes.ValueTypeTestBench
+ *                   -XX:ValueArrayElemMaxFlatSize=-1 -XX:ValueArrayElemMaxFlatOops=-1 -XX:-TieredCompilation
+ *                   compiler.valhalla.valuetypes.ValueTypeTestBench
  */
 
 package compiler.valhalla.valuetypes;
 
 import compiler.whitebox.CompilerWhiteBoxTest;

@@ -70,43 +73,51 @@
     static int s;
     static final long sf = ValueTypeTestBench.rL;
     final int x;
     final long y;
     final short z;
+    final Integer o;
+    final int[] oa;
     final MyValue2 v1;
     final MyValue2 v2;
     static final MyValue2 v3 = MyValue2.createInline(ValueTypeTestBench.rI, true);
     final int c;
 
-    private MyValue1(int x, long y, short z, MyValue2 v1, MyValue2 v2, int c) {
+    private MyValue1(int x, long y, short z, Integer o, int[] oa, MyValue2 v1, MyValue2 v2, int c) {
         s = x;
         this.x = x;
         this.y = y;
         this.z = z;
+        this.o = o;
+        this.oa = oa;
         this.v1 = v1;
         this.v2 = v2;
         this.c = c;
     }
 
     private MyValue1() {
         s = 0;
         this.x = 0;
         this.y = 0;
         this.z = 0;
+        this.o = null;
+        this.oa = null;
         this.v1 = MyValue2.createDefaultInline();
         this.v2 = MyValue2.createDefaultInline();
         this.c = 0;
     }
 
     @DontInline
     public static MyValue1 createDontInline(int x, long y) {
-        return __Make MyValue1(x, y, (short)x, MyValue2.createInline(x, true), MyValue2.createInline(x, false), ValueTypeTestBench.rI);
+        int[] oa = {x};
+        return __Make MyValue1(x, y, (short)x, new Integer(x), oa, MyValue2.createInline(x, true), MyValue2.createInline(x, false), ValueTypeTestBench.rI);
     }
 
     @ForceInline
     public static MyValue1 createInline(int x, long y) {
-        return __Make MyValue1(x, y, (short)x, MyValue2.createInline(x, true), MyValue2.createInline(x, false), ValueTypeTestBench.rI);
+        int[] oa = {x};
+        return __Make MyValue1(x, y, (short)x, new Integer(x), oa, MyValue2.createInline(x, true), MyValue2.createInline(x, false), ValueTypeTestBench.rI);
     }
 
     @DontInline
     __ValueFactory static MyValue1 createDefaultDontInline() {
         return __MakeDefault MyValue1();

@@ -121,10 +132,13 @@
     static MyValue1 createWithFieldsDontInline(int x, long y) {
         MyValue1 v = createDefaultInline();
         v = setX(v, x);
         v = setY(v, y);
         v = setZ(v, (short)x);
+        v = setO(v, new Integer(x));
+        int[] oa = {x};
+        v = setOA(v, oa);
         v = setV1(v, MyValue2.createWithFieldsInline(x, x < y));
         v = setV2(v, MyValue2.createWithFieldsInline(x, x > y));
         v = setC(v, ValueTypeTestBench.rI);
         return v;
     }

@@ -133,29 +147,38 @@
     static MyValue1 createWithFieldsInline(int x, long y) {
         MyValue1 v = createDefaultInline();
         v = setX(v, x);
         v = setY(v, y);
         v = setZ(v, (short)x);
+        v = setO(v, new Integer(x));
+        int[] oa = {x};
+        v = setOA(v, oa);
         v = setV1(v, MyValue2.createWithFieldsInline(x, x < y));
         v = setV2(v, MyValue2.createWithFieldsInline(x, x > y));
         v = setC(v, ValueTypeTestBench.rI);
         return v;
     }
 
+    // Hash only primitive and value type fields to avoid NullPointerException
     @ForceInline
-    public long hash() {
+    public long hashPrimitive() {
         return s + sf + x + y + z + c + v1.hash() + v2.hash() + v3.hash();
     }
 
+    @ForceInline
+    public long hash() {
+        return hashPrimitive() + o + oa[0];
+    }
+
     @DontCompile
     public long hashInterpreted() {
-        return s + sf + x + y + z + c + v1.hashInterpreted() + v2.hashInterpreted() + v3.hashInterpreted();
+        return s + sf + x + y + z + o + oa[0] + c + v1.hashInterpreted() + v2.hashInterpreted() + v3.hashInterpreted();
     }
 
     @ForceInline
     public void print() {
-        System.out.print("s=" + s + ", sf=" + sf + ", x=" + x + ", y=" + y + ", z=" + z + ", v1[");
+        System.out.print("s=" + s + ", sf=" + sf + ", x=" + x + ", y=" + y + ", z=" + z + ", o=" + (o != null ? (Integer)o : "NULL") + ", v1[");
         v1.print();
         System.out.print("], v2[");
         v2.print();
         System.out.print("], v3[");
         v3.print();

@@ -179,10 +202,22 @@
         v.z = z;
         return v;
     }
 
     @ForceInline
+    __ValueFactory static MyValue1 setO(MyValue1 v, Integer o) {
+        v.o = o;
+        return v;
+    }
+
+    @ForceInline
+    __ValueFactory static MyValue1 setOA(MyValue1 v, int[] oa) {
+        v.oa = oa;
+        return v;
+    }
+
+    @ForceInline
     __ValueFactory static MyValue1 setC(MyValue1 v, int c) {
         v.c = c;
         return v;
     }
 

@@ -485,11 +520,11 @@
         long result = test10(rI, rL);
         Asserts.assertEQ(result, hash(rI + 10, rL + 10));
     }
 
     // Merge value types created in a loop (inlined)
-    @Test(failOn = ALLOC + LOAD + STORE + LOOP + TRAP)
+    @Test(failOn = ALLOC + LOAD + STORE + TRAP)
     public long test11(int x, long y) {
         MyValue1 v = MyValue1.createInline(x, y);
         for (int i = 0; i < 10; ++i) {
             v = MyValue1.createInline(v.x + 1, v.y + 1);
         }

@@ -664,22 +699,22 @@
     // correctly allocated.
     @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = LOAD + ALLOC + STORE)
     @Test(valid = ValueTypePassFieldsAsArgsOff, match = {ALLOC}, matchCount = {2}, failOn = LOAD)
     public long test20(boolean deopt) {
         MyValue1 v = MyValue1.createInline(rI, rL);
-        MyValue1[] va = new MyValue1[3];
+        MyValue2[] va = new MyValue2[3];
         if (deopt) {
             // uncommon trap
             WHITE_BOX.deoptimizeMethod(tests.get("ValueTypeTestBench::test20"));
         }
         return v.hashInterpreted() + va[0].hashInterpreted() +
                 va[1].hashInterpreted() + va[2].hashInterpreted();
     }
 
     @DontCompile
     public void test20_verifier(boolean warmup) {
-        MyValue1[] va = new MyValue1[42];
+        MyValue2[] va = new MyValue2[42];
         long result = test20(!warmup);
         Asserts.assertEQ(result, hash() + va[0].hash() + va[1].hash() + va[2].hash());
     }
 
     // Value type fields in regular object

@@ -1168,10 +1203,11 @@
         for (int i = 0; i < 10; ++i) {
             Asserts.assertEQ(va[i].hash(), hash(rI + i, rL + i));
         }
     }
 
+    // Merge value type arrays created from two branches
     @Test(failOn = (TRAP))
     public MyValue1[] test45(boolean b) {
         MyValue1[] va;
         if (b) {
             va = new MyValue1[5];

@@ -1219,11 +1255,11 @@
 
     @DontCompile
     public void test46_verifier(boolean warmup) {
         MyValue1[] va = new MyValue1[1];
         MyValue1 v = test46();
-        Asserts.assertEQ(v.hash(), va[0].hash());
+        Asserts.assertEQ(v.hashPrimitive(), va[0].hashPrimitive());
     }
 
     // Test default initialization of value type arrays
     @Test(failOn = LOAD)
     public MyValue1[] test47(int len) {

@@ -1234,11 +1270,11 @@
     public void test47_verifier(boolean warmup) {
         int len = Math.abs(rI % 10);
         MyValue1[] va = new MyValue1[len];
         MyValue1[] var = test47(len);
         for (int i = 0; i < len; ++i) {
-            Asserts.assertEQ(va[i].hash(), var[i].hash());
+            Asserts.assertEQ(va[i].hashPrimitive(), var[i].hashPrimitive());
         }
     }
 
     // Test creation of value type array with zero length
     @Test(failOn = ALLOC + LOAD + STORE + LOOP + TRAP)

@@ -1284,17 +1320,17 @@
     // test vdefault
     @Test(failOn = ALLOC + STORE + LOOP + TRAP)
     public long test51() {
         MyValue1 v1 = MyValue1.createDefaultInline();
         MyValue1 v2 = MyValue1.createDefaultDontInline();
-        return v1.hash() + v2.hash();
+        return v1.hashPrimitive() + v2.hashPrimitive();
     }
 
     @DontCompile
     public void test51_verifier(boolean warmup) {
         long result = test51();
-        Asserts.assertEQ(result, 2 * MyValue1.createDefaultInline().hash());
+        Asserts.assertEQ(result, 2 * MyValue1.createDefaultInline().hashPrimitive());
     }
 
     // test vwithfield
     @Test(failOn = ALLOC + LOAD + LOADP + STORE + LOOP + TRAP)
     public long test52() {

@@ -1442,12 +1478,11 @@
     public void test58_verifier(boolean warmup) {
         test58();
     }
 
     // When calling a method on __Value, passing fields as arguments is impossible
-    @Test(valid = ValueTypePassFieldsAsArgsOn, match = {ALLOC, STORE}, matchCount={1, 0})
-    @Test(valid = ValueTypePassFieldsAsArgsOff, failOn = STORE + LOAD)
+    @Test(failOn = ALLOC + STORE + LOAD)
     public String test59(MyValue1 v) {
         return v.toString();
     }
 
     @DontCompile

@@ -1654,10 +1689,29 @@
                     lreturn();
                }
                 );
     }
 
+    // Test GC with heap allocated value type containing reference field
+    @Test()
+    public long test66() {
+        MyValue1 v = MyValue1.createInline(rI, rL);
+        long result = 0;
+        for (int i = 0 ; i < 10_000; ++i) {
+            // The C2I adapter allocates the value type at every call which
+            // triggers intermittent GCs that scan the stack frames for oops.
+            result = v.hashInterpreted();
+        }
+        return result;
+    }
+
+    @DontCompile
+    public void test66_verifier(boolean warmup) {
+        long result = test66();
+        Asserts.assertEQ(result, hash());
+    }
+
     // ========== Test infrastructure ==========
 
     private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
     private static final int ValueTypePassFieldsAsArgsOn = 0x1;
     private static final int ValueTypePassFieldsAsArgsOff = 0x2;

@@ -1680,18 +1734,18 @@
 
     // Regular expressions used  to match nodes in the PrintIdeal output
     private static final String START = "(\\d+\\t(.*";
     private static final String MID = ".*)+\\t===.*";
     private static final String END = ")|";
-    private static final String ALLOC  = START + "CallStaticJava" + MID + "_new_instance_Java" + END;
-    private static final String ALLOCA = START + "CallStaticJava" + MID + "_new_array_Java" + END;
+    private static final String ALLOC  = "(.*RSI, precise klass compiler/valhalla/valuetypes/MyValue.*" + END;
+    private static final String ALLOCA = "(.*RSI, precise klass \\[Qcompiler/valhalla/valuetypes/MyValue.*" + END;
     private static final String LOAD   = START + "Load(B|S|I|L|F|D)" + MID + "valuetype\\*" + END;
     private static final String LOADP  = START + "Load(P|N)" + MID + "valuetype\\*" + END;
     private static final String STORE  = START + "Store(B|S|I|L|F|D)" + MID + "valuetype\\*" + END;
     private static final String STOREP = START + "Store(P|N)" + MID + "valuetype\\*" + END;
     private static final String LOOP   = START + "Loop" + MID + "" + END;
-    private static final String TRAP   = START + "CallStaticJava" + MID + "uncommon_trap" + END;
+    private static final String TRAP   = START + "CallStaticJava" + MID + "uncommon_trap.*(unstable_if|predicate)" + END;
     private static final String RETURN = START + "Return" + MID + "returns" + END;
     private static final String LINKTOSTATIC = START + "CallStaticJava" + MID + "linkToStatic" + END;
     private static final String NPE = START + "CallStaticJava" + MID + "null_check" + END;
     private static final String CCE = START + "CallStaticJava" + MID + "class_check" + END;
     // TODO: match field values of scalar replaced object
< prev index next >