blob: 4de563469dc36ac23a1183fffbbbe142c7c0dd9f [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 new SubMain();
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +000021 if ($noinline$returnInt() != 53) {
22 throw new Error("Unexpected return value");
23 }
24 if ($noinline$returnFloat() != 42.2f) {
25 throw new Error("Unexpected return value");
26 }
27 if ($noinline$returnDouble() != Double.longBitsToDouble(0xF000000000001111L)) {
28 throw new Error("Unexpected return value ");
29 }
30 if ($noinline$returnLong() != 0xFFFF000000001111L) {
31 throw new Error("Unexpected return value");
32 }
33
34 try {
35 $noinline$deopt();
36 } catch (Exception e) {}
Nicolas Geoffrayd9994f02016-02-11 17:35:55 +000037 DeoptimizationController.stopDeoptimization();
38
Nicolas Geoffrayd186dd82016-02-16 10:03:44 +000039 $noinline$inlineCache(new Main(), /* isSecondInvocation */ false);
40 if ($noinline$inlineCache(new SubMain(), /* isSecondInvocation */ true) != SubMain.class) {
Nicolas Geoffrayd9994f02016-02-11 17:35:55 +000041 throw new Error("Unexpected return value");
42 }
Nicolas Geoffrayb88d59e2016-02-17 11:31:49 +000043
Nicolas Geoffray93a18c52016-04-22 13:16:14 +010044 $noinline$inlineCache2(new Main(), /* isSecondInvocation */ false);
45 if ($noinline$inlineCache2(new SubMain(), /* isSecondInvocation */ true) != SubMain.class) {
46 throw new Error("Unexpected return value");
47 }
48
49 // Test polymorphic inline cache to the same target (inlineCache3).
50 $noinline$inlineCache3(new Main(), /* isSecondInvocation */ false);
51 $noinline$inlineCache3(new SubMain(), /* isSecondInvocation */ false);
52 if ($noinline$inlineCache3(new SubMain(), /* isSecondInvocation */ true) != null) {
53 throw new Error("Unexpected return value");
54 }
55
Nicolas Geoffrayb88d59e2016-02-17 11:31:49 +000056 $noinline$stackOverflow(new Main(), /* isSecondInvocation */ false);
57 $noinline$stackOverflow(new SubMain(), /* isSecondInvocation */ true);
Vladimir Markofd66c502016-04-18 15:37:01 +010058
59 $opt$noinline$testOsrInlineLoop(null);
60 System.out.println("b28210356 passed.");
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +000061 }
62
63 public static int $noinline$returnInt() {
64 if (doThrow) throw new Error("");
65 int i = 0;
Nicolas Geoffray17fccfb2016-02-12 16:52:16 +000066 for (; i < 100000; ++i) {
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +000067 }
Vladimir Markofd66c502016-04-18 15:37:01 +010068 while (!isInOsrCode("$noinline$returnInt")) {}
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +000069 System.out.println(i);
70 return 53;
71 }
72
73 public static float $noinline$returnFloat() {
74 if (doThrow) throw new Error("");
75 int i = 0;
Nicolas Geoffray17fccfb2016-02-12 16:52:16 +000076 for (; i < 200000; ++i) {
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +000077 }
Vladimir Markofd66c502016-04-18 15:37:01 +010078 while (!isInOsrCode("$noinline$returnFloat")) {}
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +000079 System.out.println(i);
80 return 42.2f;
81 }
82
83 public static double $noinline$returnDouble() {
84 if (doThrow) throw new Error("");
85 int i = 0;
Nicolas Geoffray17fccfb2016-02-12 16:52:16 +000086 for (; i < 300000; ++i) {
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +000087 }
Vladimir Markofd66c502016-04-18 15:37:01 +010088 while (!isInOsrCode("$noinline$returnDouble")) {}
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +000089 System.out.println(i);
90 return Double.longBitsToDouble(0xF000000000001111L);
91 }
92
93 public static long $noinline$returnLong() {
94 if (doThrow) throw new Error("");
Nicolas Geoffray17fccfb2016-02-12 16:52:16 +000095 int i = 0;
96 for (; i < 400000; ++i) {
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +000097 }
Vladimir Markofd66c502016-04-18 15:37:01 +010098 while (!isInOsrCode("$noinline$returnLong")) {}
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +000099 System.out.println(i);
100 return 0xFFFF000000001111L;
101 }
102
103 public static void $noinline$deopt() {
104 if (doThrow) throw new Error("");
105 int i = 0;
Nicolas Geoffray17fccfb2016-02-12 16:52:16 +0000106 for (; i < 100000; ++i) {
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +0000107 }
Vladimir Markofd66c502016-04-18 15:37:01 +0100108 while (!isInOsrCode("$noinline$deopt")) {}
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +0000109 DeoptimizationController.startDeoptimization();
110 }
111
Andreas Gampe166aaee2016-07-18 08:27:23 -0700112 public static Class<?> $noinline$inlineCache(Main m, boolean isSecondInvocation) {
Nicolas Geoffrayd186dd82016-02-16 10:03:44 +0000113 // If we are running in non-JIT mode, or were unlucky enough to get this method
114 // already JITted, just return the expected value.
Vladimir Markofd66c502016-04-18 15:37:01 +0100115 if (!isInInterpreter("$noinline$inlineCache")) {
Nicolas Geoffrayd186dd82016-02-16 10:03:44 +0000116 return SubMain.class;
Nicolas Geoffrayd9994f02016-02-11 17:35:55 +0000117 }
Nicolas Geoffrayd186dd82016-02-16 10:03:44 +0000118
Vladimir Markob9d338b2016-04-19 17:26:54 +0100119 ensureHasProfilingInfo("$noinline$inlineCache");
Nicolas Geoffrayd186dd82016-02-16 10:03:44 +0000120
121 // Ensure that we have OSR code to jump to.
122 if (isSecondInvocation) {
Vladimir Markofd66c502016-04-18 15:37:01 +0100123 ensureHasOsrCode("$noinline$inlineCache");
Nicolas Geoffrayd9994f02016-02-11 17:35:55 +0000124 }
125
126 // This call will be optimized in the OSR compiled code
127 // to check and deoptimize if m is not of type 'Main'.
128 Main other = m.inlineCache();
129
Nicolas Geoffrayd186dd82016-02-16 10:03:44 +0000130 // Jump to OSR compiled code. The second run
131 // of this method will have 'm' as a SubMain, and the compiled
132 // code we are jumping to will have wrongly optimize other as being a
133 // 'Main'.
134 if (isSecondInvocation) {
Vladimir Markofd66c502016-04-18 15:37:01 +0100135 while (!isInOsrCode("$noinline$inlineCache")) {}
Nicolas Geoffrayd9994f02016-02-11 17:35:55 +0000136 }
137
138 // We used to wrongly optimize this call and assume 'other' was a 'Main'.
139 return other.returnClass();
140 }
141
Andreas Gampe166aaee2016-07-18 08:27:23 -0700142 public static Class<?> $noinline$inlineCache2(Main m, boolean isSecondInvocation) {
Nicolas Geoffray93a18c52016-04-22 13:16:14 +0100143 // If we are running in non-JIT mode, or were unlucky enough to get this method
144 // already JITted, just return the expected value.
145 if (!isInInterpreter("$noinline$inlineCache2")) {
146 return SubMain.class;
147 }
148
149 ensureHasProfilingInfo("$noinline$inlineCache2");
150
151 // Ensure that we have OSR code to jump to.
152 if (isSecondInvocation) {
153 ensureHasOsrCode("$noinline$inlineCache2");
154 }
155
156 // This call will be optimized in the OSR compiled code
157 // to check and deoptimize if m is not of type 'Main'.
158 Main other = m.inlineCache2();
159
160 // Jump to OSR compiled code. The second run
161 // of this method will have 'm' as a SubMain, and the compiled
162 // code we are jumping to will have wrongly optimize other as being null.
163 if (isSecondInvocation) {
164 while (!isInOsrCode("$noinline$inlineCache2")) {}
165 }
166
167 // We used to wrongly optimize this code and assume 'other' was always null.
168 return (other == null) ? null : other.returnClass();
169 }
170
Andreas Gampe166aaee2016-07-18 08:27:23 -0700171 public static Class<?> $noinline$inlineCache3(Main m, boolean isSecondInvocation) {
Nicolas Geoffray93a18c52016-04-22 13:16:14 +0100172 // If we are running in non-JIT mode, or were unlucky enough to get this method
173 // already JITted, just return the expected value.
174 if (!isInInterpreter("$noinline$inlineCache3")) {
Nicolas Geoffraya4a640e2016-04-27 13:43:48 +0100175 return null;
Nicolas Geoffray93a18c52016-04-22 13:16:14 +0100176 }
177
178 ensureHasProfilingInfo("$noinline$inlineCache3");
179
180 // Ensure that we have OSR code to jump to.
181 if (isSecondInvocation) {
182 ensureHasOsrCode("$noinline$inlineCache3");
183 }
184
185 // This call will be optimized in the OSR compiled code
186 // to check and deoptimize if m is not of type 'Main'.
187 Main other = m.inlineCache3();
188
189 // Jump to OSR compiled code. The second run
190 // of this method will have 'm' as a SubMain, and the compiled
191 // code we are jumping to will have wrongly optimize other as being null.
192 if (isSecondInvocation) {
193 while (!isInOsrCode("$noinline$inlineCache3")) {}
194 }
195
196 // We used to wrongly optimize this code and assume 'other' was always null.
197 return (other == null) ? null : other.returnClass();
198 }
199
Nicolas Geoffrayd9994f02016-02-11 17:35:55 +0000200 public Main inlineCache() {
201 return new Main();
202 }
203
Nicolas Geoffray93a18c52016-04-22 13:16:14 +0100204 public Main inlineCache2() {
205 return null;
206 }
207
208 public Main inlineCache3() {
209 return null;
210 }
211
Andreas Gampe166aaee2016-07-18 08:27:23 -0700212 public Class<?> returnClass() {
Nicolas Geoffrayd9994f02016-02-11 17:35:55 +0000213 return Main.class;
214 }
215
Nicolas Geoffrayb88d59e2016-02-17 11:31:49 +0000216 public void otherInlineCache() {
217 return;
218 }
219
220 public static void $noinline$stackOverflow(Main m, boolean isSecondInvocation) {
221 // If we are running in non-JIT mode, or were unlucky enough to get this method
222 // already JITted, just return the expected value.
Vladimir Markofd66c502016-04-18 15:37:01 +0100223 if (!isInInterpreter("$noinline$stackOverflow")) {
Nicolas Geoffrayb88d59e2016-02-17 11:31:49 +0000224 return;
225 }
226
227 // We need a ProfilingInfo object to populate the 'otherInlineCache' call.
Vladimir Markob9d338b2016-04-19 17:26:54 +0100228 ensureHasProfilingInfo("$noinline$stackOverflow");
Nicolas Geoffrayb88d59e2016-02-17 11:31:49 +0000229
230 if (isSecondInvocation) {
231 // Ensure we have an OSR code and we jump to it.
Vladimir Markofd66c502016-04-18 15:37:01 +0100232 while (!isInOsrCode("$noinline$stackOverflow")) {}
Nicolas Geoffrayb88d59e2016-02-17 11:31:49 +0000233 }
234
235 for (int i = 0; i < (isSecondInvocation ? 10000000 : 1); ++i) {
236 // The first invocation of $noinline$stackOverflow will populate the inline
237 // cache with Main. The second invocation of the method, will see a SubMain
238 // and will therefore trigger deoptimization.
239 m.otherInlineCache();
240 }
241 }
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +0000242
Vladimir Markofd66c502016-04-18 15:37:01 +0100243 public static void $opt$noinline$testOsrInlineLoop(String[] args) {
244 // Regression test for inlining a method with a loop to a method without a loop in OSR mode.
245 if (doThrow) throw new Error();
246 assertIntEquals(12, $opt$inline$testRemoveSuspendCheck(12, 5));
247 // Since we cannot have a loop directly in this method, we need to force the OSR
248 // compilation from native code.
Vladimir Markob9d338b2016-04-19 17:26:54 +0100249 ensureHasProfilingInfo("$opt$noinline$testOsrInlineLoop");
Vladimir Markofd66c502016-04-18 15:37:01 +0100250 ensureHasOsrCode("$opt$noinline$testOsrInlineLoop");
251 }
252
253 public static int $opt$inline$testRemoveSuspendCheck(int x, int y) {
254 // For this test we need an inlined loop and have DCE re-run loop analysis
255 // after inlining.
256 while (y > 0) {
257 while ($opt$inline$inlineFalse() || !$opt$inline$inlineTrue()) {
258 x++;
259 }
260 y--;
261 }
262 return x;
263 }
264
265 public static boolean $opt$inline$inlineTrue() {
266 return true;
267 }
268
269 public static boolean $opt$inline$inlineFalse() {
270 return false;
271 }
272
273 public static void assertIntEquals(int expected, int result) {
274 if (expected != result) {
275 throw new Error("Expected: " + expected + ", found: " + result);
276 }
277 }
278
279 public static native boolean isInOsrCode(String methodName);
280 public static native boolean isInInterpreter(String methodName);
Vladimir Markob9d338b2016-04-19 17:26:54 +0100281 public static native void ensureHasProfilingInfo(String methodName);
Vladimir Markofd66c502016-04-18 15:37:01 +0100282 public static native void ensureHasOsrCode(String methodName);
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +0000283
284 public static boolean doThrow = false;
285}
Nicolas Geoffrayd9994f02016-02-11 17:35:55 +0000286
287class SubMain extends Main {
Andreas Gampe166aaee2016-07-18 08:27:23 -0700288 public Class<?> returnClass() {
Nicolas Geoffrayd9994f02016-02-11 17:35:55 +0000289 return SubMain.class;
290 }
291
292 public Main inlineCache() {
293 return new SubMain();
294 }
Nicolas Geoffrayb88d59e2016-02-17 11:31:49 +0000295
Nicolas Geoffray93a18c52016-04-22 13:16:14 +0100296 public Main inlineCache2() {
297 return new SubMain();
298 }
299
Nicolas Geoffrayb88d59e2016-02-17 11:31:49 +0000300 public void otherInlineCache() {
301 return;
302 }
Nicolas Geoffrayd9994f02016-02-11 17:35:55 +0000303}