--- /dev/null 2014-10-17 05:25:30.601014041 +0200 +++ new/test/compiler/rangechecks/TestRangeCheckSmearing.java 2014-12-02 13:42:34.801123276 +0100 @@ -0,0 +1,427 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @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]; + res += array[i+7]; + res += array[i+6]; + res += array[i+5]; + res += array[i+4]; + res += array[i+3]; + res += array[i+2]; + res += array[i+1]; + } + return res; + } + + // first range check is i + min of all constants + static int m2(int[] array, int i, boolean allaccesses) { + int res = 0; + res += array[i+1]; + if (allaccesses) { + res += array[i+2]; + res += array[i+3]; + res += array[i+4]; + res += array[i+5]; + res += array[i+6]; + res += array[i+7]; + res += array[i+8]; + res += array[i+9]; + } + return res; + } + + // first range check is not i + min/max of all constants + static int m3(int[] array, int i, boolean allaccesses) { + int res = 0; + res += array[i+3]; + if (allaccesses) { + res += array[i+2]; + res += array[i+1]; + res += array[i+4]; + res += array[i+5]; + res += array[i+6]; + res += array[i+7]; + res += array[i+8]; + res += array[i+9]; + } + return res; + } + + static int m4(int[] array, int i, boolean allaccesses) { + int res = 0; + res += array[i+3]; + if (allaccesses) { + res += array[i+4]; + res += array[i+1]; + res += array[i+2]; + res += array[i+5]; + res += array[i+6]; + res += array[i+7]; + res += array[i+8]; + res += array[i+9]; + } + return res; + } + + static int m5(int[] array, int i, boolean allaccesses) { + int res = 0; + res += array[i+3]; + res += array[i+2]; + if (allaccesses) { + res += array[i+1]; + res += array[i+4]; + res += array[i+5]; + res += array[i+6]; + res += array[i+7]; + res += array[i+8]; + res += array[i+9]; + } + return res; + } + + static int m6(int[] array, int i, boolean allaccesses) { + int res = 0; + res += array[i+3]; + res += array[i+4]; + if (allaccesses) { + res += array[i+2]; + res += array[i+1]; + res += array[i+5]; + res += array[i+6]; + res += array[i+7]; + res += array[i+8]; + res += array[i+9]; + } + return res; + } + + static int m7(int[] array, int i, boolean allaccesses) { + int res = 0; + res += array[i+3]; + res += array[i+2]; + res += array[i+4]; + if (allaccesses) { + res += array[i+1]; + res += array[i+5]; + res += array[i+6]; + res += array[i+7]; + res += array[i+8]; + res += array[i+9]; + } + return res; + } + + static int m8(int[] array, int i, boolean allaccesses) { + int res = 0; + res += array[i+3]; + res += array[i+4]; + res += array[i+2]; + if (allaccesses) { + res += array[i+1]; + res += array[i+5]; + res += array[i+6]; + res += array[i+7]; + res += array[i+8]; + 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]; + res += array[i-1]; + res += array[i-4]; + res += array[i-5]; + res += array[i-6]; + } + return res; + } + + static int m11(int[] array, int i, boolean allaccesses) { + int res = 0; + res += array[i+3]; + if (allaccesses) { + res += array[i-2]; + res += array[i-1]; + res += array[i-3]; + res += array[i+4]; + res += array[i+5]; + res += array[i+6]; + } + return res; + } + + static int m12(int[] array, int i, boolean allaccesses) { + int res = 0; + res += array[i+3]; + res += array[i-2]; + if (allaccesses) { + res += array[i+5]; + res += array[i+6]; + } + return res; + } + + static int m13(int[] array, int i, boolean allaccesses) { + int res = 0; + res += array[i+3]; + res += array[i+6]; + if (allaccesses) { + res += array[i-2]; + res += array[i-3]; + } + 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"); + } + } +}