blob: 3d45b861c981345f0fdacbc379843f4c13a184ea [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 Geoffrayadfd25c2018-09-14 20:07:30 +000080 System.exit(0);
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 Geoffrayadfd25c2018-09-14 20:07:30 +000099 System.exit(0);
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 Geoffrayadfd25c2018-09-14 20:07:30 +0000115 System.exit(0);
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.
Nicolas Geoffray41627362018-09-18 14:48:36 +0100129 if (map.get(new DummyObject(10)) == null) {
130 System.out.println("Expected map to contain DummyObject(10)");
131 }
Mingyao Yangf711f2c2016-05-23 12:29:39 -0700132 } catch (Exception e) {
Kevin Brodskyf6c66c32015-12-17 14:13:00 +0000133 e.printStackTrace(System.out);
Mingyao Yangf711f2c2016-05-23 12:29:39 -0700134 }
135 }
136 });
137
138 undeoptimizeAll(); // Make compiled code useable again.
139
140 if (!DummyObject.sHashCodeInvoked) {
141 System.out.println("hashCode() method not invoked!");
142 }
143 if (map.get(new DummyObject(10)) != 100) {
144 System.out.println("Wrong hashmap value!");
145 }
146 System.out.println("Finishing");
147 }
148
149 public static int $noinline$run1(int[] arr) {
150 assertIsManaged();
151 // Prevent inlining.
152 if (sFlag) {
153 throw new Error();
154 }
155 boolean caught = false;
156 // BCE will use deoptimization for the code below.
157 try {
158 arr[0] = 1;
159 arr[1] = 1;
160 arr[2] = 1;
161 // This causes AIOOBE and triggers deoptimization from compiled code.
162 arr[3] = 1;
163 } catch (ArrayIndexOutOfBoundsException e) {
164 assertIsInterpreted(); // Single-frame deoptimization triggered.
165 caught = true;
166 }
167 if (!caught) {
168 System.out.println("Expected exception");
169 }
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");
Mingyao Yangf711f2c2016-05-23 12:29:39 -0700194 }
195 assertIsInterpreted();
196 return 79.3d;
197 }
198
199 public static float $noinline$run3A() {
200 assertIsManaged();
201 // Prevent inlining.
202 if (sFlag) {
203 throw new Error();
204 }
205 // Deoptimize callers.
206 deoptimizeAll();
207 assertIsInterpreted();
208 assertCallerIsInterpreted(); // $noinline$run3B is deoptimizeable.
209 return 0.034f;
210 }
211
212 public static float $noinline$run3B() {
213 assertIsManaged();
214 // Prevent inlining.
215 if (sFlag) {
216 throw new Error();
217 }
218 float res = $noinline$run3A();
219 assertIsInterpreted();
220 return res;
221 }
222}