< prev index next >
test/compiler/valhalla/valuetypes/ValueTypeTestBench.java
Print this page
*** 35,44 ****
--- 35,51 ----
* @run main/othervm -ea -noverify -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
* -XX:+UnlockExperimentalVMOptions -XX:-ValueTypePassFieldsAsArgs -XX:-ValueArrayFlatten
* -XX:-TieredCompilation compiler.valhalla.valuetypes.ValueTypeTestBench
*/
+ // TODO Enable this
+ /*
+ * run main/othervm -ea -noverify -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ * -XX:+UnlockExperimentalVMOptions -XX:+ValueTypePassFieldsAsArgs -XX:+AlwaysIncrementalInline -XX:+ValueArrayFlatten
+ * -XX:-TieredCompilation compiler.valhalla.valuetypes.ValueTypeTestBench
+ */
+
package compiler.valhalla.valuetypes;
import compiler.whitebox.CompilerWhiteBoxTest;
import jdk.internal.misc.Unsafe;
import jdk.test.lib.Asserts;
*** 473,525 ****
long result = test11(rI, rL);
Asserts.assertEQ(result, hash(rI + 10, rL + 10));
}
// Test loop with uncommon trap referencing a value type
! @Test(match = {TRAP, SCOBJ}, matchCount = {1, 1}, failOn = ALLOC + LOAD + STORE)
public long test12(boolean b) {
MyValue1 v = MyValue1.createInline(rI, rL);
! long result = 42;
for (int i = 0; i < 1000; ++i) {
if (b) {
result += v.x;
} else {
// Uncommon trap referencing v. We delegate allocation to the
// interpreter by adding a SafePointScalarObjectNode.
result = v.hashInterpreted();
}
}
return result;
}
@DontCompile
public void test12_verifier(boolean warmup) {
long result = test12(warmup);
! Asserts.assertEQ(result, warmup ? 42 + (1000*rI) : hash());
}
// Test loop with uncommon trap referencing a value type
! @Test(match = {TRAP, LOAD}, matchCount = {1, 1}, failOn = ALLOC + STORE + SCOBJ)
public long test13(boolean b) {
MyValue1 v = MyValue1.createDontInline(rI, rL);
! long result = 42;
for (int i = 0; i < 1000; ++i) {
if (b) {
result += v.x;
} else {
// Uncommon trap referencing v. Should not allocate
// but just pass the existing oop to the uncommon trap.
result = v.hashInterpreted();
}
}
return result;
}
@DontCompile
public void test13_verifier(boolean warmup) {
long result = test13(warmup);
! 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 = {7})
--- 480,546 ----
long result = test11(rI, rL);
Asserts.assertEQ(result, hash(rI + 10, rL + 10));
}
// Test loop with uncommon trap referencing a value type
! @Test(match = {TRAP, SCOBJ}, matchCount = {1, -1 /* at least 1 */}, failOn = LOAD)
public long test12(boolean b) {
MyValue1 v = MyValue1.createInline(rI, rL);
! MyValue1[] va = new MyValue1[Math.abs(rI) % 10];
! for (int i = 0; i < va.length; ++i) {
! va[i] = MyValue1.createInline(rI, rL);
! }
! long result = rL;
for (int i = 0; i < 1000; ++i) {
if (b) {
result += v.x;
} else {
// Uncommon trap referencing v. We delegate allocation to the
// interpreter by adding a SafePointScalarObjectNode.
result = v.hashInterpreted();
+ for (int j = 0; j < va.length; ++j) {
+ result += va[j].hash();
+ }
}
}
return result;
}
@DontCompile
public void test12_verifier(boolean warmup) {
long result = test12(warmup);
! Asserts.assertEQ(result, warmup ? rL + (1000 * rI) : ((Math.abs(rI) % 10) + 1) * hash());
}
// Test loop with uncommon trap referencing a value type
! @Test(match = {TRAP}, matchCount = {1})
public long test13(boolean b) {
MyValue1 v = MyValue1.createDontInline(rI, rL);
! MyValue1[] va = new MyValue1[Math.abs(rI) % 10];
! for (int i = 0; i < va.length; ++i) {
! va[i] = MyValue1.createDontInline(rI, rL);
! }
! long result = rL;
for (int i = 0; i < 1000; ++i) {
if (b) {
result += v.x;
} else {
// Uncommon trap referencing v. Should not allocate
// but just pass the existing oop to the uncommon trap.
result = v.hashInterpreted();
+ for (int j = 0; j < va.length; ++j) {
+ result += va[j].hashInterpreted();
+ }
}
}
return result;
}
@DontCompile
public void test13_verifier(boolean warmup) {
long result = test13(warmup);
! Asserts.assertEQ(result, warmup ? rL + (1000 * rI) : ((Math.abs(rI) % 10) + 1) * 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 = {7})
*** 619,648 ****
// 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(); // + va[0].hashInterpreted();
}
@DontCompile
public void test20_verifier(boolean warmup) {
MyValue1[] va = new MyValue1[42];
long result = test20(false);
! Asserts.assertEQ(result, hash() /* + va[0].hash() */);
if (!warmup) {
result = test20(true);
! Asserts.assertEQ(result, hash() /* + va[0].hash() */);
}
}
// Value type fields in regular object
MyValue1 val1;
--- 640,669 ----
// 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 = {2}, failOn = LOAD)
public long test20(boolean flag) {
MyValue1 v = MyValue1.createInline(rI, rL);
! MyValue1[] va = new MyValue1[3];
if (flag) {
// 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];
long result = test20(false);
! Asserts.assertEQ(result, hash() + va[0].hash() + va[1].hash() + va[2].hash());
if (!warmup) {
result = test20(true);
! Asserts.assertEQ(result, hash() + va[0].hash() + va[1].hash() + va[2].hash());
}
}
// Value type fields in regular object
MyValue1 val1;
*** 893,923 ****
Asserts.assertEQ(result, v1.hashInterpreted() + rL + rI + v2.hashInterpreted());
}
// test that debug info at a call is correct
@DontCompile
! public long test36_interp(MyValue2 v, boolean flag) {
if (flag) {
// uncommon trap
WHITE_BOX.deoptimizeMethod(tests.get("ValueTypeTestBench::test36"));
}
! return v.hash();
}
@Test(failOn = ALLOC + STORE + TRAP)
! public long test36(MyValue2 v, boolean flag, long l) {
! return test36_interp(v, flag) + l;
}
@DontCompile
public void test36_verifier(boolean warmup) {
MyValue2 v = MyValue2.createInline(rI, true);
! long result = test36(v, false, rL);
! Asserts.assertEQ(result, v.hashInterpreted() + rL);
if (!warmup) {
! result = test36(v, true, rL);
! Asserts.assertEQ(result, v.hashInterpreted() + rL);
}
}
// Test vbox and vunbox
@Test
--- 914,947 ----
Asserts.assertEQ(result, v1.hashInterpreted() + rL + rI + v2.hashInterpreted());
}
// test that debug info at a call is correct
@DontCompile
! public long test36_interp(MyValue2 v, MyValue1[] va, boolean flag) {
if (flag) {
// uncommon trap
WHITE_BOX.deoptimizeMethod(tests.get("ValueTypeTestBench::test36"));
}
! return v.hash() + va[0].hash() + va[1].hash();
}
@Test(failOn = ALLOC + STORE + TRAP)
! public long test36(MyValue2 v, MyValue1[] va, boolean flag, long l) {
! return test36_interp(v, va, flag) + l;
}
@DontCompile
public void test36_verifier(boolean warmup) {
MyValue2 v = MyValue2.createInline(rI, true);
! MyValue1[] va = new MyValue1[2];
! va[0] = MyValue1.createDontInline(rI, rL);
! va[1] = MyValue1.createDontInline(rI, rL);
! long result = test36(v, va, false, rL);
! Asserts.assertEQ(result, v.hashInterpreted() + va[0].hash() + va[1].hash() + rL);
if (!warmup) {
! result = test36(v, va, true, rL);
! Asserts.assertEQ(result, v.hashInterpreted() + va[0].hash() + va[1].hash() + rL);
}
}
// Test vbox and vunbox
@Test
*** 1066,1076 ****
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();
}
--- 1090,1101 ----
Asserts.assertEQ(va[i].hash(), hash());
}
}
// Test creation of a value type array and element access
! @Test(valid = ValueTypeArrayFlattenOff, failOn = (LOOP + LOAD + TRAP))
! @Test(valid = ValueTypeArrayFlattenOn, failOn = (ALLOC + ALLOCA + LOOP + LOAD + LOADP + STORE + TRAP))
public long test42() {
MyValue1[] va = new MyValue1[1];
va[0] = MyValue1.createInline(rI, rL);
return va[0].hash();
}
*** 1126,1137 ****
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) {
--- 1151,1161 ----
for (int i = 0; i < 10; ++i) {
Asserts.assertEQ(va[i].hash(), hash(rI + i, rL + i));
}
}
! @Test(failOn = (TRAP))
public MyValue1[] test45(boolean b) {
MyValue1[] va;
if (b) {
va = new MyValue1[5];
for (int i = 0; i < 5; ++i) {
*** 1167,1177 ****
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];
}
--- 1191,1202 ----
Asserts.assertEQ(va[i].hash(), hash(rI + i, rL + i));
}
}
// Test creation of value type array with single element
! @Test(valid = ValueTypeArrayFlattenOff, failOn = (LOAD + LOOP + TRAP))
! @Test(valid = ValueTypeArrayFlattenOn, failOn = (ALLOCA + LOAD + LOOP + TRAP))
public MyValue1 test46() {
MyValue1[] va = new MyValue1[1];
return va[0];
}
*** 1208,1219 ****
public void test48_verifier(boolean warmup) {
MyValue1[] va = test48();
Asserts.assertEQ(va.length, 0);
}
- // Test that value type array loaded from field has correct type
static MyValue1[] test49_va;
@Test(failOn = (LOOP))
public long test49() {
return test49_va[0].hash();
}
--- 1233,1245 ----
public void test48_verifier(boolean warmup) {
MyValue1[] va = test48();
Asserts.assertEQ(va.length, 0);
}
static MyValue1[] test49_va;
+
+ // Test that value type array loaded from field has correct type
@Test(failOn = (LOOP))
public long test49() {
return test49_va[0].hash();
}
*** 1224,1234 ****
long result = test49();
Asserts.assertEQ(result, hash());
}
// test vdefault
! @Test(failOn = ALLOC + LOAD + STORE + LOOP + TRAP)
public long test50() {
MyValue2 v = MyValue2.createDefaultInline();
return v.hash();
}
--- 1250,1260 ----
long result = test49();
Asserts.assertEQ(result, hash());
}
// test vdefault
! @Test(failOn = ALLOC + LOAD + LOADP + STORE + LOOP + TRAP)
public long test50() {
MyValue2 v = MyValue2.createDefaultInline();
return v.hash();
}
*** 1251,1261 ****
long result = test51();
Asserts.assertEQ(result, 2 * MyValue1.createDefaultInline().hash());
}
// test vwithfield
! @Test(failOn = ALLOC + LOAD + STORE + LOOP + TRAP)
public long test52() {
MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
return v.hash();
}
--- 1277,1287 ----
long result = test51();
Asserts.assertEQ(result, 2 * MyValue1.createDefaultInline().hash());
}
// test vwithfield
! @Test(failOn = ALLOC + LOAD + LOADP + STORE + LOOP + TRAP)
public long test52() {
MyValue2 v = MyValue2.createWithFieldsInline(rI, true);
return v.hash();
}
*** 1278,1288 ****
long result = test53();
Asserts.assertEQ(result, 2 * hash());
}
// multi-dimensional arrays
! @Test()
public MyValue1[][][] test54(int len1, int len2, int len3) {
MyValue1[][][] arr = new MyValue1[len1][len2][len3];
for (int i = 0; i < len1; i++) {
for (int j = 0; j < len2; j++) {
for (int k = 0; k < len3; k++) {
--- 1304,1314 ----
long result = test53();
Asserts.assertEQ(result, 2 * hash());
}
// multi-dimensional arrays
! @Test
public MyValue1[][][] test54(int len1, int len2, int len3) {
MyValue1[][][] arr = new MyValue1[len1][len2][len3];
for (int i = 0; i < len1; i++) {
for (int j = 0; j < len2; j++) {
for (int k = 0; k < len3; k++) {
*** 1303,1313 ****
}
}
}
}
! @Test()
public void test55(MyValue1[][][] arr, long[] res) {
int l = 0;
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
for (int k = 0; k < arr[i][j].length; k++) {
--- 1329,1339 ----
}
}
}
}
! @Test
public void test55(MyValue1[][][] arr, long[] res) {
int l = 0;
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
for (int k = 0; k < arr[i][j].length; k++) {
*** 1381,1405 ****
tests.put("ValueTypeTestBench::" + m.getName(), m);
}
}
}
! private static void execute_vm(String... extra_args) throws Throwable {
! ArrayList<String> all_args = new ArrayList(List.of(
! "-noverify",
! "-XX:+UnlockDiagnosticVMOptions", "-Xbootclasspath/a:.", "-XX:+WhiteBoxAPI",
! "-XX:-TieredCompilation", "-XX:-BackgroundCompilation",
! "-XX:+IgnoreUnrecognizedVMOptions", "-XX:+PrintCompilation", "-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::*"
! ));
! all_args.addAll(List.of(extra_args));
// Run tests in own process and verify output
all_args.add(ValueTypeTestBench.class.getName());
all_args.add("run");
! OutputAnalyzer oa = ProcessTools.executeTestJvm(all_args.toArray(new String[0]));
// If ideal graph printing is enabled/supported, verify output
String output = oa.getOutput();
oa.shouldHaveExitValue(0);
if (output.contains("PrintIdeal enabled")) {
parseOutput(output);
--- 1407,1424 ----
tests.put("ValueTypeTestBench::" + m.getName(), m);
}
}
}
! private static void execute_vm(String... args) throws Throwable {
! Asserts.assertFalse(tests.isEmpty(), "no tests to execute");
! ArrayList<String> all_args = new ArrayList(List.of(args));
// Run tests in own process and verify output
all_args.add(ValueTypeTestBench.class.getName());
all_args.add("run");
! // Spawn process with default JVM options from the test's run command
! OutputAnalyzer oa = ProcessTools.executeTestJvmAllArgs(all_args.toArray(new String[all_args.size()]));
// If ideal graph printing is enabled/supported, verify output
String output = oa.getOutput();
oa.shouldHaveExitValue(0);
if (output.contains("PrintIdeal enabled")) {
parseOutput(output);
*** 1408,1435 ****
}
}
public static void main(String[] args) throws Throwable {
if (args.length == 0) {
! String field_as_args;
! String array_flatten;
! if (ValueTypePassFieldsAsArgs) {
! field_as_args = "-XX:+ValueTypePassFieldsAsArgs";
! } else {
! field_as_args = "-XX:-ValueTypePassFieldsAsArgs";
! }
! 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
ValueTypeTestBench bench = new ValueTypeTestBench();
bench.run();
}
}
--- 1427,1442 ----
}
}
public static void main(String[] args) throws Throwable {
if (args.length == 0) {
! execute_vm("-XX:+IgnoreUnrecognizedVMOptions", "-XX:-BackgroundCompilation",
! "-XX:+PrintCompilation", "-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::*");
} else {
// Execute tests
ValueTypeTestBench bench = new ValueTypeTestBench();
bench.run();
}
}
*** 1489,1500 ****
--- 1496,1511 ----
String nodes = "";
while (matcher.find()) {
count++;
nodes += matcher.group() + "\n";
}
+ if (matchCount[i] < 0) {
+ Asserts.assertLTE(Math.abs(matchCount[i]), count, "Graph for '" + testName + "' contains different number of match nodes:\n" + nodes);
+ } else {
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
if (tests.size() != 0) {
*** 1522,1531 ****
--- 1533,1545 ----
}
}
}
public void run() throws Exception {
+ if (USE_COMPILER && PRINT_IDEAL && !XCOMP) {
+ System.out.println("PrintIdeal enabled");
+ }
System.out.format("rI = %d, rL = %d\n", rI, rL);
setup(this.getClass().getDeclaredMethods());
setup(MyValue1.class.getDeclaredMethods());
setup(MyValue2.class.getDeclaredMethods());
< prev index next >