< 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 >