/* * 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; }