--- old/test/compiler/valhalla/valuetypes/ValueTypeTestBench.java 2017-06-16 14:34:20.793928416 +0200 +++ new/test/compiler/valhalla/valuetypes/ValueTypeTestBench.java 2017-06-16 14:34:20.413928434 +0200 @@ -566,6 +566,8 @@ private static final MethodHandle objectUnboxLoadLongMH = generateObjectUnboxLoadLongMH(); private static final MethodHandle objectBoxMH = generateObjectBoxMH(); private static final MethodHandle checkedvccUnboxLoadLongMH = generateCheckedVCCUnboxLoadLongMH(); + private static final MethodHandle vastoreMH = generateVastore(); + private static final MethodHandle invalidVastoreMH = generateInvalidVastore(); private static final ValueCapableClass1 vcc = ValueCapableClass1.create(rL, rI, (short)rI, (short)rI); private static final ValueCapableClass2 vcc2 = ValueCapableClass2.create(rL + 1); @@ -769,7 +771,7 @@ } // Test loop with uncommon trap referencing a value type - @Test(match = {TRAP, SCOBJ}, matchCount = {1, -1 /* at least 1 */}, failOn = LOAD) + @Test(match = {SCOBJ}, matchCount = {-1 /* at least 1 */}, failOn = LOAD) public long test12(boolean b) { MyValue1 v = MyValue1.createWithFieldsInline(rI, rL); MyValue1[] va = new MyValue1[Math.abs(rI) % 10]; @@ -799,7 +801,7 @@ } // Test loop with uncommon trap referencing a value type - @Test(match = {TRAP}, matchCount = {1}) + @Test public long test13(boolean b) { MyValue1 v = MyValue1.createWithFieldsDontInline(rI, rL); MyValue1[] va = new MyValue1[Math.abs(rI) % 10]; @@ -1437,7 +1439,7 @@ } // Merge value type arrays created from two branches - @Test(failOn = (TRAP)) + @Test public MyValue1[] test45(boolean b) { MyValue1[] va; if (b) { @@ -2161,6 +2163,208 @@ } } + /* Array load out of bounds (upper bound) at compile time.*/ + @Test + public int test77() { + int arraySize = Math.abs(rI) % 10;; + MyValue1[] va = new MyValue1[arraySize]; + + for (int i = 0; i < arraySize; i++) { + va[i] = MyValue1.createWithFieldsDontInline(rI + 1, rL); + } + + try { + return va[arraySize + 1].x; + } catch (ArrayIndexOutOfBoundsException e) { + return rI; + } + } + + public void test77_verifier(boolean warmup) { + Asserts.assertEQ(test77(), rI); + } + + /* Array load out of bounds (lower bound) at compile time.*/ + @Test + public int test78() { + int arraySize = Math.abs(rI) % 10;; + MyValue1[] va = new MyValue1[arraySize]; + + for (int i = 0; i < arraySize; i++) { + va[i] = MyValue1.createWithFieldsDontInline(rI + i, rL); + } + + try { + return va[-arraySize].x; + } catch (ArrayIndexOutOfBoundsException e) { + return rI; + } + } + + public void test78_verifier(boolean warmup) { + Asserts.assertEQ(test78(), rI); + } + + /* Array load out of bound not known to compiler (both lower and upper bound). */ + @Test + public int test79(MyValue1[] va, int index) { + return va[index].x; + } + + public void test79_verifier(boolean warmup) { + int arraySize = Math.abs(rI) % 10; + MyValue1[] va = new MyValue1[arraySize]; + + for (int i = 0; i < arraySize; i++) { + va[i] = MyValue1.createWithFieldsDontInline(rI, rL); + } + + int result; + for (int i = -20; i < 20; i++) { + try { + result = test79(va, i); + } catch (ArrayIndexOutOfBoundsException e) { + result = rI; + } + Asserts.assertEQ(result, rI); + } + } + + /* Array store out of bounds (upper bound) at compile time.*/ + @Test + public int test80() { + int arraySize = Math.abs(rI) % 10;; + MyValue1[] va = new MyValue1[arraySize]; + + try { + for (int i = 0; i <= arraySize; i++) { + va[i] = MyValue1.createWithFieldsDontInline(rI + 1, rL); + } + return rI - 1; + } catch (ArrayIndexOutOfBoundsException e) { + return rI; + } + } + + public void test80_verifier(boolean warmup) { + Asserts.assertEQ(test80(), rI); + } + + /* Array store out of bounds (lower bound) at compile time.*/ + @Test + public int test81() { + int arraySize = Math.abs(rI) % 10;; + MyValue1[] va = new MyValue1[arraySize]; + + try { + for (int i = -1; i <= arraySize; i++) { + va[i] = MyValue1.createWithFieldsDontInline(rI + 1, rL); + } + return rI - 1; + } catch (ArrayIndexOutOfBoundsException e) { + return rI; + } + } + + public void test81_verifier(boolean warmup) { + Asserts.assertEQ(test81(), rI); + } + + /* Array store out of bound not known to compiler (both lower and upper bound). */ + @Test + public int test82(MyValue1[] va, int index, MyValue1 vt) { + va[index] = vt; + return va[index].x; + } + + @DontCompile + public void test82_verifier(boolean warmup) { + int arraySize = Math.abs(rI) % 10; + MyValue1[] va = new MyValue1[arraySize]; + + for (int i = 0; i < arraySize; i++) { + va[i] = MyValue1.createWithFieldsDontInline(rI, rL); + } + + MyValue1 vt = MyValue1.createWithFieldsDontInline(rI + 1, rL); + int result; + for (int i = -20; i < 20; i++) { + try { + result = test82(va, i, vt); + } catch (ArrayIndexOutOfBoundsException e) { + result = rI + 1; + } + Asserts.assertEQ(result, rI + 1); + } + + for (int i = 0; i < arraySize; i++) { + Asserts.assertEQ(va[i].x, rI + 1); + } + } + + /* Create a new value type array and store a value type into + * it. The test should pass without throwing an exception. */ + @Test + public void test83() throws Throwable { + vastoreMH.invokeExact(vcc); + } + + public void test83_verifier(boolean warmup) throws Throwable { + test83(); + } + + private static MethodHandle generateVastore() { + return MethodHandleBuilder.loadCode(MethodHandles.lookup(), + "Vastore", + MethodType.methodType(void.class, ValueCapableClass1.class), + CODE -> { + CODE. + iconst_1(). + anewarray(ValueType.forClass(ValueCapableClass1.class).valueClass()). + iconst_0(). + aload_0(). + vunbox(ValueType.forClass(ValueCapableClass1.class).valueClass()). + vastore(). + return_(); + } + ); + } + + /* Create a new value type array with element type + * ValueCapableClass1 and attempt to store a value type of type + * ValueCapableClass2 into it. */ + @Test + public void test84() throws Throwable { + invalidVastoreMH.invokeExact(vcc2); + } + + public void test84_verifier(boolean warmup) throws Throwable { + boolean exceptionThrown = false; + try { + test84(); + } catch (ArrayStoreException e) { + exceptionThrown = true; + } + Asserts.assertTrue(exceptionThrown, "ArrayStoreException must be thrown"); + } + + private static MethodHandle generateInvalidVastore() { + return MethodHandleBuilder.loadCode(MethodHandles.lookup(), + "Vastore", + MethodType.methodType(void.class, ValueCapableClass2.class), + CODE -> { + CODE. + iconst_1(). + anewarray(ValueType.forClass(ValueCapableClass1.class).valueClass()). + iconst_0(). + aload_0(). + vunbox(ValueType.forClass(ValueCapableClass2.class).valueClass()). + vastore(). + return_(); + } + ); + } + // ========== Test infrastructure ========== private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); @@ -2235,7 +2439,7 @@ } public static void main(String[] args) throws Throwable { - //tests.values().removeIf(p -> !p.getName().equals("test74")); // Run single test + //tests.values().removeIf(p -> !p.getName().equals("test85")); // Run single test if (args.length == 0) { execute_vm("-XX:+IgnoreUnrecognizedVMOptions", "-XX:-BackgroundCompilation", "-XX:+PrintCompilation", "-XX:+PrintInlining", "-XX:+PrintIdeal", "-XX:+PrintOptoAssembly",