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