Path: blob/master/test/hotspot/jtreg/vmTestbase/jit/Arrays/ArrayBounds/ArrayBounds.java
40948 views
/*1* Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25*26* @summary converted from VM Testbase jit/Arrays/ArrayBounds.27* VM Testbase keywords: [jit, quick]28*29* @library /vmTestbase30* /test/lib31* @run main/othervm jit.Arrays.ArrayBounds.ArrayBounds32*/3334package jit.Arrays.ArrayBounds;3536/*37SCCS ID : @(#)ArrayBounds.java 1.2 02/07/1638*/39/* The intent of this Java program is to expose Virtual Machines that40make illegal array bounds check removal optimizations. */4142/* There are a variety of potential semantic problems with array bounds43checking.4445One source of potential bounds-check problems is a compiler that46"hoist"s bounds checks outside of loops. This may either either47because an array access is loop invariant, or because the compiler48is clever enough to determine a loop-invariant "sufficient49condition" that guarantees the safety of the safety of one or more50accesses within the loop.5152While this is a good approach, it has a variety of possible53pitfalls:54551) If a hoisted test fails, you can't just raise a bounds-check56exception when the test fails; the loop may have had global57side effects before the exception was supposed to have been58raised. [prematureExceptionTest]59602) A hoisted test may itself generate an exception (such as a61null pointer exception). Again, this must not be reflected62prematurely if the loop has global side effects that should be63observed.64653) An implementation might fail to be conservative enough about66the possible side effects of a method call within the loop.67For example, when an array being accessed within a loop is68accessed as a static or instance variable, then any call must69be assumed to possibly modify the array variable itself (in70the absence of pretty clever proof techniques!) So no hoisted71predicate mentioning the array length (as most will) can be72loop-invariant.73744) In some implementations, the code generated for a bounds-check75implicitly does a null check as well. For example, it may76access an array length field in the object header. On systems77where the 0-th page is protected, this might ensure an OS78signal for a null array pointer. But if a bounds check is79elided, the generated code might only access the null pointer80at a large offset, beyond the protected page, and fail to81produce a null pointer exception.82835) Multi-dimensional arrays are annoying for bounds-check removal.84If a loop over "i" accesses "a[i][j]" (where "j" is invariant in85the loop, then "a[i]" is not loop-invariant; it changes every86iteration. Even if a two-dimensional array were "rectangular"87when a loop begins, nothing guarantees that another thread88won't update some "a[k]" during the loop. If the compiler89hoisted some bounds check comparing "j" to the presumed length90of all the "a[k]", and a shorter array were written to some91"a[k]" during the loop, then we might miss a necessary array92bounds exception.93*/9495import nsk.share.TestFailure;969798public class ArrayBounds {99private static int global;100101private static int[] aplIota(int n) {102int[] a = new int[n];103for (int j = 0; j < n; j++) a[j] = j;104return a;105}106107private static int prematureExceptionWork(int[] a, int n) {108global = 0;109int sum = 0;110try {111for (int i = 0; i < n; i++) {112global++; sum += a[i];113}114} catch (ArrayIndexOutOfBoundsException t) {}115return sum;116}117private static void prematureException() {118int[] a = aplIota(10);119int sum = prematureExceptionWork(a, 11);120if (global != 11 || sum != 45) {121throw new TestFailure("Premature exception test failed.");122}123}124125private static class Foo {126int[] a;127}128129private static int exceptionInHoistedPredWork(Foo f, int n) {130global = 0;131int sum = 0;132try {133for (int i = 0; i < n; i++) {134global++; sum += f.a[i];135}136} catch (NullPointerException t) {}137return sum;138}139private static void exceptionInHoistedPred() {140int sum = exceptionInHoistedPredWork(null, 10);141if (global != 1 || sum != 0) {142throw new TestFailure("Premature exception test failed.");143}144}145146private static void changeLength(Foo f, int n) {147int[] a = aplIota(n);148f.a = a;149}150private static int arraySideEffectWork(Foo f, int n) {151int sum = 0;152try {153for (int i = 0; i < n; i++) {154sum += f.a[i];155if (i == 0) changeLength(f, 5);156}157} catch (ArrayIndexOutOfBoundsException t) {}158return sum;159}160private static void arraySideEffect() {161int[] a = aplIota(10);162Foo f = new Foo(); f.a = a;163int sum = arraySideEffectWork(f, 10);164if (sum != 10) {165throw new TestFailure("Array side effect test failed (" + sum + ")");166}167}168169private static boolean nullArrayWork(int[] a, int n) {170int sum = 0;171global = 0;172boolean x = false;173try {174for (int i = 0; i < n; i++) {175global++; sum += a[i];176}177} catch (NullPointerException t) {178x = true;179}180return x;181}182private static void nullArray() {183/* 30000 should be larger than most pages sizes! */184if (!nullArrayWork(null, 30000) || global != 1) {185throw new TestFailure("nullArray test failed.");186}187}188189private static int[][] aa = new int[10][20];190static {191for (int i = 0; i < 10; i++) aa[i] = aplIota(20);192}193private static class ArrayMutator extends Thread {194int[][] aa; int newN;195ArrayMutator(int[][] aa, int newN) {196super();197this.aa = aa; this.newN = newN;198}199public void run() {200aa[1] = aplIota(newN);201}202}203204private static int array2DWork(int[][] aa, int m, int n) {205int sum = 0;206global = 0;207try {208for (int i = 0; i < m; i++) {209for (int j = 0; j < n; j++) {210global++; sum += aa[i][j];211if (i == 0 && j == 0) {212Thread t = new ArrayMutator(aa, n/2);213try {214t.start();215t.join();216} catch (InterruptedException x) {}217}218}219}220} catch (ArrayIndexOutOfBoundsException t) {}221return sum;222}223private static void array2D() {224int sum = array2DWork(aa, aa.length, aa[0].length);225if (sum != 19*20/2 + 9*10/2 || global != 20 + 10 + 1) {226throw new TestFailure("array2D test failed (sum = " + sum +227"; global = " + global + ")");228}229}230231public static void main(String[] args) {232exceptionInHoistedPred();233prematureException();234arraySideEffect();235nullArray();236array2D();237}238}239240241