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 $noinline$busyLoop()54 public void $noinline$busyLoop() { 55 Main.assertIsManaged(); 56 57 // On Arm64: 58 // This loop is likely to be vectorized which causes the full 16-byte Q-register to be saved 59 // across slow paths. 60 int[] array = new int[kArraySize]; 61 for (int i = 0; i < kArraySize; i++) { 62 array[i]++; 63 } 64 65 sEntered = true; 66 float s0 = kFloatConst0; 67 float s1 = kFloatConst1; 68 for (int i = 0; !sExitFlag; i++) { 69 if (i % 2 == 0) { 70 s0 += 2.0; 71 s1 += 2.0; 72 } else { 73 s0 -= 2.0; 74 s1 -= 2.0; 75 } 76 // SuspendCheckSlowPath must record correct stack offset for spilled FP registers. 77 } 78 Main.assertIsInterpreted(); 79 80 expectEqualToEither(s0, kFloatConst0, kFloatConst0 + 2.0f); 81 expectEqualToEither(s1, kFloatConst1, kFloatConst1 + 2.0f); 82 83 floatField = s0 + s1; 84 } 85 run()86 public void run() { 87 if (threadIndex == 0) { 88 while (!sEntered) { 89 Thread.yield(); 90 } 91 Main.deoptimizeAll(); 92 sExitFlag = true; 93 } else { 94 $noinline$busyLoop(); 95 } 96 } 97 } 98