1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 // This test checks that FP registers spill offset is correctly recorded in the SlowPath; by causing 18 // asynchronous deoptimization in debuggable mode we observe the FP values in the interpreter. 19 public class FloatLoop implements Runnable { 20 static final int numberOfThreads = 2; 21 volatile static boolean sExitFlag = false; 22 volatile static boolean sEntered = false; 23 int threadIndex; 24 FloatLoop(int index)25 FloatLoop(int index) { 26 threadIndex = index; 27 } 28 main()29 public static void main() throws Exception { 30 final Thread[] threads = new Thread[numberOfThreads]; 31 for (int t = 0; t < threads.length; t++) { 32 threads[t] = new Thread(new FloatLoop(t)); 33 threads[t].start(); 34 } 35 for (Thread t : threads) { 36 t.join(); 37 } 38 39 System.out.println("Float loop finishing"); 40 } 41 42 static final float kFloatConst0 = 256.0f; 43 static final float kFloatConst1 = 128.0f; 44 static final int kArraySize = 128; 45 volatile static float floatField; 46 expectEqualToEither(float value, float expected0, float expected1)47 public void expectEqualToEither(float value, float expected0, float expected1) { 48 if (value != expected0 && value != expected1) { 49 throw new Error("Expected: " + expected0 + " or "+ expected1 + 50 ", found: " + value); 51 } 52 } 53 54 // Create an empty int[] to force loading the int[] class before compiling $noinline$busyLoop. 55 // This makes sure the compiler can properly type int[] and not bail. 56 static int[] emptyArray = new int[0]; 57 $noinline$busyLoop()58 public void $noinline$busyLoop() { 59 Main.assertIsManaged(); 60 61 // On Arm64: 62 // This loop is likely to be vectorized which causes the full 16-byte Q-register to be saved 63 // across slow paths. 64 int[] array = new int[kArraySize]; 65 for (int i = 0; i < kArraySize; i++) { 66 array[i]++; 67 } 68 69 sEntered = true; 70 float s0 = kFloatConst0; 71 float s1 = kFloatConst1; 72 for (int i = 0; !sExitFlag; i++) { 73 if (i % 2 == 0) { 74 s0 += 2.0; 75 s1 += 2.0; 76 } else { 77 s0 -= 2.0; 78 s1 -= 2.0; 79 } 80 // SuspendCheckSlowPath must record correct stack offset for spilled FP registers. 81 } 82 Main.assertIsInterpreted(); 83 84 expectEqualToEither(s0, kFloatConst0, kFloatConst0 + 2.0f); 85 expectEqualToEither(s1, kFloatConst1, kFloatConst1 + 2.0f); 86 87 floatField = s0 + s1; 88 } 89 run()90 public void run() { 91 if (threadIndex == 0) { 92 while (!sEntered) { 93 Thread.yield(); 94 } 95 Main.deoptimizeAll(); 96 sExitFlag = true; 97 } else { 98 $noinline$busyLoop(); 99 } 100 } 101 } 102