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