blob: d995923f88dc400ce695c213786d47d588aab90b [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.
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!");
139 }
140 if (map.get(new DummyObject(10)) != 100) {
141 System.out.println("Wrong hashmap value!");
142 }
143 System.out.println("Finishing");
144 }
145
146 public static int $noinline$run1(int[] arr) {
147 assertIsManaged();
148 // Prevent inlining.
149 if (sFlag) {
150 throw new Error();
151 }
152 boolean caught = false;
153 // BCE will use deoptimization for the code below.
154 try {
155 arr[0] = 1;
156 arr[1] = 1;
157 arr[2] = 1;
158 // This causes AIOOBE and triggers deoptimization from compiled code.
159 arr[3] = 1;
160 } catch (ArrayIndexOutOfBoundsException e) {
161 assertIsInterpreted(); // Single-frame deoptimization triggered.
162 caught = true;
163 }
164 if (!caught) {
165 System.out.println("Expected exception");
166 }
167 assertIsInterpreted();
168 return 79;
169 }
170
171 public static double $noinline$run2(int[] arr) {
172 assertIsManaged();
173 // Prevent inlining.
174 if (sFlag) {
175 throw new Error();
176 }
177 boolean caught = false;
178 // BCE will use deoptimization for the code below.
179 try {
180 arr[0] = 1;
181 arr[1] = 1;
182 arr[2] = 1;
183 // This causes AIOOBE and triggers deoptimization from compiled code.
184 arr[3] = 1;
185 } catch (ArrayIndexOutOfBoundsException e) {
186 assertIsInterpreted(); // Single-frame deoptimization triggered.
187 caught = true;
188 }
189 if (!caught) {
190 System.out.println("Expected exception");
Mingyao Yangf711f2c2016-05-23 12:29:39 -0700191 }
192 assertIsInterpreted();
193 return 79.3d;
194 }
195
196 public static float $noinline$run3A() {
197 assertIsManaged();
198 // Prevent inlining.
199 if (sFlag) {
200 throw new Error();
201 }
202 // Deoptimize callers.
203 deoptimizeAll();
204 assertIsInterpreted();
205 assertCallerIsInterpreted(); // $noinline$run3B is deoptimizeable.
206 return 0.034f;
207 }
208
209 public static float $noinline$run3B() {
210 assertIsManaged();
211 // Prevent inlining.
212 if (sFlag) {
213 throw new Error();
214 }
215 float res = $noinline$run3A();
216 assertIsInterpreted();
217 return res;
218 }
219}