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 int result = (int) c.getDeclaredMethod("weirdLoop").invoke(null); 73 if (result != 42) { 74 throw new Error("Unexpected result: " + result); 75 } 76 } catch (Throwable t) { 77 t.printStackTrace(); 78 } 79 } 80 $noinline$magicValue()81 public static int $noinline$magicValue() { 82 return 42; 83 } 84 $noinline$returnInt(int result)85 public static int $noinline$returnInt(int result) { 86 // If we are running in non-JIT mode, or were unlucky enough to get this method 87 // already JITted, skip the wait for OSR code. 88 if (isInInterpreter("$noinline$returnInt")) { 89 while (!isInOsrCode("$noinline$returnInt")) {} 90 } 91 return result; 92 } 93 $noinline$returnFloat(float result)94 public static float $noinline$returnFloat(float result) { 95 // If we are running in non-JIT mode, or were unlucky enough to get this method 96 // already JITted, skip the wait for OSR code. 97 if (isInInterpreter("$noinline$returnFloat")) { 98 while (!isInOsrCode("$noinline$returnFloat")) {} 99 } 100 return result; 101 } 102 $noinline$returnDouble(double result)103 public static double $noinline$returnDouble(double result) { 104 // If we are running in non-JIT mode, or were unlucky enough to get this method 105 // already JITted, skip the wait for OSR code. 106 if (isInInterpreter("$noinline$returnDouble")) { 107 while (!isInOsrCode("$noinline$returnDouble")) {} 108 } 109 return result; 110 } 111 $noinline$returnLong(long result)112 public static long $noinline$returnLong(long result) { 113 // If we are running in non-JIT mode, or were unlucky enough to get this method 114 // already JITted, skip the wait for OSR code. 115 if (isInInterpreter("$noinline$returnLong")) { 116 while (!isInOsrCode("$noinline$returnLong")) {} 117 } 118 return result; 119 } 120 isInOsrCode(String methodName)121 public static native boolean isInOsrCode(String methodName); isInInterpreter(String methodName)122 public static native boolean isInInterpreter(String methodName); 123 } 124