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