blob: 11a6fd43f30d19fab6f680f6d26a434a0b8685a4 [file] [log] [blame]
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +00001/*
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
17public class Main {
18 public static void main(String[] args) {
19 System.loadLibrary(args[0]);
Vladimir Marko1939a882016-04-07 10:12:31 +010020 Thread testThread = new Thread() {
21 public void run() {
22 performTest();
23 }
24 };
25 testThread.start();
26 try {
Vladimir Marko732350b2016-04-20 09:06:08 +000027 testThread.join(20 * 1000); // 20s timeout.
Vladimir Marko1939a882016-04-07 10:12:31 +010028 } catch (InterruptedException ie) {
29 System.out.println("Interrupted.");
30 System.exit(1);
31 }
32 Thread.State state = testThread.getState();
33 if (state != Thread.State.TERMINATED) {
34 System.out.println("Test timed out, current state: " + state);
35 System.exit(1);
36 }
37 }
38
39 public static void performTest() {
40 new SubMain();
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +000041 if ($noinline$returnInt() != 53) {
42 throw new Error("Unexpected return value");
43 }
44 if ($noinline$returnFloat() != 42.2f) {
45 throw new Error("Unexpected return value");
46 }
47 if ($noinline$returnDouble() != Double.longBitsToDouble(0xF000000000001111L)) {
48 throw new Error("Unexpected return value ");
49 }
50 if ($noinline$returnLong() != 0xFFFF000000001111L) {
51 throw new Error("Unexpected return value");
52 }
53
54 try {
55 $noinline$deopt();
56 } catch (Exception e) {}
Nicolas Geoffrayd9994f02016-02-11 17:35:55 +000057 DeoptimizationController.stopDeoptimization();
58
Nicolas Geoffrayd186dd82016-02-16 10:03:44 +000059 $noinline$inlineCache(new Main(), /* isSecondInvocation */ false);
60 if ($noinline$inlineCache(new SubMain(), /* isSecondInvocation */ true) != SubMain.class) {
Nicolas Geoffrayd9994f02016-02-11 17:35:55 +000061 throw new Error("Unexpected return value");
62 }
Nicolas Geoffrayb88d59e2016-02-17 11:31:49 +000063
Nicolas Geoffray93a18c52016-04-22 13:16:14 +010064 $noinline$inlineCache2(new Main(), /* isSecondInvocation */ false);
65 if ($noinline$inlineCache2(new SubMain(), /* isSecondInvocation */ true) != SubMain.class) {
66 throw new Error("Unexpected return value");
67 }
68
69 // Test polymorphic inline cache to the same target (inlineCache3).
70 $noinline$inlineCache3(new Main(), /* isSecondInvocation */ false);
71 $noinline$inlineCache3(new SubMain(), /* isSecondInvocation */ false);
72 if ($noinline$inlineCache3(new SubMain(), /* isSecondInvocation */ true) != null) {
73 throw new Error("Unexpected return value");
74 }
75
Nicolas Geoffrayb88d59e2016-02-17 11:31:49 +000076 $noinline$stackOverflow(new Main(), /* isSecondInvocation */ false);
77 $noinline$stackOverflow(new SubMain(), /* isSecondInvocation */ true);
Vladimir Markofd66c502016-04-18 15:37:01 +010078
79 $opt$noinline$testOsrInlineLoop(null);
80 System.out.println("b28210356 passed.");
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +000081 }
82
83 public static int $noinline$returnInt() {
84 if (doThrow) throw new Error("");
85 int i = 0;
Nicolas Geoffray17fccfb2016-02-12 16:52:16 +000086 for (; i < 100000; ++i) {
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +000087 }
Vladimir Markofd66c502016-04-18 15:37:01 +010088 while (!isInOsrCode("$noinline$returnInt")) {}
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +000089 System.out.println(i);
90 return 53;
91 }
92
93 public static float $noinline$returnFloat() {
94 if (doThrow) throw new Error("");
95 int i = 0;
Nicolas Geoffray17fccfb2016-02-12 16:52:16 +000096 for (; i < 200000; ++i) {
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +000097 }
Vladimir Markofd66c502016-04-18 15:37:01 +010098 while (!isInOsrCode("$noinline$returnFloat")) {}
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +000099 System.out.println(i);
100 return 42.2f;
101 }
102
103 public static double $noinline$returnDouble() {
104 if (doThrow) throw new Error("");
105 int i = 0;
Nicolas Geoffray17fccfb2016-02-12 16:52:16 +0000106 for (; i < 300000; ++i) {
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +0000107 }
Vladimir Markofd66c502016-04-18 15:37:01 +0100108 while (!isInOsrCode("$noinline$returnDouble")) {}
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +0000109 System.out.println(i);
110 return Double.longBitsToDouble(0xF000000000001111L);
111 }
112
113 public static long $noinline$returnLong() {
114 if (doThrow) throw new Error("");
Nicolas Geoffray17fccfb2016-02-12 16:52:16 +0000115 int i = 0;
116 for (; i < 400000; ++i) {
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +0000117 }
Vladimir Markofd66c502016-04-18 15:37:01 +0100118 while (!isInOsrCode("$noinline$returnLong")) {}
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +0000119 System.out.println(i);
120 return 0xFFFF000000001111L;
121 }
122
123 public static void $noinline$deopt() {
124 if (doThrow) throw new Error("");
125 int i = 0;
Nicolas Geoffray17fccfb2016-02-12 16:52:16 +0000126 for (; i < 100000; ++i) {
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +0000127 }
Vladimir Markofd66c502016-04-18 15:37:01 +0100128 while (!isInOsrCode("$noinline$deopt")) {}
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +0000129 DeoptimizationController.startDeoptimization();
130 }
131
Nicolas Geoffrayd186dd82016-02-16 10:03:44 +0000132 public static Class $noinline$inlineCache(Main m, boolean isSecondInvocation) {
133 // If we are running in non-JIT mode, or were unlucky enough to get this method
134 // already JITted, just return the expected value.
Vladimir Markofd66c502016-04-18 15:37:01 +0100135 if (!isInInterpreter("$noinline$inlineCache")) {
Nicolas Geoffrayd186dd82016-02-16 10:03:44 +0000136 return SubMain.class;
Nicolas Geoffrayd9994f02016-02-11 17:35:55 +0000137 }
Nicolas Geoffrayd186dd82016-02-16 10:03:44 +0000138
Vladimir Markob9d338b2016-04-19 17:26:54 +0100139 ensureHasProfilingInfo("$noinline$inlineCache");
Nicolas Geoffrayd186dd82016-02-16 10:03:44 +0000140
141 // Ensure that we have OSR code to jump to.
142 if (isSecondInvocation) {
Vladimir Markofd66c502016-04-18 15:37:01 +0100143 ensureHasOsrCode("$noinline$inlineCache");
Nicolas Geoffrayd9994f02016-02-11 17:35:55 +0000144 }
145
146 // This call will be optimized in the OSR compiled code
147 // to check and deoptimize if m is not of type 'Main'.
148 Main other = m.inlineCache();
149
Nicolas Geoffrayd186dd82016-02-16 10:03:44 +0000150 // Jump to OSR compiled code. The second run
151 // of this method will have 'm' as a SubMain, and the compiled
152 // code we are jumping to will have wrongly optimize other as being a
153 // 'Main'.
154 if (isSecondInvocation) {
Vladimir Markofd66c502016-04-18 15:37:01 +0100155 while (!isInOsrCode("$noinline$inlineCache")) {}
Nicolas Geoffrayd9994f02016-02-11 17:35:55 +0000156 }
157
158 // We used to wrongly optimize this call and assume 'other' was a 'Main'.
159 return other.returnClass();
160 }
161
Nicolas Geoffray93a18c52016-04-22 13:16:14 +0100162 public static Class $noinline$inlineCache2(Main m, boolean isSecondInvocation) {
163 // If we are running in non-JIT mode, or were unlucky enough to get this method
164 // already JITted, just return the expected value.
165 if (!isInInterpreter("$noinline$inlineCache2")) {
166 return SubMain.class;
167 }
168
169 ensureHasProfilingInfo("$noinline$inlineCache2");
170
171 // Ensure that we have OSR code to jump to.
172 if (isSecondInvocation) {
173 ensureHasOsrCode("$noinline$inlineCache2");
174 }
175
176 // This call will be optimized in the OSR compiled code
177 // to check and deoptimize if m is not of type 'Main'.
178 Main other = m.inlineCache2();
179
180 // Jump to OSR compiled code. The second run
181 // of this method will have 'm' as a SubMain, and the compiled
182 // code we are jumping to will have wrongly optimize other as being null.
183 if (isSecondInvocation) {
184 while (!isInOsrCode("$noinline$inlineCache2")) {}
185 }
186
187 // We used to wrongly optimize this code and assume 'other' was always null.
188 return (other == null) ? null : other.returnClass();
189 }
190
191 public static Class $noinline$inlineCache3(Main m, boolean isSecondInvocation) {
192 // If we are running in non-JIT mode, or were unlucky enough to get this method
193 // already JITted, just return the expected value.
194 if (!isInInterpreter("$noinline$inlineCache3")) {
195 return SubMain.class;
196 }
197
198 ensureHasProfilingInfo("$noinline$inlineCache3");
199
200 // Ensure that we have OSR code to jump to.
201 if (isSecondInvocation) {
202 ensureHasOsrCode("$noinline$inlineCache3");
203 }
204
205 // This call will be optimized in the OSR compiled code
206 // to check and deoptimize if m is not of type 'Main'.
207 Main other = m.inlineCache3();
208
209 // Jump to OSR compiled code. The second run
210 // of this method will have 'm' as a SubMain, and the compiled
211 // code we are jumping to will have wrongly optimize other as being null.
212 if (isSecondInvocation) {
213 while (!isInOsrCode("$noinline$inlineCache3")) {}
214 }
215
216 // We used to wrongly optimize this code and assume 'other' was always null.
217 return (other == null) ? null : other.returnClass();
218 }
219
Nicolas Geoffrayd9994f02016-02-11 17:35:55 +0000220 public Main inlineCache() {
221 return new Main();
222 }
223
Nicolas Geoffray93a18c52016-04-22 13:16:14 +0100224 public Main inlineCache2() {
225 return null;
226 }
227
228 public Main inlineCache3() {
229 return null;
230 }
231
Nicolas Geoffrayd9994f02016-02-11 17:35:55 +0000232 public Class returnClass() {
233 return Main.class;
234 }
235
Nicolas Geoffrayb88d59e2016-02-17 11:31:49 +0000236 public void otherInlineCache() {
237 return;
238 }
239
240 public static void $noinline$stackOverflow(Main m, boolean isSecondInvocation) {
241 // If we are running in non-JIT mode, or were unlucky enough to get this method
242 // already JITted, just return the expected value.
Vladimir Markofd66c502016-04-18 15:37:01 +0100243 if (!isInInterpreter("$noinline$stackOverflow")) {
Nicolas Geoffrayb88d59e2016-02-17 11:31:49 +0000244 return;
245 }
246
247 // We need a ProfilingInfo object to populate the 'otherInlineCache' call.
Vladimir Markob9d338b2016-04-19 17:26:54 +0100248 ensureHasProfilingInfo("$noinline$stackOverflow");
Nicolas Geoffrayb88d59e2016-02-17 11:31:49 +0000249
250 if (isSecondInvocation) {
251 // Ensure we have an OSR code and we jump to it.
Vladimir Markofd66c502016-04-18 15:37:01 +0100252 while (!isInOsrCode("$noinline$stackOverflow")) {}
Nicolas Geoffrayb88d59e2016-02-17 11:31:49 +0000253 }
254
255 for (int i = 0; i < (isSecondInvocation ? 10000000 : 1); ++i) {
256 // The first invocation of $noinline$stackOverflow will populate the inline
257 // cache with Main. The second invocation of the method, will see a SubMain
258 // and will therefore trigger deoptimization.
259 m.otherInlineCache();
260 }
261 }
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +0000262
Vladimir Markofd66c502016-04-18 15:37:01 +0100263 public static void $opt$noinline$testOsrInlineLoop(String[] args) {
264 // Regression test for inlining a method with a loop to a method without a loop in OSR mode.
265 if (doThrow) throw new Error();
266 assertIntEquals(12, $opt$inline$testRemoveSuspendCheck(12, 5));
267 // Since we cannot have a loop directly in this method, we need to force the OSR
268 // compilation from native code.
Vladimir Markob9d338b2016-04-19 17:26:54 +0100269 ensureHasProfilingInfo("$opt$noinline$testOsrInlineLoop");
Vladimir Markofd66c502016-04-18 15:37:01 +0100270 ensureHasOsrCode("$opt$noinline$testOsrInlineLoop");
271 }
272
273 public static int $opt$inline$testRemoveSuspendCheck(int x, int y) {
274 // For this test we need an inlined loop and have DCE re-run loop analysis
275 // after inlining.
276 while (y > 0) {
277 while ($opt$inline$inlineFalse() || !$opt$inline$inlineTrue()) {
278 x++;
279 }
280 y--;
281 }
282 return x;
283 }
284
285 public static boolean $opt$inline$inlineTrue() {
286 return true;
287 }
288
289 public static boolean $opt$inline$inlineFalse() {
290 return false;
291 }
292
293 public static void assertIntEquals(int expected, int result) {
294 if (expected != result) {
295 throw new Error("Expected: " + expected + ", found: " + result);
296 }
297 }
298
299 public static native boolean isInOsrCode(String methodName);
300 public static native boolean isInInterpreter(String methodName);
Vladimir Markob9d338b2016-04-19 17:26:54 +0100301 public static native void ensureHasProfilingInfo(String methodName);
Vladimir Markofd66c502016-04-18 15:37:01 +0100302 public static native void ensureHasOsrCode(String methodName);
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +0000303
304 public static boolean doThrow = false;
305}
Nicolas Geoffrayd9994f02016-02-11 17:35:55 +0000306
307class SubMain extends Main {
308 public Class returnClass() {
309 return SubMain.class;
310 }
311
312 public Main inlineCache() {
313 return new SubMain();
314 }
Nicolas Geoffrayb88d59e2016-02-17 11:31:49 +0000315
Nicolas Geoffray93a18c52016-04-22 13:16:14 +0100316 public Main inlineCache2() {
317 return new SubMain();
318 }
319
Nicolas Geoffrayb88d59e2016-02-17 11:31:49 +0000320 public void otherInlineCache() {
321 return;
322 }
Nicolas Geoffrayd9994f02016-02-11 17:35:55 +0000323}