blob: f7ce32a42a1c88cea28e79df65fa6098c41802a1 [file] [log] [blame]
Mingyao Yangf711f2c2016-05-23 12:29:39 -07001/*
2 * Copyright (C) 2016 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
17import java.lang.reflect.Method;
18import java.util.Arrays;
19import java.util.Comparator;
20import java.util.HashMap;
21
22class DummyObject {
23 public static boolean sHashCodeInvoked = false;
24 private int i;
25
26 public DummyObject(int i) {
27 this.i = i;
28 }
29
30 public boolean equals(Object obj) {
31 return (obj instanceof DummyObject) && (i == ((DummyObject)obj).i);
32 }
33
34 public int hashCode() {
35 sHashCodeInvoked = true;
36 Main.assertIsManaged();
37 Main.deoptimizeAll();
38 Main.assertIsInterpreted();
39 Main.assertCallerIsManaged(); // Caller is from framework code HashMap.
40 return i % 64;
41 }
42}
43
44public class Main {
45 static boolean sFlag = false;
46
47 public static native void deoptimizeAll();
48 public static native void undeoptimizeAll();
49 public static native void assertIsInterpreted();
50 public static native void assertIsManaged();
51 public static native void assertCallerIsInterpreted();
52 public static native void assertCallerIsManaged();
Nicolas Geoffray20e9cef2016-05-27 10:38:14 +010053 public static native void disableStackFrameAsserts();
54 public static native boolean hasOatFile();
55 public static native boolean isInterpreted();
Mingyao Yangf711f2c2016-05-23 12:29:39 -070056
57 public static void execute(Runnable runnable) throws Exception {
58 Thread t = new Thread(runnable);
59 t.start();
60 t.join();
61 }
62
63 public static void main(String[] args) throws Exception {
64 System.loadLibrary(args[0]);
Nicolas Geoffray20e9cef2016-05-27 10:38:14 +010065 // Only test stack frames in compiled mode.
66 if (!hasOatFile() || isInterpreted()) {
67 disableStackFrameAsserts();
68 }
Mingyao Yangf711f2c2016-05-23 12:29:39 -070069 final HashMap<DummyObject, Long> map = new HashMap<DummyObject, Long>();
70
71 // Single-frame deoptimization that covers partial fragment.
72 execute(new Runnable() {
73 public void run() {
74 int[] arr = new int[3];
75 assertIsManaged();
76 int res = $noinline$run1(arr);
77 assertIsManaged(); // Only single frame is deoptimized.
78 if (res != 79) {
79 System.out.println("Failure 1!");
Nicolas Geoffraya42f4e62018-09-14 10:47:25 +010080 System.exit(1);
Mingyao Yangf711f2c2016-05-23 12:29:39 -070081 }
82 }
83 });
84
85 // Single-frame deoptimization that covers a full fragment.
86 execute(new Runnable() {
87 public void run() {
88 try {
89 int[] arr = new int[3];
90 assertIsManaged();
91 // Use reflection to call $noinline$run2 so that it does
92 // full-fragment deoptimization since that is an upcall.
93 Class<?> cls = Class.forName("Main");
94 Method method = cls.getDeclaredMethod("$noinline$run2", int[].class);
95 double res = (double)method.invoke(Main.class, arr);
96 assertIsManaged(); // Only single frame is deoptimized.
97 if (res != 79.3d) {
98 System.out.println("Failure 2!");
Nicolas Geoffraya42f4e62018-09-14 10:47:25 +010099 System.exit(2);
Mingyao Yangf711f2c2016-05-23 12:29:39 -0700100 }
101 } catch (Exception e) {
Kevin Brodskyf6c66c32015-12-17 14:13:00 +0000102 e.printStackTrace(System.out);
Mingyao Yangf711f2c2016-05-23 12:29:39 -0700103 }
104 }
105 });
106
107 // Full-fragment deoptimization.
108 execute(new Runnable() {
109 public void run() {
110 assertIsManaged();
111 float res = $noinline$run3B();
112 assertIsInterpreted(); // Every deoptimizeable method is deoptimized.
113 if (res != 0.034f) {
114 System.out.println("Failure 3!");
Nicolas Geoffraya42f4e62018-09-14 10:47:25 +0100115 System.exit(3);
Mingyao Yangf711f2c2016-05-23 12:29:39 -0700116 }
117 }
118 });
119
120 undeoptimizeAll(); // Make compiled code useable again.
121
122 // Partial-fragment deoptimization.
123 execute(new Runnable() {
124 public void run() {
125 try {
126 assertIsManaged();
127 map.put(new DummyObject(10), Long.valueOf(100));
128 assertIsInterpreted(); // Every deoptimizeable method is deoptimized.
129 } catch (Exception e) {
Kevin Brodskyf6c66c32015-12-17 14:13:00 +0000130 e.printStackTrace(System.out);
Mingyao Yangf711f2c2016-05-23 12:29:39 -0700131 }
132 }
133 });
134
135 undeoptimizeAll(); // Make compiled code useable again.
136
137 if (!DummyObject.sHashCodeInvoked) {
138 System.out.println("hashCode() method not invoked!");
Nicolas Geoffraya42f4e62018-09-14 10:47:25 +0100139 System.exit(4);
Mingyao Yangf711f2c2016-05-23 12:29:39 -0700140 }
141 if (map.get(new DummyObject(10)) != 100) {
142 System.out.println("Wrong hashmap value!");
Nicolas Geoffraya42f4e62018-09-14 10:47:25 +0100143 System.exit(5);
Mingyao Yangf711f2c2016-05-23 12:29:39 -0700144 }
145 System.out.println("Finishing");
146 }
147
148 public static int $noinline$run1(int[] arr) {
149 assertIsManaged();
150 // Prevent inlining.
151 if (sFlag) {
152 throw new Error();
153 }
154 boolean caught = false;
155 // BCE will use deoptimization for the code below.
156 try {
157 arr[0] = 1;
158 arr[1] = 1;
159 arr[2] = 1;
160 // This causes AIOOBE and triggers deoptimization from compiled code.
161 arr[3] = 1;
162 } catch (ArrayIndexOutOfBoundsException e) {
163 assertIsInterpreted(); // Single-frame deoptimization triggered.
164 caught = true;
165 }
166 if (!caught) {
167 System.out.println("Expected exception");
Nicolas Geoffraya42f4e62018-09-14 10:47:25 +0100168 System.exit(6);
Mingyao Yangf711f2c2016-05-23 12:29:39 -0700169 }
170 assertIsInterpreted();
171 return 79;
172 }
173
174 public static double $noinline$run2(int[] arr) {
175 assertIsManaged();
176 // Prevent inlining.
177 if (sFlag) {
178 throw new Error();
179 }
180 boolean caught = false;
181 // BCE will use deoptimization for the code below.
182 try {
183 arr[0] = 1;
184 arr[1] = 1;
185 arr[2] = 1;
186 // This causes AIOOBE and triggers deoptimization from compiled code.
187 arr[3] = 1;
188 } catch (ArrayIndexOutOfBoundsException e) {
189 assertIsInterpreted(); // Single-frame deoptimization triggered.
190 caught = true;
191 }
192 if (!caught) {
193 System.out.println("Expected exception");
Nicolas Geoffraya42f4e62018-09-14 10:47:25 +0100194 System.exit(7);
Mingyao Yangf711f2c2016-05-23 12:29:39 -0700195 }
196 assertIsInterpreted();
197 return 79.3d;
198 }
199
200 public static float $noinline$run3A() {
201 assertIsManaged();
202 // Prevent inlining.
203 if (sFlag) {
204 throw new Error();
205 }
206 // Deoptimize callers.
207 deoptimizeAll();
208 assertIsInterpreted();
209 assertCallerIsInterpreted(); // $noinline$run3B is deoptimizeable.
210 return 0.034f;
211 }
212
213 public static float $noinline$run3B() {
214 assertIsManaged();
215 // Prevent inlining.
216 if (sFlag) {
217 throw new Error();
218 }
219 float res = $noinline$run3A();
220 assertIsInterpreted();
221 return res;
222 }
223}