< prev index next >
test/compiler/valhalla/valuetypes/ValueTypeTestBench.java
Print this page
@@ -28,14 +28,14 @@
* @library /testlibrary /test/lib /compiler/whitebox /
* @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:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
- * -XX:+UnlockExperimentalVMOptions -XX:+ValueTypePassFieldsAsArgs
+ * -XX:+UnlockExperimentalVMOptions -XX:+ValueTypePassFieldsAsArgs -XX:+ValueArrayFlatten
* -XX:-TieredCompilation compiler.valhalla.valuetypes.ValueTypeTestBench
* @run main/othervm -ea -noverify -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
- * -XX:+UnlockExperimentalVMOptions -XX:-ValueTypePassFieldsAsArgs
+ * -XX:+UnlockExperimentalVMOptions -XX:-ValueTypePassFieldsAsArgs -XX:-ValueArrayFlatten
* -XX:-TieredCompilation compiler.valhalla.valuetypes.ValueTypeTestBench
*/
package compiler.valhalla.valuetypes;
@@ -98,10 +98,21 @@
@DontCompile
public long hashInterpreted() {
return s + sf + x + y + c + v1.hashInterpreted() + v2.hashInterpreted() + v3.hashInterpreted();
}
+
+ @ForceInline
+ public void print() {
+ System.out.print("s=" + s + ", sf=" + sf + ", x=" + x + ", y=" + y + ", v1[");
+ v1.print();
+ System.out.print("], v2[");
+ v2.print();
+ System.out.print("], v3[");
+ v3.print();
+ System.out.print("], c=" + c);
+ }
}
__ByValue final class MyValue2 {
final int x;
final boolean b;
@@ -125,10 +136,15 @@
@DontInline
public long hashInterpreted() {
return x + (b ? 0 : 1) + c;
}
+
+ @ForceInline
+ public void print() {
+ System.out.print("x=" + x + ", b=" + b + ", c=" + c);
+ }
}
public class ValueTypeTestBench {
// Print ideal graph after execution of each test
private static final boolean PRINT_GRAPH = true;
@@ -281,11 +297,13 @@
Asserts.assertEQ(test8(true), hash());
Asserts.assertEQ(test8(false), hash(rI + 1, rL + 1));
}
// Merge value types created from two branches
- @Test(valid = ValueTypePassFieldsAsArgsOn, match = {LOAD}, matchCount = {9}, failOn = TRAP + ALLOC + STORE)
+ @Test(valid = ValueTypePassFieldsAsArgsOn, match = {LOAD}, matchCount = {7}, failOn = TRAP + ALLOC + STORE)
+ // FIXME
+ //@Test(valid = ValueTypePassFieldsAsArgsOff, match = {ALLOC, STORE}, matchCount = {1, 9}, failOn = LOAD + TRAP)
@Test(valid = ValueTypePassFieldsAsArgsOff, match = {ALLOC, STORE}, matchCount = {1, 3}, failOn = LOAD + TRAP)
public MyValue1 test9(boolean b) {
MyValue1 v;
if (b) {
// Value type is not allocated
@@ -393,11 +411,11 @@
Asserts.assertEQ(result, warmup ? 42 + (1000*rI) : hash());
}
// Create a value type in a non-inlined method and then call a
// non-inlined method on that value type.
- @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = (ALLOC + STORE + TRAP), match = {LOAD}, matchCount = {9})
+ @Test(valid = ValueTypePassFieldsAsArgsOn, failOn = (ALLOC + STORE + TRAP), match = {LOAD}, matchCount = {7})
@Test(valid = ValueTypePassFieldsAsArgsOff, failOn = (ALLOC + LOAD + STORE + TRAP))
public long test14() {
MyValue1 v = MyValue1.createDontInline(rI, rL);
return v.hashInterpreted();
}
@@ -487,32 +505,35 @@
public void test19_verifier(boolean warmup) {
long result = test19();
Asserts.assertEQ(result, hash());
}
- // Create a value type in compiled code and pass it to the
+ // Create a value type (array) in compiled code and pass it to the
// interpreter via a call. The value type is live at the uncommon
// trap: verify that deoptimization causes the value type to be
// correctly allocated.
@Test(valid = ValueTypePassFieldsAsArgsOn, failOn = LOAD + ALLOC + STORE)
@Test(valid = ValueTypePassFieldsAsArgsOff, match = {ALLOC}, matchCount = {1}, failOn = LOAD)
public long test20(boolean flag) {
MyValue1 v = MyValue1.createInline(rI, rL);
+ // TODO add value type array testcase
+ // MyValue1[] va = new MyValue1[42];
if (flag) {
// uncommon trap
WHITE_BOX.deoptimizeMethod(tests.get("ValueTypeTestBench::test20"));
}
- return v.hashInterpreted();
+ return v.hashInterpreted(); // + va[0].hashInterpreted();
}
@DontCompile
public void test20_verifier(boolean warmup) {
+ MyValue1[] va = new MyValue1[42];
long result = test20(false);
- Asserts.assertEQ(result, hash());
+ Asserts.assertEQ(result, hash() /* + va[0].hash() */);
if (!warmup) {
result = test20(true);
- Asserts.assertEQ(result, hash());
+ Asserts.assertEQ(result, hash() /* + va[0].hash() */);
}
}
// Value type fields in regular object
MyValue1 val1;
@@ -565,23 +586,26 @@
// Test OSR compilation
@Test(failOn = ALLOC + LOAD + STORE + LOOP + TRAP)
public long test23() {
MyValue1 v = MyValue1.createInline(rI, rL);
+ // TODO add OSR testcase for value type arrays
+ //MyValue1[] va = new MyValue1[10];
long result = 0;
// Long loop to trigger OSR compilation
for (int i = 0 ; i < 100_000 ; ++i) {
// Reference local value type in interpreter state
- result = v.hash();
+ result = v.hash(); // + va[0].hash();
}
return result;
}
@DontCompile
public void test23_verifier(boolean warmup) {
+ //MyValue1[] va = new MyValue1[10];
long result = test23();
- Asserts.assertEQ(result, hash());
+ Asserts.assertEQ(result, hash() /* + va[0].hash() */);
}
// Test interpreter to compiled code with various signatures
@Test(failOn = ALLOC + STORE + TRAP)
public long test24(MyValue2 v) {
@@ -816,11 +840,10 @@
lreturn();
}
);
}
-
@Test
public int test38() throws Throwable {
return (int)vccUnboxLoadIntMH.invokeExact(vcc);
}
@@ -910,19 +933,186 @@
vbox(ValueCapableClass1.class).
getfield(ValueCapableClass1.class, "x", "I").
ireturn();
}
);
+
+ }
+
+ // Test value type array creation and initialization
+ @Test(valid = ValueTypeArrayFlattenOff, failOn = (LOAD))
+ @Test(valid = ValueTypeArrayFlattenOn)
+ public MyValue1[] test41(int len) {
+ MyValue1[] va = new MyValue1[len];
+ for (int i = 0; i < len; ++i) {
+ va[i] = MyValue1.createDontInline(rI, rL);
+ }
+ return va;
+ }
+
+ @DontCompile
+ public void test41_verifier(boolean warmup) {
+ int len = Math.abs(rI % 10);
+ MyValue1[] va = test41(len);
+ for (int i = 0; i < len; ++i) {
+ Asserts.assertEQ(va[i].hash(), hash());
+ }
+ }
+
+ // Test creation of a value type array and element access
+ @Test(failOn = (LOOP + LOAD + TRAP))
+ public long test42() {
+ MyValue1[] va = new MyValue1[1];
+ va[0] = MyValue1.createInline(rI, rL);
+ return va[0].hash();
+ }
+
+ @DontCompile
+ public void test42_verifier(boolean warmup) {
+ long result = test42();
+ Asserts.assertEQ(result, hash());
+ }
+
+ // Test receiving a value type array from the interpreter,
+ // updating its elements in a loop and computing a hash.
+ @Test(failOn = (ALLOCA))
+ public long test43(MyValue1[] va) {
+ long result = 0;
+ for (int i = 0; i < 10; ++i) {
+ result += va[i].hash();
+ va[i] = MyValue1.createInline(rI + 1, rL + 1);
+ }
+ return result;
+ }
+
+ @DontCompile
+ public void test43_verifier(boolean warmup) {
+ MyValue1[] va = new MyValue1[10];
+ long expected = 0;
+ for (int i = 0; i < 10; ++i) {
+ va[i] = MyValue1.createDontInline(rI + i, rL + i);
+ expected += va[i].hash();
+ }
+ long result = test43(va);
+ Asserts.assertEQ(expected, result);
+ for (int i = 0; i < 10; ++i) {
+ if (va[i].hash() != hash(rI + 1, rL + 1)) {
+ Asserts.assertEQ(va[i].hash(), hash(rI + 1, rL + 1));
+ }
+ }
+ }
+
+ // Test returning a value type array received from the interpreter
+ @Test(failOn = ALLOC + ALLOCA + LOAD + LOADP + STORE + LOOP + TRAP)
+ public MyValue1[] test44(MyValue1[] va) {
+ return va;
+ }
+
+ @DontCompile
+ public void test44_verifier(boolean warmup) {
+ MyValue1[] va = new MyValue1[10];
+ for (int i = 0; i < 10; ++i) {
+ va[i] = MyValue1.createDontInline(rI + i, rL + i);
+ }
+ va = test44(va);
+ for (int i = 0; i < 10; ++i) {
+ Asserts.assertEQ(va[i].hash(), hash(rI + i, rL + i));
+ }
+ }
+
+ // TODO add match rules
+ @Test()
+ public MyValue1[] test45(boolean b) {
+ MyValue1[] va;
+ if (b) {
+ va = new MyValue1[5];
+ for (int i = 0; i < 5; ++i) {
+ va[i] = MyValue1.createInline(rI, rL);
+ }
+ } else {
+ va = new MyValue1[10];
+ for (int i = 0; i < 10; ++i) {
+ va[i] = MyValue1.createInline(rI + i, rL + i);
+ }
+ }
+ long sum = va[0].hashInterpreted();
+ if (b) {
+ va[0] = MyValue1.createDontInline(rI, sum);
+ } else {
+ va[0] = MyValue1.createDontInline(rI + 1, sum + 1);
+ }
+ return va;
+ }
+
+ @DontCompile
+ public void test45_verifier(boolean warmup) {
+ MyValue1[] va = test45(true);
+ Asserts.assertEQ(va.length, 5);
+ Asserts.assertEQ(va[0].hash(), hash(rI, hash()));
+ for (int i = 1; i < 5; ++i) {
+ Asserts.assertEQ(va[i].hash(), hash());
+ }
+ va = test45(false);
+ Asserts.assertEQ(va.length, 10);
+ Asserts.assertEQ(va[0].hash(), hash(rI + 1, hash(rI, rL) + 1));
+ for (int i = 1; i < 10; ++i) {
+ Asserts.assertEQ(va[i].hash(), hash(rI + i, rL + i));
+ }
+ }
+
+ // Test creation of value type array with single element
+ @Test(failOn = LOOP + TRAP)
+ public MyValue1 test46() {
+ MyValue1[] va = new MyValue1[1];
+ return va[0];
+ }
+
+ @DontCompile
+ public void test46_verifier(boolean warmup) {
+ MyValue1[] va = new MyValue1[1];
+ MyValue1 v = test46();
+ Asserts.assertEQ(v.hash(), va[0].hash());
+ }
+
+ // Test default initialization of value type arrays
+ @Test(failOn = LOAD)
+ public MyValue1[] test47(int len) {
+ return new MyValue1[len];
+ }
+
+ @DontCompile
+ 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());
+ }
+ }
+
+ // Test creation of value type array with zero length
+ @Test(failOn = ALLOC + LOAD + STORE + LOOP + TRAP)
+ public MyValue1[] test48() {
+ return new MyValue1[0];
+ }
+
+ @DontCompile
+ public void test48_verifier(boolean warmup) {
+ MyValue1[] va = test48();
+ Asserts.assertEQ(va.length, 0);
}
// ========== Test infrastructure ==========
private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
private static final int ValueTypePassFieldsAsArgsOn = 0x1;
private static final int ValueTypePassFieldsAsArgsOff = 0x2;
- static final int AllFlags = ValueTypePassFieldsAsArgsOn | ValueTypePassFieldsAsArgsOff;
+ private static final int ValueTypeArrayFlattenOn = 0x4;
+ private static final int ValueTypeArrayFlattenOff = 0x8;
+ static final int AllFlags = ValueTypePassFieldsAsArgsOn | ValueTypePassFieldsAsArgsOff | ValueTypeArrayFlattenOn | ValueTypeArrayFlattenOff;
private static final boolean ValueTypePassFieldsAsArgs = (Boolean)WHITE_BOX.getVMFlag("ValueTypePassFieldsAsArgs");
+ private static final boolean ValueTypeArrayFlatten = (Boolean)WHITE_BOX.getVMFlag("ValueArrayFlatten");
private static final int COMP_LEVEL_ANY = -1;
private static final int COMP_LEVEL_FULL_OPTIMIZATION = 4;
private static final Hashtable<String, Method> tests = new Hashtable<String, Method>();
private static final int WARMUP = 250;
private static boolean USE_COMPILER = WHITE_BOX.getBooleanVMFlag("UseCompiler");
@@ -933,12 +1123,15 @@
// 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 LOAD = START + "Load" + MID + "valuetype\\*" + END;
- private static final String STORE = START + "Store" + MID + "valuetype\\*" + END;
+ private static final String ALLOCA = START + "CallStaticJava" + MID + "_new_array_Java" + 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;
// TODO: match field values of scalar replaced object
private static final String SCOBJ = "(.*# ScObj.*" + END;
@@ -978,17 +1171,23 @@
}
public static void main(String[] args) throws Throwable {
if (args.length == 0) {
String field_as_args;
- if ((Boolean)WHITE_BOX.getVMFlag("ValueTypePassFieldsAsArgs")) {
+ String array_flatten;
+ if (ValueTypePassFieldsAsArgs) {
field_as_args = "-XX:+ValueTypePassFieldsAsArgs";
} else {
field_as_args = "-XX:-ValueTypePassFieldsAsArgs";
}
- execute_vm("-XX:+UnlockExperimentalVMOptions", field_as_args);
- execute_vm("-XX:+AlwaysIncrementalInline", "-XX:+UnlockExperimentalVMOptions", field_as_args);
+ if (ValueTypeArrayFlatten) {
+ array_flatten = "-XX:+ValueArrayFlatten";
+ } else {
+ array_flatten = "-XX:-ValueArrayFlatten";
+ }
+ execute_vm("-XX:+UnlockExperimentalVMOptions", field_as_args, array_flatten);
+ execute_vm("-XX:+AlwaysIncrementalInline", "-XX:+UnlockExperimentalVMOptions", field_as_args, array_flatten);
} else {
if (USE_COMPILER && PRINT_IDEAL && !XCOMP) {
System.out.println("PrintIdeal enabled");
}
// Execute tests
@@ -1025,24 +1224,25 @@
assert anno == null;
anno = a;
} else if ((a.valid() & ValueTypePassFieldsAsArgsOff) != 0 && !ValueTypePassFieldsAsArgs) {
assert anno == null;
anno = a;
+ } else if ((a.valid() & ValueTypeArrayFlattenOn) != 0 && ValueTypeArrayFlatten) {
+ assert anno == null;
+ anno = a;
+ } else if ((a.valid() & ValueTypeArrayFlattenOff) != 0 && !ValueTypeArrayFlatten) {
+ assert anno == null;
+ anno = a;
}
}
assert anno != null;
String regexFail = anno.failOn();
if (!regexFail.isEmpty()) {
Pattern pattern = Pattern.compile(regexFail.substring(0, regexFail.length()-1));
Matcher matcher = pattern.matcher(graph);
- boolean fail = false;
- while (matcher.find()) {
- System.out.println("Graph for '" + testName + "' contains forbidden node:");
- System.out.println(matcher.group());
- fail = true;
- }
- Asserts.assertFalse(fail, "Graph for '" + testName + "' contains forbidden nodes");
+ boolean found = matcher.find();
+ Asserts.assertFalse(found, "Graph for '" + testName + "' contains forbidden node:\n" + (found ? matcher.group() : ""));
}
String[] regexMatch = anno.match();
int[] matchCount = anno.matchCount();
for (int i = 0; i < regexMatch.length; ++i) {
Pattern pattern = Pattern.compile(regexMatch[i].substring(0, regexMatch[i].length()-1));
@@ -1051,15 +1251,11 @@
String nodes = "";
while (matcher.find()) {
count++;
nodes += matcher.group() + "\n";
}
- if (matchCount[i] != count) {
- System.out.println("Graph for '" + testName + "' contains different number of match nodes:");
- System.out.println(nodes);
- }
- Asserts.assertEQ(matchCount[i], count, "Graph for '" + testName + "' contains different number of match nodes");
+ Asserts.assertEQ(matchCount[i], count, "Graph for '" + testName + "' contains different number of match nodes:\n" + nodes);
}
tests.remove(testName);
System.out.println(testName + " passed");
}
// Check if all tests were compiled
< prev index next >