< prev index next >
test/compiler/valhalla/valuetypes/ValueTypeTestBench.java
Print this page
*** 50,468 ****
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
! // Test value type
! __ByValue final class MyValue {
final int x;
final long y;
! final double z;
! private MyValue(int x, long y, double z) {
this.x = x;
this.y = y;
! this.z = z;
}
@DontInline
! public static MyValue createDontInline(int x, long y, double z) {
! return __Make MyValue(x, y, z);
}
@ForceInline
! public static MyValue createInline(int x, long y, double z) {
! return __Make MyValue(x, y, z);
}
! @DontInline
! public String toStringDontInline() {
! return "MyValue: x=" + x + " y=" + y + " z=" + z;
}
@ForceInline
! public String toStringInline() {
! return "MyValue: x=" + x + " y=" + y + " z=" + z;
}
}
public class ValueTypeTestBench {
// Print ideal graph after execution of each test
private static final boolean PRINT_GRAPH = true;
// ========== Test definitions ==========
// Receive value type through call to interpreter
! @Test(failOn = ALLOC + STORE)
! public double test1() {
! MyValue v = MyValue.createDontInline(rI, rL, rD);
! return v.x + v.y + v.z;
}
@DontCompile
public void test1_verifier(boolean warmup) {
! double result = test1();
! Asserts.assertEQ(result, rI + rL + rD);
}
// Receive value type from interpreter via parameter
! @Test(failOn = ALLOC + STORE)
! public double test2(MyValue v) {
! return v.x + v.y + v.z;
}
@DontCompile
public void test2_verifier(boolean warmup) {
! MyValue v = MyValue.createDontInline(rI, rL, rD);
! double result = test2(v);
! Asserts.assertEQ(result, rI + rL + rD);
}
// Return incoming value type without accessing fields
! @Test(failOn = ALLOC + LOAD + STORE)
! public MyValue test3(MyValue v) {
return v;
}
@DontCompile
public void test3_verifier(boolean warmup) {
! MyValue v1 = MyValue.createDontInline(rI, rL, rD);
! MyValue v2 = test3(v1);
Asserts.assertEQ(v1.x, v2.x);
Asserts.assertEQ(v1.y, v2.y);
- Asserts.assertEQ(v1.z, v2.z);
}
// Create a value type in compiled code and only use fields.
// Allocation should go away because value type does not escape.
! @Test(failOn = ALLOC + LOAD + STORE)
! public double test4() {
! MyValue v = MyValue.createInline(rI, rL, rD);
! return v.x + v.y + v.z;
}
@DontCompile
public void test4_verifier(boolean warmup) {
! double result = test4();
! Asserts.assertEQ(result, rI + rL + rD);
}
// Create a value type in compiled code and pass it to
// an inlined compiled method via a call.
! @Test(failOn = ALLOC + LOAD + STORE)
! public double test5() {
! MyValue v = MyValue.createInline(rI, rL, rD);
return test5Inline(v);
}
@ForceInline
! public double test5Inline(MyValue v) {
! return v.x + v.y + v.z;
}
@DontCompile
public void test5_verifier(boolean warmup) {
! double result = test5();
! Asserts.assertEQ(result, rI + rL + rD);
}
// Create a value type in compiled code and pass it to
// the interpreter via a call.
! @Test(match = {ALLOC}, matchCount = {1}, failOn = LOAD)
! public double test6() {
! MyValue v = MyValue.createInline(rI, rL, rD);
// Pass to interpreter
! return sumValue(v);
}
@DontCompile
public void test6_verifier(boolean warmup) {
! double result = test6();
! Asserts.assertEQ(result, rI + rL + rD);
}
// Create a value type in compiled code and pass it to
// the interpreter by returning.
! @Test(match = {ALLOC}, matchCount = {1}, failOn = LOAD)
! public MyValue test7(int x, long y, double z) {
! return MyValue.createInline(x, y, z);
}
@DontCompile
public void test7_verifier(boolean warmup) {
! MyValue v = test7(rI, rL, rD);
! double result = v.x + v.y + v.z;
! Asserts.assertEQ(result, rI + rL + rD);
}
// Merge value types created from two branches
! @Test(failOn = ALLOC + STORE)
! public double test8(boolean b) {
! MyValue v;
if (b) {
! v = MyValue.createInline(rI, rL, rD);
} else {
! v = MyValue.createDontInline(rI + 1, rL + 1, rD + 1);
}
! return v.x + v.y + v.z;
}
@DontCompile
public void test8_verifier(boolean warmup) {
! Asserts.assertEQ(test8(true), rI + rL + rD);
! Asserts.assertEQ(test8(false), rI + 1 + rL + 1 + ((double)rD + 1));
}
// Merge value types created from two branches
! @Test(match = {ALLOC, STORE}, matchCount = {1, 3}, failOn = LOAD)
! public MyValue test9(boolean b) {
! MyValue v;
if (b) {
// Value type is not allocated
! v = MyValue.createInline(rI, rL, rD);
} else {
// Value type is allocated by the callee
! v = MyValue.createDontInline(rI + 1, rL + 1, rD + 1);
}
// Need to allocate value type if 'b' is true
! double sum = sumValue(v);
if (b) {
! v = MyValue.createDontInline(rI, rL, sum);
} else {
! v = MyValue.createDontInline(rI, rL, sum + 1);
}
// Don't need to allocate value type because both branches allocate
return v;
}
@DontCompile
public void test9_verifier(boolean warmup) {
! MyValue v = test9(true);
Asserts.assertEQ(v.x, rI);
! Asserts.assertEQ(v.y, rL);
! Asserts.assertEQ(v.z, rI + rL + rD);
!
v = test9(false);
Asserts.assertEQ(v.x, rI);
! Asserts.assertEQ(v.y, rL);
! Asserts.assertEQ(v.z, rI + rL + ((double)rD + 1));
}
// Merge value types created in a loop (not inlined)
! @Test(failOn = ALLOC + STORE)
! public double test10(int x, long y, double z) {
! MyValue v = MyValue.createDontInline(x, y, z);
for (int i = 0; i < 10; ++i) {
! v = MyValue.createDontInline(v.x + 1, v.y + 1, v.z + 1);
}
! return v.x + v.y + v.z;
}
@DontCompile
public void test10_verifier(boolean warmup) {
! double result = test10(rI, rL, rD);
! Asserts.assertEQ(result, rI + rL + 20 + ((double)rD + 10));
}
// Merge value types created in a loop (inlined)
! @Test(failOn = ALLOC + LOAD + STORE + LOOP)
! public double test11(int x, long y, double z) {
! MyValue v = MyValue.createInline(x, y, z);
for (int i = 0; i < 10; ++i) {
! v = MyValue.createInline(v.x + 1, v.y + 1, v.z + 1);
}
! return v.x + v.y + v.z;
}
@DontCompile
public void test11_verifier(boolean warmup) {
! double result = test11(rI, rL, rD);
! Asserts.assertEQ(result, rI + rL + 20 + ((double)rD + 10));
}
// Test loop with uncommon trap referencing a value type
@Test(match = {TRAP, SCOBJ}, matchCount = {1, 1}, failOn = ALLOC + LOAD + STORE)
! public double test12(boolean b) {
! MyValue v = MyValue.createInline(rI, rL, rD);
! double 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 = sumValue(v);
}
}
return result;
}
@DontCompile
public void test12_verifier(boolean warmup) {
! double result = test12(warmup);
! Asserts.assertEQ(result, warmup ? 42 + (1000*(double)rI) : (rI + rL + rD));
}
// Test loop with uncommon trap referencing a value type
@Test(match = {TRAP, LOAD}, matchCount = {1, 1}, failOn = ALLOC + STORE + SCOBJ)
! public double test13(boolean b) {
! MyValue v = MyValue.createDontInline(rI, rL, rD);
! double 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 = sumValue(v);
}
}
return result;
}
@DontCompile
public void test13_verifier(boolean warmup) {
! double result = test13(warmup);
! Asserts.assertEQ(result, warmup ? 42 + (1000*(double)rI) : (rI + rL + rD));
}
// Create a value type in a non-inlined method and then call a
// non-inlined method on that value type.
! @Test(failOn = (ALLOC + STORE))
! public String test14() {
! MyValue v = MyValue.createDontInline(32, 64L, 128.0);
! String s = v.toStringDontInline();
! return s;
}
@DontCompile
public void test14_verifier(boolean b) {
! String s = test14();
! System.out.println("Result is: " + s);
}
// Create a value type in an inlined method and then call a
// non-inlined method on that value type.
! @Test(match = {ALLOC}, matchCount = {1})
! public String test15() {
! MyValue v = MyValue.createInline(65, 129L, 257.0);
! String s = v.toStringDontInline();
! return s;
}
@DontCompile
public void test15_verifier(boolean b) {
! String s = test15();
! System.out.println("Result is: " + s);
}
// Create a value type in a non-inlined method and then call an
! // inlined method on that value type. Allocations are due to building
! // String objects and not due to allocating value types.
! @Test(match = {ALLOC}, matchCount = {2})
! public String test16() {
! MyValue v = MyValue.createDontInline(130, 258L, 514.0);
! String s = v.toStringInline();
! return s;
}
@DontCompile
public void test16_verifier(boolean b) {
! String s = test16();
! System.out.println("Result is: " + s);
}
// Create a value type in an inlined method and then call an
! // inlined method on that value type. Allocations are due to
! // building String objects and not due to allocating value types.
! @Test(match = {ALLOC}, matchCount = {2})
! public String test17() {
! MyValue v = MyValue.createInline(259, 515L, 1027.0);
! String s = v.toStringInline();
! return s;
}
@DontCompile
public void test17_verifier(boolean b) {
! String s = test17();
! System.out.println("Result is: " + s);
}
// Create a value type in compiled code and pass it to the
// interpreter via a call. The value is live at the first call so
// debug info should include a reference to all its fields.
! @Test(match = {ALLOC}, matchCount = {1}, failOn = LOAD)
! public double test18() {
! MyValue v = MyValue.createInline(rI, rL, rD);
! sumValue(v);
! return sumValue(v);
}
@DontCompile
public void test18_verifier(boolean warmup) {
! double result = test18();
! Asserts.assertEQ(result, rI + rL + rD);
}
// Create a value type in compiled code and pass it to the
// interpreter via a call. The value type is passed twice but
// should only be allocated once.
! @Test(match = {ALLOC}, matchCount = {1}, failOn = LOAD)
! public double test19() {
! MyValue v = MyValue.createInline(rI, rL, rD);
return sumValue(v, v);
}
@DontCompile
public void test19_verifier(boolean warmup) {
! double result = test19();
! Asserts.assertEQ(result, rI + rL + rD);
}
// Create a value type 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(match = {ALLOC}, matchCount = {1}, failOn = LOAD)
! public double test20(boolean flag) {
! MyValue v = MyValue.createInline(rI, rL, rD);
if (flag) {
// uncommon trap
WHITE_BOX.deoptimizeMethod(tests.get("ValueTypeTestBench::test16"));
}
! return sumValue(v);
}
@DontCompile
public void test20_verifier(boolean warmup) {
! double result = test20(false);
! Asserts.assertEQ(result, rI + rL + rD);
if (!warmup) {
result = test20(true);
! Asserts.assertEQ(result, rI + rL + rD);
}
}
! // ========== Helper methods ==========
!
! @DontCompile
! public double sumValue(MyValue v) {
! return v.x + v.y + v.z;
}
@DontCompile
! public double sumValue(MyValue v, MyValue dummy) {
! return v.x + v.y + v.z;
}
// ========== Test infrastructure ==========
private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
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 = 10;
// 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 = ")|";
--- 50,517 ----
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
! // Test value types
! __ByValue final class MyValue1 {
final int x;
final long y;
! final MyValue2 v1;
! final MyValue2 v2;
! final int c;
! private MyValue1(int x, long y, MyValue2 v1, MyValue2 v2, int c) {
this.x = x;
this.y = y;
! this.v1 = v1;
! this.v2 = v2;
! this.c = c;
}
@DontInline
! public static MyValue1 createDontInline(int x, long y) {
! return __Make MyValue1(x, y, MyValue2.createInline(x, x < y), MyValue2.createInline(x, x > y), ValueTypeTestBench.rI);
}
@ForceInline
! public static MyValue1 createInline(int x, long y) {
! return __Make MyValue1(x, y, MyValue2.createInline(x, x < y), MyValue2.createInline(x, x > y), ValueTypeTestBench.rI);
}
! @ForceInline
! public long hash() {
! return x + y + c + v1.hash() + v2.hash();
! }
!
! @DontCompile
! public long hashInterpreted() {
! return x + y + c + v1.hash() + v2.hash();
! }
! }
!
! __ByValue final class MyValue2 {
! final int x;
! final boolean b;
! final long c;
!
! private MyValue2(int x, boolean b, long c) {
! this.x = x;
! this.b = b;
! this.c = c;
}
@ForceInline
! public static MyValue2 createInline(int x, boolean b) {
! return __Make MyValue2(x, b, ValueTypeTestBench.rL);
! }
!
! @ForceInline
! public long hash() {
! return x + (b ? 0 : 1) + c;
}
}
public class ValueTypeTestBench {
// Print ideal graph after execution of each test
private static final boolean PRINT_GRAPH = true;
+ // ========== Helper methods ==========
+
+ public long hash() {
+ return hash(rI, rL);
+ }
+
+ public long hash(int x, long y) {
+ return MyValue1.createInline(x, y).hash();
+ }
+
// ========== Test definitions ==========
// Receive value type through call to interpreter
! @Test(failOn = ALLOC + STORE + TRAP)
! public long test1() {
! MyValue1 v = MyValue1.createDontInline(rI, rL);
! return v.hash();
}
@DontCompile
public void test1_verifier(boolean warmup) {
! long result = test1();
! Asserts.assertEQ(result, hash());
}
// Receive value type from interpreter via parameter
! @Test(failOn = ALLOC + STORE + TRAP)
! public long test2(MyValue1 v) {
! return v.hash();
}
@DontCompile
public void test2_verifier(boolean warmup) {
! MyValue1 v = MyValue1.createDontInline(rI, rL);
! long result = test2(v);
! Asserts.assertEQ(result, hash());
}
// Return incoming value type without accessing fields
! @Test(failOn = ALLOC + LOAD + STORE + TRAP)
! public MyValue1 test3(MyValue1 v) {
return v;
}
@DontCompile
public void test3_verifier(boolean warmup) {
! MyValue1 v1 = MyValue1.createDontInline(rI, rL);
! MyValue1 v2 = test3(v1);
Asserts.assertEQ(v1.x, v2.x);
Asserts.assertEQ(v1.y, v2.y);
}
// Create a value type in compiled code and only use fields.
// Allocation should go away because value type does not escape.
! @Test(failOn = ALLOC + LOAD + STORE + TRAP)
! public long test4() {
! MyValue1 v = MyValue1.createInline(rI, rL);
! return v.hash();
}
@DontCompile
public void test4_verifier(boolean warmup) {
! long result = test4();
! Asserts.assertEQ(result, hash());
}
// Create a value type in compiled code and pass it to
// an inlined compiled method via a call.
! @Test(failOn = ALLOC + LOAD + STORE + TRAP)
! public long test5() {
! MyValue1 v = MyValue1.createInline(rI, rL);
return test5Inline(v);
}
@ForceInline
! public long test5Inline(MyValue1 v) {
! return v.hash();
}
@DontCompile
public void test5_verifier(boolean warmup) {
! long result = test5();
! Asserts.assertEQ(result, hash());
}
// Create a value type in compiled code and pass it to
// the interpreter via a call.
! @Test(match = {ALLOC}, matchCount = {1}, failOn = LOAD + TRAP)
! public long test6() {
! MyValue1 v = MyValue1.createInline(rI, rL);
// Pass to interpreter
! return v.hashInterpreted();
}
@DontCompile
public void test6_verifier(boolean warmup) {
! long result = test6();
! Asserts.assertEQ(result, hash());
}
// Create a value type in compiled code and pass it to
// the interpreter by returning.
! @Test(match = {ALLOC}, matchCount = {1}, failOn = LOAD + TRAP)
! public MyValue1 test7(int x, long y) {
! return MyValue1.createInline(x, y);
}
@DontCompile
public void test7_verifier(boolean warmup) {
! MyValue1 v = test7(rI, rL);
! Asserts.assertEQ(v.hash(), hash());
}
// Merge value types created from two branches
! @Test(failOn = ALLOC + STORE + TRAP)
! public long test8(boolean b) {
! MyValue1 v;
if (b) {
! v = MyValue1.createInline(rI, rL);
} else {
! v = MyValue1.createDontInline(rI + 1, rL + 1);
}
! return v.hash();
}
@DontCompile
public void test8_verifier(boolean warmup) {
! Asserts.assertEQ(test8(true), hash());
! Asserts.assertEQ(test8(false), hash(rI + 1, rL + 1));
}
// Merge value types created from two branches
! @Test(match = {ALLOC, STORE}, matchCount = {1, 9}, failOn = LOAD + TRAP)
! public MyValue1 test9(boolean b) {
! MyValue1 v;
if (b) {
// Value type is not allocated
! v = MyValue1.createInline(rI, rL);
} else {
// Value type is allocated by the callee
! v = MyValue1.createDontInline(rI + 1, rL + 1);
}
// Need to allocate value type if 'b' is true
! long sum = v.hashInterpreted();
if (b) {
! v = MyValue1.createDontInline(rI, sum);
} else {
! v = MyValue1.createDontInline(rI, sum + 1);
}
// Don't need to allocate value type because both branches allocate
return v;
}
@DontCompile
public void test9_verifier(boolean warmup) {
! MyValue1 v = test9(true);
Asserts.assertEQ(v.x, rI);
! Asserts.assertEQ(v.y, hash());
v = test9(false);
Asserts.assertEQ(v.x, rI);
! Asserts.assertEQ(v.y, hash(rI + 1, rL + 1) + 1);
}
// Merge value types created in a loop (not inlined)
! @Test(failOn = ALLOC + STORE + TRAP)
! public long test10(int x, long y) {
! MyValue1 v = MyValue1.createDontInline(x, y);
for (int i = 0; i < 10; ++i) {
! v = MyValue1.createDontInline(v.x + 1, v.y + 1);
}
! return v.hash();
}
@DontCompile
public void test10_verifier(boolean warmup) {
! 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)
! 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);
}
! return v.hash();
}
@DontCompile
public void test11_verifier(boolean warmup) {
! 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(failOn = (ALLOC + LOAD + STORE + TRAP))
! public long test14() {
! MyValue1 v = MyValue1.createDontInline(rI, rL);
! return v.hashInterpreted();
}
@DontCompile
public void test14_verifier(boolean b) {
! long result = test14();
! Asserts.assertEQ(result, hash());
}
// Create a value type in an inlined method and then call a
// non-inlined method on that value type.
! @Test(failOn = (LOAD + TRAP), match = {ALLOC}, matchCount = {1})
! public long test15() {
! MyValue1 v = MyValue1.createInline(rI, rL);
! return v.hashInterpreted();
}
@DontCompile
public void test15_verifier(boolean b) {
! long result = test15();
! Asserts.assertEQ(result, hash());
}
// Create a value type in a non-inlined method and then call an
! // inlined method on that value type.
! @Test(failOn = (ALLOC + STORE + TRAP))
! public long test16() {
! MyValue1 v = MyValue1.createDontInline(rI, rL);
! return v.hash();
}
@DontCompile
public void test16_verifier(boolean b) {
! long result = test16();
! Asserts.assertEQ(result, hash());
}
// Create a value type in an inlined method and then call an
! // inlined method on that value type.
! @Test(failOn = (ALLOC + LOAD + STORE + TRAP))
! public long test17() {
! MyValue1 v = MyValue1.createInline(rI, rL);
! return v.hash();
}
@DontCompile
public void test17_verifier(boolean b) {
! long result = test17();
! Asserts.assertEQ(result, hash());
}
// Create a value type in compiled code and pass it to the
// interpreter via a call. The value is live at the first call so
// debug info should include a reference to all its fields.
! @Test(match = {ALLOC}, matchCount = {1}, failOn = LOAD + TRAP)
! public long test18() {
! MyValue1 v = MyValue1.createInline(rI, rL);
! v.hashInterpreted();
! return v.hashInterpreted();
}
@DontCompile
public void test18_verifier(boolean warmup) {
! long result = test18();
! Asserts.assertEQ(result, hash());
}
// Create a value type in compiled code and pass it to the
// interpreter via a call. The value type is passed twice but
// should only be allocated once.
! @Test(match = {ALLOC}, matchCount = {1}, failOn = LOAD + TRAP)
! public long test19() {
! MyValue1 v = MyValue1.createInline(rI, rL);
return sumValue(v, v);
}
@DontCompile
+ public long sumValue(MyValue1 v, MyValue1 dummy) {
+ return v.hash();
+ }
+
+ @DontCompile
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
// 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(match = {ALLOC}, matchCount = {1}, failOn = LOAD)
! public long test20(boolean flag) {
! MyValue1 v = MyValue1.createInline(rI, rL);
if (flag) {
// uncommon trap
WHITE_BOX.deoptimizeMethod(tests.get("ValueTypeTestBench::test16"));
}
! return v.hashInterpreted();
}
@DontCompile
public void test20_verifier(boolean warmup) {
! long result = test20(false);
! Asserts.assertEQ(result, hash());
if (!warmup) {
result = test20(true);
! Asserts.assertEQ(result, hash());
}
}
! // Value type fields in regular object
! MyValue1 val1;
! MyValue2 val2;
!
! // Test value type fields in objects
! @Test(failOn = (ALLOC + TRAP))
! public long test21(int x, long y) {
! // Compute hash of value type fields
! long result = val1.hash() + val2.hash();
! // Update fields
! val1 = MyValue1.createInline(x, y);
! val2 = MyValue2.createInline(x, true);
! return result;
}
@DontCompile
! public void test21_verifier(boolean warmup) {
! // Check if hash computed by test18 is correct
! val1 = MyValue1.createInline(rI, rL);
! val2 = val1.v2;
! long hash = val1.hash() + val2.hash();
! long result = test21(rI + 1, rL + 1);
! Asserts.assertEQ(result, hash);
! // Check if value type fields were updated
! Asserts.assertEQ(val1.hash(), hash(rI + 1, rL + 1));
! Asserts.assertEQ(val2.hash(), MyValue2.createInline(rI + 1, true).hash());
}
+
// ========== Test infrastructure ==========
private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
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 = 10;
+ private static boolean USE_COMPILER = WHITE_BOX.getBooleanVMFlag("UseCompiler");
+ private static boolean PRINT_IDEAL = WHITE_BOX.getBooleanVMFlag("PrintIdeal");
// 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 = ")|";
*** 472,486 ****
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;
-
// Random test values
! private static final int rI = Utils.getRandomInstance().nextInt();
! private static final long rL = Utils.getRandomInstance().nextLong();
! private static final double rD = Utils.getRandomInstance().nextDouble();
static {
// Gather all test methods and put them in Hashtable
for (Method m : ValueTypeTestBench.class.getDeclaredMethods()) {
if (m.isAnnotationPresent(Test.class)) {
--- 521,533 ----
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;
// Random test values
! public static final int rI = Utils.getRandomInstance().nextInt() % 1000;
! public static final long rL = Utils.getRandomInstance().nextLong() % 1000;
static {
// Gather all test methods and put them in Hashtable
for (Method m : ValueTypeTestBench.class.getDeclaredMethods()) {
if (m.isAnnotationPresent(Test.class)) {
*** 493,510 ****
if (args.length == 0) {
// Run tests in own process and verify output
OutputAnalyzer oa = ProcessTools.executeTestJvm("-noverify",
"-XX:+UnlockDiagnosticVMOptions", "-Xbootclasspath/a:.", "-XX:+WhiteBoxAPI",
"-XX:-TieredCompilation", "-XX:-BackgroundCompilation", "-XX:-UseOnStackReplacement",
! "-XX:CompileCommand=quiet", "-XX:+PrintCompilation", "-XX:+PrintIdeal", "-XX:+PrintOptoAssembly",
! "-XX:CompileCommand=compileonly,compiler.valhalla.valuetypes.ValueTypeTestBench::*",
! "-XX:CompileCommand=compileonly,compiler.valhalla.valuetypes.MyValue::*",
ValueTypeTestBench.class.getName(), "run");
String output = oa.getOutput();
oa.shouldHaveExitValue(0);
parseOutput(output);
} else {
// Execute tests
ValueTypeTestBench bench = new ValueTypeTestBench();
bench.run();
}
}
--- 540,566 ----
if (args.length == 0) {
// Run tests in own process and verify output
OutputAnalyzer oa = ProcessTools.executeTestJvm("-noverify",
"-XX:+UnlockDiagnosticVMOptions", "-Xbootclasspath/a:.", "-XX:+WhiteBoxAPI",
"-XX:-TieredCompilation", "-XX:-BackgroundCompilation", "-XX:-UseOnStackReplacement",
! "-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::*",
ValueTypeTestBench.class.getName(), "run");
+ // If ideal graph printing is enabled/supported, verify output
String output = oa.getOutput();
oa.shouldHaveExitValue(0);
+ if (output.contains("PrintIdeal enabled")) {
parseOutput(output);
} else {
+ System.out.println("WARNING: test methods not compiled or PrintIdeal disabled! Running with -Xint or release build?");
+ }
+ } else {
+ if (USE_COMPILER && PRINT_IDEAL) {
+ System.out.println("PrintIdeal enabled");
+ }
// Execute tests
ValueTypeTestBench bench = new ValueTypeTestBench();
bench.run();
}
}
*** 586,609 ****
}
}
}
public void run() throws Exception {
! System.out.format("rI = %d, rL = %d, rD = %f\n", rI, rL, rD);
setup(this.getClass().getDeclaredMethods());
! setup(MyValue.class.getDeclaredMethods());
// Execute tests
for (Method test : tests.values()) {
Method verifier = getClass().getDeclaredMethod(test.getName() + "_verifier", boolean.class);
// Warmup using verifier method
for (int i = 0; i < WARMUP; ++i) {
verifier.invoke(this, true);
}
// Trigger compilation
WHITE_BOX.enqueueMethodForCompilation(test, COMP_LEVEL_FULL_OPTIMIZATION);
! Asserts.assertTrue(WHITE_BOX.isMethodCompiled(test, false));
// Check result
verifier.invoke(this, false);
}
}
}
--- 642,666 ----
}
}
}
public void run() throws Exception {
! System.out.format("rI = %d, rL = %d\n", rI, rL);
setup(this.getClass().getDeclaredMethods());
! setup(MyValue1.class.getDeclaredMethods());
! setup(MyValue2.class.getDeclaredMethods());
// Execute tests
for (Method test : tests.values()) {
Method verifier = getClass().getDeclaredMethod(test.getName() + "_verifier", boolean.class);
// Warmup using verifier method
for (int i = 0; i < WARMUP; ++i) {
verifier.invoke(this, true);
}
// Trigger compilation
WHITE_BOX.enqueueMethodForCompilation(test, COMP_LEVEL_FULL_OPTIMIZATION);
! Asserts.assertTrue(!USE_COMPILER || WHITE_BOX.isMethodCompiled(test, false), test + " not compiled");
// Check result
verifier.invoke(this, false);
}
}
}
< prev index next >