--- old/test/compiler/valhalla/valuetypes/ValueTypeTestBench.java 2017-05-05 11:33:46.538987551 +0200 +++ new/test/compiler/valhalla/valuetypes/ValueTypeTestBench.java 2017-05-05 11:33:46.410987555 +0200 @@ -32,13 +32,16 @@ * @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; @@ -72,16 +75,20 @@ 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; @@ -92,6 +99,8 @@ 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; @@ -99,12 +108,14 @@ @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 @@ -123,6 +134,9 @@ 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); @@ -135,25 +149,34 @@ 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(); @@ -181,6 +204,18 @@ } @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; @@ -487,7 +522,7 @@ } // 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) { @@ -666,7 +701,7 @@ @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")); @@ -677,7 +712,7 @@ @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()); } @@ -1170,6 +1205,7 @@ } } + // Merge value type arrays created from two branches @Test(failOn = (TRAP)) public MyValue1[] test45(boolean b) { MyValue1[] va; @@ -1221,7 +1257,7 @@ 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 @@ -1236,7 +1272,7 @@ 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()); } } @@ -1286,13 +1322,13 @@ 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 @@ -1444,8 +1480,7 @@ } // 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(); } @@ -1500,16 +1535,16 @@ public static MethodHandle generateNullVCCUnboxLoadLongMH() { return MethodHandleBuilder.loadCode(MethodHandles.lookup(), - "nullvccUnboxLoadLong", - MethodType.methodType(long.class), - CODE -> { - CODE. - aconst_null(). - vunbox(ValueType.forClass(ValueCapableClass1.class).valueClass()). - getfield(ValueCapableClass1.class, "t", "J"). - lreturn(); - } - ); + "nullvccUnboxLoadLong", + MethodType.methodType(long.class), + CODE -> { + CODE. + aconst_null(). + vunbox(ValueType.forClass(ValueCapableClass1.class).valueClass()). + getfield(ValueCapableClass1.class, "t", "J"). + lreturn(); + } + ); } /* The compiler is supposed to determine that the allocated @@ -1530,16 +1565,16 @@ public static MethodHandle generateCheckedVCCUnboxLoadLongMH() { return MethodHandleBuilder.loadCode(MethodHandles.lookup(), - "checkedVCCUnboxLoadLongMH", - MethodType.methodType(long.class), - CODE -> { - CODE. - invokestatic(ValueCapableClass1.class, "createInline", "()Lcompiler/valhalla/valuetypes/ValueCapableClass1;", false). - vunbox(ValueType.forClass(ValueCapableClass1.class).valueClass()). - vgetfield(ValueType.forClass(ValueCapableClass1.class).valueClass(), "t", "J"). - lreturn(); - } - ); + "checkedVCCUnboxLoadLongMH", + MethodType.methodType(long.class), + CODE -> { + CODE. + invokestatic(ValueCapableClass1.class, "createInline", "()Lcompiler/valhalla/valuetypes/ValueCapableClass1;", false). + vunbox(ValueType.forClass(ValueCapableClass1.class).valueClass()). + vgetfield(ValueType.forClass(ValueCapableClass1.class).valueClass(), "t", "J"). + lreturn(); + } + ); } /* The compiler is supposed to emit a runtime null check because @@ -1652,10 +1687,29 @@ vbox(ValueCapableClass1.class). getfield(ValueCapableClass1.class, "t", "J"). 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(); @@ -1682,14 +1736,14 @@ 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; @@ -1731,12 +1785,12 @@ //tests.values().removeIf(p -> !p.getName().equals("test64")); // Run single test if (args.length == 0) { execute_vm("-XX:+IgnoreUnrecognizedVMOptions", "-XX:-BackgroundCompilation", - "-XX:+PrintCompilation", "-XX:+PrintInlining", "-XX:+PrintIdeal", "-XX:+PrintOptoAssembly", - "-XX:CompileCommand=quiet", "-XX:CompileCommand=compileonly,compiler.valhalla.valuetypes.ValueTypeTestBench::*", - "-XX:CompileCommand=compileonly,compiler.valhalla.valuetypes.MyValue1::*", - "-XX:CompileCommand=compileonly,compiler.valhalla.valuetypes.MyValue2::*", - "-XX:CompileCommand=compileonly,java.lang.Object::", - "-XX:CompileCommand=inline,java.lang.__Value::hashCode"); + "-XX:+PrintCompilation", "-XX:+PrintInlining", "-XX:+PrintIdeal", "-XX:+PrintOptoAssembly", + "-XX:CompileCommand=quiet", "-XX:CompileCommand=compileonly,compiler.valhalla.valuetypes.ValueTypeTestBench::*", + "-XX:CompileCommand=compileonly,compiler.valhalla.valuetypes.MyValue1::*", + "-XX:CompileCommand=compileonly,compiler.valhalla.valuetypes.MyValue2::*", + "-XX:CompileCommand=compileonly,java.lang.Object::", + "-XX:CompileCommand=inline,java.lang.__Value::hashCode"); } else { // Execute tests ValueTypeTestBench bench = new ValueTypeTestBench();