test/compiler/rangechecks/TestRangeCheckSmearing.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File hotspot Cdiff test/compiler/rangechecks/TestRangeCheckSmearing.java

test/compiler/rangechecks/TestRangeCheckSmearing.java

Print this page
rev 7552 : 8066103: C2's range check smearing allows out of bound array accesses
Summary: range check smearing uncorrectly adjust first range check in a list of range checks to cover all of them
Reviewed-by:
rev 7553 : reviews

*** 23,39 **** /* * @test * @bug 8066103 * @summary C2's range check smearing allows out of bound array accesses ! * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestRangeCheckSmearing * */ public class TestRangeCheckSmearing { // first range check is i + max of all constants static int m1(int[] array, int i, boolean allaccesses) { int res = 0; res += array[i+9]; if (allaccesses) { res += array[i+8]; --- 23,56 ---- /* * @test * @bug 8066103 * @summary C2's range check smearing allows out of bound array accesses ! * @library /testlibrary /testlibrary/whitebox /compiler/whitebox /testlibrary/com/oracle/java/testlibrary ! * @build TestRangeCheckSmearing ! * @run main ClassFileInstaller sun.hotspot.WhiteBox ! * @run main ClassFileInstaller com.oracle.java.testlibrary.Platform ! * @run main/othervm -ea -Xmixed -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ! * -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestRangeCheckSmearing * */ + import java.lang.annotation.*; + import java.lang.reflect.*; + import java.util.*; + import sun.hotspot.WhiteBox; + import sun.hotspot.code.NMethod; + import com.oracle.java.testlibrary.Platform; + public class TestRangeCheckSmearing { + private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + + @Retention(RetentionPolicy.RUNTIME) + @interface Args { int[] value(); } // first range check is i + max of all constants + @Args({0, 8}) static int m1(int[] array, int i, boolean allaccesses) { int res = 0; res += array[i+9]; if (allaccesses) { res += array[i+8];
*** 47,56 **** --- 64,74 ---- } return res; } // first range check is i + min of all constants + @Args({0, -9}) static int m2(int[] array, int i, boolean allaccesses) { int res = 0; res += array[i+1]; if (allaccesses) { res += array[i+2];
*** 64,73 **** --- 82,92 ---- } return res; } // first range check is not i + min/max of all constants + @Args({0, 8}) static int m3(int[] array, int i, boolean allaccesses) { int res = 0; res += array[i+3]; if (allaccesses) { res += array[i+2];
*** 80,89 **** --- 99,109 ---- res += array[i+9]; } return res; } + @Args({0, -9}) static int m4(int[] array, int i, boolean allaccesses) { int res = 0; res += array[i+3]; if (allaccesses) { res += array[i+4];
*** 96,105 **** --- 116,126 ---- res += array[i+9]; } return res; } + @Args({0, -3}) static int m5(int[] array, int i, boolean allaccesses) { int res = 0; res += array[i+3]; res += array[i+2]; if (allaccesses) {
*** 112,121 **** --- 133,143 ---- res += array[i+9]; } return res; } + @Args({0, 6}) static int m6(int[] array, int i, boolean allaccesses) { int res = 0; res += array[i+3]; res += array[i+4]; if (allaccesses) {
*** 128,137 **** --- 150,160 ---- res += array[i+9]; } return res; } + @Args({0, 6}) static int m7(int[] array, int i, boolean allaccesses) { int res = 0; res += array[i+3]; res += array[i+2]; res += array[i+4];
*** 144,153 **** --- 167,177 ---- res += array[i+9]; } return res; } + @Args({0, -3}) static int m8(int[] array, int i, boolean allaccesses) { int res = 0; res += array[i+3]; res += array[i+4]; res += array[i+2];
*** 160,176 **** res += array[i+9]; } return res; } ! static int m9(int[] array, int i) { int res = 0; res += array[i+3]; res += array[i+3]; return res; } static int m10(int[] array, int i, boolean allaccesses) { int res = 0; res += array[i+3]; if (allaccesses) { res += array[i-2]; --- 184,202 ---- res += array[i+9]; } return res; } ! @Args({0}) ! static int m9(int[] array, int i, boolean ignore) { int res = 0; res += array[i+3]; res += array[i+3]; return res; } + @Args({6, 15}) static int m10(int[] array, int i, boolean allaccesses) { int res = 0; res += array[i+3]; if (allaccesses) { res += array[i-2];
*** 180,189 **** --- 206,216 ---- res += array[i-6]; } return res; } + @Args({3, 12}) static int m11(int[] array, int i, boolean allaccesses) { int res = 0; res += array[i+3]; if (allaccesses) { res += array[i-2];
*** 194,203 **** --- 221,231 ---- res += array[i+6]; } return res; } + @Args({3, -3}) static int m12(int[] array, int i, boolean allaccesses) { int res = 0; res += array[i+3]; res += array[i-2]; if (allaccesses) {
*** 205,214 **** --- 233,243 ---- res += array[i+6]; } return res; } + @Args({3, 6}) static int m13(int[] array, int i, boolean allaccesses) { int res = 0; res += array[i+3]; res += array[i+6]; if (allaccesses) {
*** 217,427 **** } return res; } static public void main(String[] args) { ! boolean success = true; ! boolean exception = false; ! int[] array = new int[10]; ! ! for (int i = 0; i < 20000; i++) { ! m1(array, 0, (i % 2) == 0); ! } ! ! exception = false; ! try { ! m1(array, 8, false); ! } catch(ArrayIndexOutOfBoundsException aioob) { ! exception = true; ! System.out.println("ArrayIndexOutOfBoundsException thrown in m1"); ! } ! if (!exception) { ! System.out.println("ArrayIndexOutOfBoundsException was not thrown in m1"); ! success = false; ! } ! ! for (int i = 0; i < 20000; i++) { ! m2(array, 0, (i % 2) == 0); ! } ! ! exception = false; ! try { ! m2(array, -9, false); ! } catch(ArrayIndexOutOfBoundsException aioob) { ! exception = true; ! System.out.println("ArrayIndexOutOfBoundsException thrown in m2"); ! } ! if (!exception) { ! System.out.println("ArrayIndexOutOfBoundsException was not thrown in m2"); ! success = false; ! } ! ! for (int i = 0; i < 20000; i++) { ! m3(array, 0, (i % 2) == 0); } ! ! exception = false; ! try { ! m3(array, 8, false); ! } catch(ArrayIndexOutOfBoundsException aioob) { ! exception = true; ! System.out.println("ArrayIndexOutOfBoundsException thrown in m3"); ! } ! if (!exception) { ! System.out.println("ArrayIndexOutOfBoundsException was not thrown in m3"); ! success = false; ! } ! ! for (int i = 0; i < 20000; i++) { ! m4(array, 0, (i % 2) == 0); ! } ! ! exception = false; ! try { ! m4(array, -9, false); ! } catch(ArrayIndexOutOfBoundsException aioob) { ! exception = true; ! System.out.println("ArrayIndexOutOfBoundsException thrown in m4"); ! } ! if (!exception) { ! System.out.println("ArrayIndexOutOfBoundsException was not thrown in m4"); ! success = false; ! } ! ! for (int i = 0; i < 20000; i++) { ! m5(array, 0, (i % 2) == 0); ! } ! ! exception = false; ! try { ! m5(array, -3, false); ! } catch(ArrayIndexOutOfBoundsException aioob) { ! exception = true; ! System.out.println("ArrayIndexOutOfBoundsException thrown in m5"); } ! if (!exception) { ! System.out.println("ArrayIndexOutOfBoundsException was not thrown in m5"); ! success = false; ! } ! ! for (int i = 0; i < 20000; i++) { ! m6(array, 0, (i % 2) == 0); } - - exception = false; - try { - m6(array, 6, false); - } catch(ArrayIndexOutOfBoundsException aioob) { - exception = true; - System.out.println("ArrayIndexOutOfBoundsException thrown in m6"); } - if (!exception) { - System.out.println("ArrayIndexOutOfBoundsException was not thrown in m6"); - success = false; } ! for (int i = 0; i < 20000; i++) { ! m7(array, 0, (i % 2) == 0); ! } ! ! exception = false; try { ! m7(array, 6, false); ! } catch(ArrayIndexOutOfBoundsException aioob) { ! exception = true; ! System.out.println("ArrayIndexOutOfBoundsException thrown in m7"); } - if (!exception) { - System.out.println("ArrayIndexOutOfBoundsException was not thrown in m7"); - success = false; } ! for (int i = 0; i < 20000; i++) { ! m8(array, 0, (i % 2) == 0); } ! ! exception = false; ! try { ! m8(array, -3, false); ! } catch(ArrayIndexOutOfBoundsException aioob) { ! exception = true; ! System.out.println("ArrayIndexOutOfBoundsException thrown in m8"); } - if (!exception) { - System.out.println("ArrayIndexOutOfBoundsException was not thrown in m8"); - success = false; } ! ! for (int i = 0; i < 20000; i++) { ! m9(array, 0); } ! for (int i = 0; i < 20000; i++) { ! m10(array, 6, (i % 2) == 0); } exception = false; try { ! m10(array, 15, false); } catch(ArrayIndexOutOfBoundsException aioob) { exception = true; ! System.out.println("ArrayIndexOutOfBoundsException thrown in m10"); } if (!exception) { ! System.out.println("ArrayIndexOutOfBoundsException was not thrown in m10"); ! success = false; ! } ! ! for (int i = 0; i < 20000; i++) { ! m11(array, 3, (i % 2) == 0); } ! exception = false; ! try { ! m11(array, 12, false); ! } catch(ArrayIndexOutOfBoundsException aioob) { ! exception = true; ! System.out.println("ArrayIndexOutOfBoundsException thrown in m11"); ! } ! if (!exception) { ! System.out.println("ArrayIndexOutOfBoundsException was not thrown in m11"); success = false; } - - for (int i = 0; i < 20000; i++) { - m12(array, 3, (i % 2) == 0); } ! exception = false; ! try { ! m12(array, -3, false); ! } catch(ArrayIndexOutOfBoundsException aioob) { ! exception = true; ! System.out.println("ArrayIndexOutOfBoundsException thrown in m12"); ! } ! if (!exception) { ! System.out.println("ArrayIndexOutOfBoundsException was not thrown in m12"); success = false; } ! for (int i = 0; i < 20000; i++) { ! m13(array, 3, (i % 2) == 0); } - exception = false; - try { - m13(array, 6, false); - } catch(ArrayIndexOutOfBoundsException aioob) { - exception = true; - System.out.println("ArrayIndexOutOfBoundsException thrown in m13"); - } - if (!exception) { - System.out.println("ArrayIndexOutOfBoundsException was not thrown in m13"); - success = false; } ! if (!success) { throw new RuntimeException("Some tests failed"); } } } --- 246,363 ---- } return res; } static public void main(String[] args) { ! if (WHITE_BOX.getBooleanVMFlag("BackgroundCompilation")) { ! throw new AssertionError("Background compilation enabled"); } ! new TestRangeCheckSmearing().doTests(); } ! boolean success = true; ! boolean exception = false; ! final int[] array = new int[10]; ! final HashMap<String,Method> tests = new HashMap<>(); ! { ! final Class<?> TEST_PARAM_TYPES[] = { int[].class, int.class, boolean.class }; ! for (Method m : this.getClass().getDeclaredMethods()) { ! if (m.getName().matches("m[0-9]+")) { ! assert(Modifier.isStatic(m.getModifiers())) : m; ! assert(m.getReturnType() == int.class) : m; ! assert(Arrays.equals(m.getParameterTypes(), TEST_PARAM_TYPES)) : m; ! tests.put(m.getName(), m); } } } ! void invokeTest(Method m, int[] array, int index, boolean z) { try { ! m.invoke(null, array, index, z); ! } catch (ReflectiveOperationException roe) { ! Throwable ex = roe.getCause(); ! if (ex instanceof ArrayIndexOutOfBoundsException) ! throw (ArrayIndexOutOfBoundsException) ex; ! throw new AssertionError(roe); } } ! void doTest(String name) { ! Method m = tests.get(name); ! tests.remove(name); ! int[] args = m.getAnnotation(Args.class).value(); ! int index0 = args[0], index1; ! boolean exceptionRequired = true; ! if (args.length == 2) { ! index1 = args[1]; ! } else { ! // no negative test for this one ! assert(args.length == 1); ! assert(name.equals("m9")); ! exceptionRequired = false; ! index1 = index0; } ! // Get the method compiled. ! if (!WHITE_BOX.isMethodCompiled(m)) { ! // If not, try to compile it with C2 ! if(!WHITE_BOX.enqueueMethodForCompilation(m, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION)) { ! // C2 compiler not available, try to compile with C1 ! WHITE_BOX.enqueueMethodForCompilation(m, CompilerWhiteBoxTest.COMP_LEVEL_SIMPLE); } } ! if (!WHITE_BOX.isMethodCompiled(m)) { ! throw new RuntimeException(m + " not compiled"); } + // valid access + invokeTest(m, array, index0, true); ! if (!WHITE_BOX.isMethodCompiled(m)) { ! throw new RuntimeException(m + " deoptimized on valid array access"); } exception = false; try { ! invokeTest(m, array, index1, false); } catch(ArrayIndexOutOfBoundsException aioob) { exception = true; ! System.out.println("ArrayIndexOutOfBoundsException thrown in "+name); } if (!exception) { ! System.out.println("ArrayIndexOutOfBoundsException was not thrown in "+name); } ! if (Platform.isServer()) { ! if (exceptionRequired == WHITE_BOX.isMethodCompiled(m)) { ! System.out.println((exceptionRequired?"Didn't deoptimized":"deoptimized") + " in "+name); success = false; } } ! if (exception != exceptionRequired) { success = false; } ! if (!success) { ! System.out.println("TEST FAILED: "+name); } } ! void doTests() { ! doTest("m1"); ! doTest("m2"); ! doTest("m3"); ! doTest("m4"); ! doTest("m5"); ! doTest("m6"); ! doTest("m7"); ! doTest("m8"); ! doTest("m9"); ! doTest("m10"); ! doTest("m11"); ! doTest("m12"); ! doTest("m13"); if (!success) { throw new RuntimeException("Some tests failed"); } + assert(tests.isEmpty()) : tests; } }
test/compiler/rangechecks/TestRangeCheckSmearing.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File