/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
public class Main {
public static void main(String[] args) {
new Main().run();
testPreserveFloat();
testPreserveDouble();
System.out.println("finish");
}
public void run() {
double a[][] = new double[200][201];
double b[] = new double[200];
int n = 100;
foo1(a, n, b);
}
void foo1(double a[][], int n, double b[]) {
double t;
int i,k;
for (i = 0; i < n; i++) {
k = n - (i + 1);
b[k] /= a[k][k];
t = -b[k];
foo2(k + 1000, t, b);
}
}
void foo2(int n, double c, double b[]) {
try {
foo3(n, c, b);
} catch (Exception e) {
}
}
void foo3(int n, double c, double b[]) {
int i = 0;
for (i = 0; i < n; i++) {
b[i + 1] += c * b[i + 1];
}
}
/*
* Test that we correctly preserve floating point registers when we deoptimize.
*
* Note: These tests rely on the deoptimization happening before the loop,
* so that the loop is interpreted and fills the provided arrays. However,
* the BCE transformation can be modified to execute the loop as many times
* as the compiler can guarantee no AIOOBE and only deoptimize thereafter,
* just before the throwing iteration. Then the floating point registers
* would no longer be used after the deoptimization and another approach
* would be needed to test this.
*/
static public void testPreserveFloat() {
float[] array = new float[2];
try {
$noinline$FloatFill(1.125f, 2.5f, array, 3);
throw new Error();
} catch (ArrayIndexOutOfBoundsException expected) {
System.out.println("array[0]=" + array[0] + "f");
System.out.println("array[1]=" + array[1] + "f");
}
}
/// CHECK-START: void Main.$noinline$FloatFill(float, float, float[], int) BCE (after)
/// CHECK-DAG: Deoptimize
/// CHECK-DAG: Deoptimize
/// CHECK-DAG: Deoptimize
/// CHECK-NOT: Deoptimize
/// CHECK-START: void Main.$noinline$FloatFill(float, float, float[], int) BCE (after)
/// CHECK-NOT: BoundsCheck
public static void $noinline$FloatFill(float f1, float f2, float[] array, int n) {
if (doThrow) { throw new Error(); }
for (int i = 0; i < n; ++i) {
array[i] = ((i & 1) == 1) ? f1 : f2;
f1 += 1.5f;
f2 += 2.25f;
}
}
static public void testPreserveDouble() {
double[] array = new double[2];
try {
$noinline$DoubleFill(2.125, 3.5, array, 3);
throw new Error();
} catch (ArrayIndexOutOfBoundsException expected) {
System.out.println("array[0]=" + array[0]);
System.out.println("array[1]=" + array[1]);
}
}
/// CHECK-START: void Main.$noinline$DoubleFill(double, double, double[], int) BCE (after)
/// CHECK-DAG: Deoptimize
/// CHECK-DAG: Deoptimize
/// CHECK-DAG: Deoptimize
/// CHECK-NOT: Deoptimize
/// CHECK-START: void Main.$noinline$DoubleFill(double, double, double[], int) BCE (after)
/// CHECK-NOT: BoundsCheck
public static void $noinline$DoubleFill(double d1, double d2, double[] array, int n) {
if (doThrow) { throw new Error(); }
for (int i = 0; i < n; ++i) {
array[i] = ((i & 1) == 1) ? d1 : d2;
d1 += 1.5;
d2 += 2.25;
}
}
public static boolean doThrow = false;
}