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 public class Main { main(String[] args)18 public static void main(String[] args) { 19 System.loadLibrary(args[0]); 20 while (runTests(true)); 21 runTests(false); 22 runSmaliTest(); 23 } 24 runTests(boolean warmup)25 public static boolean runTests(boolean warmup) { 26 if (warmup) { 27 return isInInterpreter("runTests"); 28 } 29 30 // Several local variables which live across calls below, 31 // thus they are likely to be saved in callee save registers. 32 int i = $noinline$magicValue(); 33 long l = $noinline$magicValue(); 34 float f = $noinline$magicValue(); 35 double d = $noinline$magicValue(); 36 37 // The calls below will OSR. We pass the expected value in 38 // argument, which should be saved in callee save register. 39 if ($noinline$returnInt(53) != 53) { 40 throw new Error("Unexpected return value"); 41 } 42 if ($noinline$returnFloat(42.2f) != 42.2f) { 43 throw new Error("Unexpected return value"); 44 } 45 if ($noinline$returnDouble(Double.longBitsToDouble(0xF000000000001111L)) != 46 Double.longBitsToDouble(0xF000000000001111L)) { 47 throw new Error("Unexpected return value "); 48 } 49 if ($noinline$returnLong(0xFFFF000000001111L) != 0xFFFF000000001111L) { 50 throw new Error("Unexpected return value"); 51 } 52 53 // Check that the register used in callee did not clober our value. 54 if (i != $noinline$magicValue()) { 55 throw new Error("Corrupted int local variable in caller"); 56 } 57 if (l != $noinline$magicValue()) { 58 throw new Error("Corrupted long local variable in caller"); 59 } 60 if (f != $noinline$magicValue()) { 61 throw new Error("Corrupted float local variable in caller"); 62 } 63 if (d != $noinline$magicValue()) { 64 throw new Error("Corrupted double local variable in caller"); 65 } 66 return true; 67 } 68 runSmaliTest()69 public static void runSmaliTest() { 70 try { 71 Class<?> c = Class.forName("WeirdLoop"); 72 // Make sure `WeirdLoop` is visibly initialized to avoid waiting for OSR 73 // for the `--jit-on=first-use` configuration. 74 makeVisiblyInitialized(); 75 int result = (int) c.getDeclaredMethod("weirdLoop").invoke(null); 76 if (result != 42) { 77 throw new Error("Unexpected result: " + result); 78 } 79 } catch (Throwable t) { 80 t.printStackTrace(); 81 } 82 } 83 $noinline$magicValue()84 public static int $noinline$magicValue() { 85 return 42; 86 } 87 $noinline$returnInt(int result)88 public static int $noinline$returnInt(int result) { 89 // If we are running in non-JIT mode, or were unlucky enough to get this method 90 // already JITted, skip the wait for OSR code. 91 if (isInInterpreter("$noinline$returnInt")) { 92 while (!isInOsrCode("$noinline$returnInt")) {} 93 } 94 return result; 95 } 96 $noinline$returnFloat(float result)97 public static float $noinline$returnFloat(float result) { 98 // If we are running in non-JIT mode, or were unlucky enough to get this method 99 // already JITted, skip the wait for OSR code. 100 if (isInInterpreter("$noinline$returnFloat")) { 101 while (!isInOsrCode("$noinline$returnFloat")) {} 102 } 103 return result; 104 } 105 $noinline$returnDouble(double result)106 public static double $noinline$returnDouble(double result) { 107 // If we are running in non-JIT mode, or were unlucky enough to get this method 108 // already JITted, skip the wait for OSR code. 109 if (isInInterpreter("$noinline$returnDouble")) { 110 while (!isInOsrCode("$noinline$returnDouble")) {} 111 } 112 return result; 113 } 114 $noinline$returnLong(long result)115 public static long $noinline$returnLong(long result) { 116 // If we are running in non-JIT mode, or were unlucky enough to get this method 117 // already JITted, skip the wait for OSR code. 118 if (isInInterpreter("$noinline$returnLong")) { 119 while (!isInOsrCode("$noinline$returnLong")) {} 120 } 121 return result; 122 } 123 isInOsrCode(String methodName)124 public static native boolean isInOsrCode(String methodName); isInInterpreter(String methodName)125 public static native boolean isInInterpreter(String methodName); makeVisiblyInitialized()126 public static native void makeVisiblyInitialized(); 127 } 128