blob: 6fc12f138ce30a62e59bd4387f4f35d679469dd3 [file] [log] [blame]
Roland Levillain4c0eb422015-04-24 16:43:49 +01001/*
2 * Copyright (C) 2015 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
Vladimir Markoc7591b42016-06-29 14:59:07 +010019 static boolean doThrow = false;
20
Roland Levillain4c0eb422015-04-24 16:43:49 +010021 /*
22 * Ensure an inlined static invoke explicitly triggers the
23 * initialization check of the called method's declaring class, and
24 * that the corresponding load class instruction does not get
25 * removed before register allocation & code generation.
26 */
27
David Brazdila06d66a2015-05-28 11:14:54 +010028 /// CHECK-START: void Main.invokeStaticInlined() builder (after)
29 /// CHECK-DAG: <<LoadClass:l\d+>> LoadClass gen_clinit_check:false
30 /// CHECK-DAG: <<ClinitCheck:l\d+>> ClinitCheck [<<LoadClass>>]
Nicolas Geoffray94015b92015-06-04 18:21:04 +010031 /// CHECK-DAG: InvokeStaticOrDirect [{{[ij]\d+}},<<ClinitCheck>>]
Roland Levillain4c0eb422015-04-24 16:43:49 +010032
David Brazdila06d66a2015-05-28 11:14:54 +010033 /// CHECK-START: void Main.invokeStaticInlined() inliner (after)
34 /// CHECK-DAG: <<LoadClass:l\d+>> LoadClass gen_clinit_check:false
35 /// CHECK-DAG: <<ClinitCheck:l\d+>> ClinitCheck [<<LoadClass>>]
Roland Levillain4c0eb422015-04-24 16:43:49 +010036
David Brazdila06d66a2015-05-28 11:14:54 +010037 /// CHECK-START: void Main.invokeStaticInlined() inliner (after)
38 /// CHECK-NOT: InvokeStaticOrDirect
Roland Levillain4c0eb422015-04-24 16:43:49 +010039
40 // The following checks ensure the clinit check instruction added by
41 // the builder is pruned by the PrepareForRegisterAllocation, while
42 // the load class instruction is preserved. As the control flow
43 // graph is not dumped after (nor before) this step, we check the
44 // CFG as it is before the next pass (liveness analysis) instead.
45
David Brazdila06d66a2015-05-28 11:14:54 +010046 /// CHECK-START: void Main.invokeStaticInlined() liveness (before)
47 /// CHECK-DAG: LoadClass gen_clinit_check:true
Roland Levillain4c0eb422015-04-24 16:43:49 +010048
David Brazdila06d66a2015-05-28 11:14:54 +010049 /// CHECK-START: void Main.invokeStaticInlined() liveness (before)
50 /// CHECK-NOT: ClinitCheck
51 /// CHECK-NOT: InvokeStaticOrDirect
Roland Levillain4c0eb422015-04-24 16:43:49 +010052
53 static void invokeStaticInlined() {
54 ClassWithClinit1.$opt$inline$StaticMethod();
55 }
56
57 static class ClassWithClinit1 {
58 static {
59 System.out.println("Main$ClassWithClinit1's static initializer");
60 }
61
62 static void $opt$inline$StaticMethod() {
63 }
64 }
65
66 /*
67 * Ensure a non-inlined static invoke eventually has an implicit
68 * initialization check of the called method's declaring class.
69 */
70
David Brazdila06d66a2015-05-28 11:14:54 +010071 /// CHECK-START: void Main.invokeStaticNotInlined() builder (after)
Vladimir Markob554b5a2015-11-06 12:57:55 +000072 /// CHECK: <<LoadClass:l\d+>> LoadClass gen_clinit_check:false
73 /// CHECK: <<ClinitCheck:l\d+>> ClinitCheck [<<LoadClass>>]
74 /// CHECK: InvokeStaticOrDirect [{{[ij]\d+}},<<ClinitCheck>>]
Roland Levillain4c0eb422015-04-24 16:43:49 +010075
David Brazdila06d66a2015-05-28 11:14:54 +010076 /// CHECK-START: void Main.invokeStaticNotInlined() inliner (after)
Vladimir Markob554b5a2015-11-06 12:57:55 +000077 /// CHECK: <<LoadClass:l\d+>> LoadClass gen_clinit_check:false
78 /// CHECK: <<ClinitCheck:l\d+>> ClinitCheck [<<LoadClass>>]
79 /// CHECK: InvokeStaticOrDirect [{{([ij]\d+,)?}}<<ClinitCheck>>]
Roland Levillain4c0eb422015-04-24 16:43:49 +010080
81 // The following checks ensure the clinit check and load class
82 // instructions added by the builder are pruned by the
83 // PrepareForRegisterAllocation. As the control flow graph is not
84 // dumped after (nor before) this step, we check the CFG as it is
85 // before the next pass (liveness analysis) instead.
86
David Brazdila06d66a2015-05-28 11:14:54 +010087 /// CHECK-START: void Main.invokeStaticNotInlined() liveness (before)
Vladimir Markofbb184a2015-11-13 14:47:00 +000088 /// CHECK: InvokeStaticOrDirect clinit_check:implicit
Roland Levillain4c0eb422015-04-24 16:43:49 +010089
David Brazdila06d66a2015-05-28 11:14:54 +010090 /// CHECK-START: void Main.invokeStaticNotInlined() liveness (before)
91 /// CHECK-NOT: LoadClass
92 /// CHECK-NOT: ClinitCheck
Roland Levillain4c0eb422015-04-24 16:43:49 +010093
94 static void invokeStaticNotInlined() {
Guillaume "Vermeille" Sancheze918d382015-06-03 15:32:41 +010095 ClassWithClinit2.$noinline$staticMethod();
Roland Levillain4c0eb422015-04-24 16:43:49 +010096 }
97
98 static class ClassWithClinit2 {
99 static {
100 System.out.println("Main$ClassWithClinit2's static initializer");
101 }
102
103 static boolean doThrow = false;
104
Guillaume "Vermeille" Sancheze918d382015-06-03 15:32:41 +0100105 static void $noinline$staticMethod() {
Nicolas Geoffray19dc2552016-07-06 14:01:50 +0000106 if (doThrow) {
107 // Try defeating inlining.
108 throw new Error();
109 }
Roland Levillain4c0eb422015-04-24 16:43:49 +0100110 }
111 }
112
113 /*
114 * Ensure an inlined call to a static method whose declaring class
115 * is statically known to have been initialized does not require an
116 * explicit clinit check.
117 */
118
David Brazdila06d66a2015-05-28 11:14:54 +0100119 /// CHECK-START: void Main$ClassWithClinit3.invokeStaticInlined() builder (after)
120 /// CHECK-DAG: InvokeStaticOrDirect
Roland Levillain4c0eb422015-04-24 16:43:49 +0100121
David Brazdila06d66a2015-05-28 11:14:54 +0100122 /// CHECK-START: void Main$ClassWithClinit3.invokeStaticInlined() builder (after)
123 /// CHECK-NOT: LoadClass
124 /// CHECK-NOT: ClinitCheck
Roland Levillain4c0eb422015-04-24 16:43:49 +0100125
David Brazdila06d66a2015-05-28 11:14:54 +0100126 /// CHECK-START: void Main$ClassWithClinit3.invokeStaticInlined() inliner (after)
127 /// CHECK-NOT: LoadClass
128 /// CHECK-NOT: ClinitCheck
129 /// CHECK-NOT: InvokeStaticOrDirect
Roland Levillain4c0eb422015-04-24 16:43:49 +0100130
131 static class ClassWithClinit3 {
132 static void invokeStaticInlined() {
133 // The invocation of invokeStaticInlined triggers the
134 // initialization of ClassWithClinit3, meaning that the
135 // hereinbelow call to $opt$inline$StaticMethod does not need a
136 // clinit check.
137 $opt$inline$StaticMethod();
138 }
139
140 static {
141 System.out.println("Main$ClassWithClinit3's static initializer");
142 }
143
144 static void $opt$inline$StaticMethod() {
145 }
146 }
147
148 /*
149 * Ensure an non-inlined call to a static method whose declaring
150 * class is statically known to have been initialized does not
151 * require an explicit clinit check.
152 */
153
David Brazdila06d66a2015-05-28 11:14:54 +0100154 /// CHECK-START: void Main$ClassWithClinit4.invokeStaticNotInlined() builder (after)
155 /// CHECK-DAG: InvokeStaticOrDirect
Roland Levillain4c0eb422015-04-24 16:43:49 +0100156
David Brazdila06d66a2015-05-28 11:14:54 +0100157 /// CHECK-START: void Main$ClassWithClinit4.invokeStaticNotInlined() builder (after)
158 /// CHECK-NOT: LoadClass
159 /// CHECK-NOT: ClinitCheck
Roland Levillain4c0eb422015-04-24 16:43:49 +0100160
David Brazdila06d66a2015-05-28 11:14:54 +0100161 /// CHECK-START: void Main$ClassWithClinit4.invokeStaticNotInlined() inliner (after)
162 /// CHECK-DAG: InvokeStaticOrDirect
Roland Levillain4c0eb422015-04-24 16:43:49 +0100163
David Brazdila06d66a2015-05-28 11:14:54 +0100164 /// CHECK-START: void Main$ClassWithClinit4.invokeStaticNotInlined() inliner (after)
165 /// CHECK-NOT: LoadClass
166 /// CHECK-NOT: ClinitCheck
Roland Levillain4c0eb422015-04-24 16:43:49 +0100167
168 static class ClassWithClinit4 {
169 static void invokeStaticNotInlined() {
170 // The invocation of invokeStaticNotInlined triggers the
171 // initialization of ClassWithClinit4, meaning that the
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +0100172 // call to staticMethod below does not need a clinit
Roland Levillain4c0eb422015-04-24 16:43:49 +0100173 // check.
Guillaume "Vermeille" Sancheze918d382015-06-03 15:32:41 +0100174 $noinline$staticMethod();
Roland Levillain4c0eb422015-04-24 16:43:49 +0100175 }
176
177 static {
178 System.out.println("Main$ClassWithClinit4's static initializer");
179 }
180
181 static boolean doThrow = false;
182
Guillaume "Vermeille" Sancheze918d382015-06-03 15:32:41 +0100183 static void $noinline$staticMethod() {
Nicolas Geoffray19dc2552016-07-06 14:01:50 +0000184 if (doThrow) {
Roland Levillain4c0eb422015-04-24 16:43:49 +0100185 // Try defeating inlining.
Nicolas Geoffray19dc2552016-07-06 14:01:50 +0000186 throw new Error();
187 }
Roland Levillain4c0eb422015-04-24 16:43:49 +0100188 }
189 }
190
Roland Levillain5f02c6c2015-04-24 19:14:22 +0100191 /*
192 * Ensure an inlined call to a static method whose declaring class
193 * is a super class of the caller's class does not require an
194 * explicit clinit check.
195 */
196
David Brazdila06d66a2015-05-28 11:14:54 +0100197 /// CHECK-START: void Main$SubClassOfClassWithClinit5.invokeStaticInlined() builder (after)
198 /// CHECK-DAG: InvokeStaticOrDirect
Roland Levillain5f02c6c2015-04-24 19:14:22 +0100199
David Brazdila06d66a2015-05-28 11:14:54 +0100200 /// CHECK-START: void Main$SubClassOfClassWithClinit5.invokeStaticInlined() builder (after)
201 /// CHECK-NOT: LoadClass
202 /// CHECK-NOT: ClinitCheck
Roland Levillain5f02c6c2015-04-24 19:14:22 +0100203
David Brazdila06d66a2015-05-28 11:14:54 +0100204 /// CHECK-START: void Main$SubClassOfClassWithClinit5.invokeStaticInlined() inliner (after)
205 /// CHECK-NOT: LoadClass
206 /// CHECK-NOT: ClinitCheck
207 /// CHECK-NOT: InvokeStaticOrDirect
Roland Levillain5f02c6c2015-04-24 19:14:22 +0100208
209 static class ClassWithClinit5 {
210 static void $opt$inline$StaticMethod() {
211 }
212
213 static {
214 System.out.println("Main$ClassWithClinit5's static initializer");
215 }
216 }
217
218 static class SubClassOfClassWithClinit5 extends ClassWithClinit5 {
219 static void invokeStaticInlined() {
220 ClassWithClinit5.$opt$inline$StaticMethod();
221 }
222 }
223
224 /*
225 * Ensure an non-inlined call to a static method whose declaring
226 * class is a super class of the caller's class does not require an
227 * explicit clinit check.
228 */
229
David Brazdila06d66a2015-05-28 11:14:54 +0100230 /// CHECK-START: void Main$SubClassOfClassWithClinit6.invokeStaticNotInlined() builder (after)
231 /// CHECK-DAG: InvokeStaticOrDirect
Roland Levillain5f02c6c2015-04-24 19:14:22 +0100232
David Brazdila06d66a2015-05-28 11:14:54 +0100233 /// CHECK-START: void Main$SubClassOfClassWithClinit6.invokeStaticNotInlined() builder (after)
234 /// CHECK-NOT: LoadClass
235 /// CHECK-NOT: ClinitCheck
Roland Levillain5f02c6c2015-04-24 19:14:22 +0100236
David Brazdila06d66a2015-05-28 11:14:54 +0100237 /// CHECK-START: void Main$SubClassOfClassWithClinit6.invokeStaticNotInlined() inliner (after)
238 /// CHECK-DAG: InvokeStaticOrDirect
Roland Levillain5f02c6c2015-04-24 19:14:22 +0100239
David Brazdila06d66a2015-05-28 11:14:54 +0100240 /// CHECK-START: void Main$SubClassOfClassWithClinit6.invokeStaticNotInlined() inliner (after)
241 /// CHECK-NOT: LoadClass
242 /// CHECK-NOT: ClinitCheck
Roland Levillain5f02c6c2015-04-24 19:14:22 +0100243
244 static class ClassWithClinit6 {
245 static boolean doThrow = false;
246
Guillaume "Vermeille" Sancheze918d382015-06-03 15:32:41 +0100247 static void $noinline$staticMethod() {
Nicolas Geoffray19dc2552016-07-06 14:01:50 +0000248 if (doThrow) {
Roland Levillain5f02c6c2015-04-24 19:14:22 +0100249 // Try defeating inlining.
Nicolas Geoffray19dc2552016-07-06 14:01:50 +0000250 throw new Error();
251 }
Roland Levillain5f02c6c2015-04-24 19:14:22 +0100252 }
253
254 static {
255 System.out.println("Main$ClassWithClinit6's static initializer");
256 }
257 }
258
259 static class SubClassOfClassWithClinit6 extends ClassWithClinit6 {
260 static void invokeStaticNotInlined() {
Guillaume "Vermeille" Sancheze918d382015-06-03 15:32:41 +0100261 ClassWithClinit6.$noinline$staticMethod();
Roland Levillain5f02c6c2015-04-24 19:14:22 +0100262 }
263 }
264
Calin Juravle0ba218d2015-05-19 18:46:01 +0100265
266 /*
267 * Verify that if we have a static call immediately after the load class
268 * we don't do generate a clinit check.
269 */
270
David Brazdila06d66a2015-05-28 11:14:54 +0100271 /// CHECK-START: void Main.noClinitBecauseOfInvokeStatic() liveness (before)
272 /// CHECK-DAG: <<IntConstant:i\d+>> IntConstant 0
273 /// CHECK-DAG: <<LoadClass:l\d+>> LoadClass gen_clinit_check:false
Vladimir Markofbb184a2015-11-13 14:47:00 +0000274 /// CHECK-DAG: InvokeStaticOrDirect clinit_check:implicit
David Brazdila06d66a2015-05-28 11:14:54 +0100275 /// CHECK-DAG: StaticFieldSet [<<LoadClass>>,<<IntConstant>>]
Calin Juravle0ba218d2015-05-19 18:46:01 +0100276
David Brazdila06d66a2015-05-28 11:14:54 +0100277 /// CHECK-START: void Main.noClinitBecauseOfInvokeStatic() liveness (before)
278 /// CHECK-NOT: ClinitCheck
Calin Juravle0ba218d2015-05-19 18:46:01 +0100279
280 static void noClinitBecauseOfInvokeStatic() {
Guillaume "Vermeille" Sancheze918d382015-06-03 15:32:41 +0100281 ClassWithClinit2.$noinline$staticMethod();
Calin Juravle0ba218d2015-05-19 18:46:01 +0100282 ClassWithClinit2.doThrow = false;
283 }
284
285 /*
286 * Verify that if the static call is after a field access, the load class
287 * will generate a clinit check.
288 */
289
David Brazdila06d66a2015-05-28 11:14:54 +0100290 /// CHECK-START: void Main.clinitBecauseOfFieldAccess() liveness (before)
291 /// CHECK-DAG: <<IntConstant:i\d+>> IntConstant 0
292 /// CHECK-DAG: <<LoadClass:l\d+>> LoadClass gen_clinit_check:true
293 /// CHECK-DAG: StaticFieldSet [<<LoadClass>>,<<IntConstant>>]
Vladimir Markofbb184a2015-11-13 14:47:00 +0000294 /// CHECK-DAG: InvokeStaticOrDirect clinit_check:none
Calin Juravle0ba218d2015-05-19 18:46:01 +0100295
David Brazdila06d66a2015-05-28 11:14:54 +0100296 /// CHECK-START: void Main.clinitBecauseOfFieldAccess() liveness (before)
297 /// CHECK-NOT: ClinitCheck
Calin Juravle0ba218d2015-05-19 18:46:01 +0100298 static void clinitBecauseOfFieldAccess() {
299 ClassWithClinit2.doThrow = false;
Guillaume "Vermeille" Sancheze918d382015-06-03 15:32:41 +0100300 ClassWithClinit2.$noinline$staticMethod();
Calin Juravle0ba218d2015-05-19 18:46:01 +0100301 }
302
Vladimir Markofbb184a2015-11-13 14:47:00 +0000303 /*
304 * Verify that LoadClass from const-class is not merged with
305 * later invoke-static (or it's ClinitCheck).
306 */
307
308 /// CHECK-START: void Main.constClassAndInvokeStatic(java.lang.Iterable) liveness (before)
309 /// CHECK: LoadClass gen_clinit_check:false
310 /// CHECK: InvokeStaticOrDirect clinit_check:implicit
311
312 /// CHECK-START: void Main.constClassAndInvokeStatic(java.lang.Iterable) liveness (before)
313 /// CHECK-NOT: ClinitCheck
314
Vladimir Markoc7591b42016-06-29 14:59:07 +0100315 static void constClassAndInvokeStatic(Iterable<?> it) {
Vladimir Markofbb184a2015-11-13 14:47:00 +0000316 $opt$inline$ignoreClass(ClassWithClinit7.class);
Nicolas Geoffray19dc2552016-07-06 14:01:50 +0000317 ClassWithClinit7.someStaticMethod(it);
Vladimir Markofbb184a2015-11-13 14:47:00 +0000318 }
319
Vladimir Markoc7591b42016-06-29 14:59:07 +0100320 static void $opt$inline$ignoreClass(Class<?> c) {
Vladimir Markofbb184a2015-11-13 14:47:00 +0000321 }
322
323 static class ClassWithClinit7 {
324 static {
325 System.out.println("Main$ClassWithClinit7's static initializer");
326 }
327
Nicolas Geoffray19dc2552016-07-06 14:01:50 +0000328 // Note: not inlined from constClassAndInvokeStatic() but fully inlined from main().
329 static void someStaticMethod(Iterable<?> it) {
330 // We're not inlining invoke-interface at the moment.
Vladimir Markofbb184a2015-11-13 14:47:00 +0000331 it.iterator();
332 }
333 }
334
335 /*
336 * Verify that LoadClass from sget is not merged with later invoke-static.
337 */
338
339 /// CHECK-START: void Main.sgetAndInvokeStatic(java.lang.Iterable) liveness (before)
340 /// CHECK: LoadClass gen_clinit_check:true
341 /// CHECK: InvokeStaticOrDirect clinit_check:none
342
343 /// CHECK-START: void Main.sgetAndInvokeStatic(java.lang.Iterable) liveness (before)
344 /// CHECK-NOT: ClinitCheck
345
Vladimir Markoc7591b42016-06-29 14:59:07 +0100346 static void sgetAndInvokeStatic(Iterable<?> it) {
Vladimir Markofbb184a2015-11-13 14:47:00 +0000347 $opt$inline$ignoreInt(ClassWithClinit8.value);
Nicolas Geoffray19dc2552016-07-06 14:01:50 +0000348 ClassWithClinit8.someStaticMethod(it);
Vladimir Markofbb184a2015-11-13 14:47:00 +0000349 }
350
351 static void $opt$inline$ignoreInt(int i) {
352 }
353
354 static class ClassWithClinit8 {
355 public static int value = 0;
356 static {
357 System.out.println("Main$ClassWithClinit8's static initializer");
358 }
359
Nicolas Geoffray19dc2552016-07-06 14:01:50 +0000360 // Note: not inlined from sgetAndInvokeStatic() but fully inlined from main().
361 static void someStaticMethod(Iterable<?> it) {
362 // We're not inlining invoke-interface at the moment.
Vladimir Markofbb184a2015-11-13 14:47:00 +0000363 it.iterator();
364 }
365 }
366
367 /*
368 * Verify that LoadClass from const-class, ClinitCheck from sget and
369 * InvokeStaticOrDirect from invoke-static are not merged.
370 */
371
372 /// CHECK-START: void Main.constClassSgetAndInvokeStatic(java.lang.Iterable) liveness (before)
373 /// CHECK: LoadClass gen_clinit_check:false
374 /// CHECK: ClinitCheck
375 /// CHECK: InvokeStaticOrDirect clinit_check:none
376
Vladimir Markoc7591b42016-06-29 14:59:07 +0100377 static void constClassSgetAndInvokeStatic(Iterable<?> it) {
Vladimir Markofbb184a2015-11-13 14:47:00 +0000378 $opt$inline$ignoreClass(ClassWithClinit9.class);
379 $opt$inline$ignoreInt(ClassWithClinit9.value);
Nicolas Geoffray19dc2552016-07-06 14:01:50 +0000380 ClassWithClinit9.someStaticMethod(it);
Vladimir Markofbb184a2015-11-13 14:47:00 +0000381 }
382
383 static class ClassWithClinit9 {
384 public static int value = 0;
385 static {
386 System.out.println("Main$ClassWithClinit9's static initializer");
387 }
388
Nicolas Geoffray19dc2552016-07-06 14:01:50 +0000389 // Note: not inlined from constClassSgetAndInvokeStatic() but fully inlined from main().
390 static void someStaticMethod(Iterable<?> it) {
391 // We're not inlining invoke-interface at the moment.
Vladimir Markofbb184a2015-11-13 14:47:00 +0000392 it.iterator();
393 }
394 }
395
396 /*
397 * Verify that LoadClass from a fully-inlined invoke-static is not merged
398 * with InvokeStaticOrDirect from a later invoke-static to the same method.
399 */
400
401 /// CHECK-START: void Main.inlinedInvokeStaticViaNonStatic(java.lang.Iterable) liveness (before)
402 /// CHECK: LoadClass gen_clinit_check:true
403 /// CHECK: InvokeStaticOrDirect clinit_check:none
404
405 /// CHECK-START: void Main.inlinedInvokeStaticViaNonStatic(java.lang.Iterable) liveness (before)
406 /// CHECK-NOT: ClinitCheck
407
Vladimir Markoc7591b42016-06-29 14:59:07 +0100408 static void inlinedInvokeStaticViaNonStatic(Iterable<?> it) {
Vladimir Markofbb184a2015-11-13 14:47:00 +0000409 inlinedInvokeStaticViaNonStaticHelper(null);
410 inlinedInvokeStaticViaNonStaticHelper(it);
411 }
412
Vladimir Markoc7591b42016-06-29 14:59:07 +0100413 static void inlinedInvokeStaticViaNonStaticHelper(Iterable<?> it) {
Vladimir Markofbb184a2015-11-13 14:47:00 +0000414 ClassWithClinit10.inlinedForNull(it);
415 }
416
417 static class ClassWithClinit10 {
418 public static int value = 0;
419 static {
420 System.out.println("Main$ClassWithClinit10's static initializer");
421 }
422
Vladimir Markoc7591b42016-06-29 14:59:07 +0100423 static void inlinedForNull(Iterable<?> it) {
Vladimir Markofbb184a2015-11-13 14:47:00 +0000424 if (it != null) {
Nicolas Geoffray19dc2552016-07-06 14:01:50 +0000425 // We're not inlining invoke-interface at the moment.
Vladimir Markofbb184a2015-11-13 14:47:00 +0000426 it.iterator();
427 }
428 }
429 }
430
431 /*
432 * Check that the LoadClass from an invoke-static C.foo() doesn't get merged with
433 * an invoke-static inside C.foo(). This would mess up the stack walk in the
434 * resolution trampoline where we would have to load C (if C isn't loaded yet)
435 * which is not permitted there.
436 *
437 * Note: In case of failure, we would get an failed assertion during compilation,
438 * so we wouldn't really get to the checker tests below.
439 */
440
441 /// CHECK-START: void Main.inlinedInvokeStaticViaStatic(java.lang.Iterable) liveness (before)
442 /// CHECK: LoadClass gen_clinit_check:true
443 /// CHECK: InvokeStaticOrDirect clinit_check:none
444
445 /// CHECK-START: void Main.inlinedInvokeStaticViaStatic(java.lang.Iterable) liveness (before)
446 /// CHECK-NOT: ClinitCheck
447
Vladimir Markoc7591b42016-06-29 14:59:07 +0100448 static void inlinedInvokeStaticViaStatic(Iterable<?> it) {
Vladimir Markofbb184a2015-11-13 14:47:00 +0000449 ClassWithClinit11.callInlinedForNull(it);
450 }
451
452 static class ClassWithClinit11 {
453 public static int value = 0;
454 static {
455 System.out.println("Main$ClassWithClinit11's static initializer");
456 }
457
Vladimir Markoc7591b42016-06-29 14:59:07 +0100458 static void callInlinedForNull(Iterable<?> it) {
Vladimir Markofbb184a2015-11-13 14:47:00 +0000459 inlinedForNull(it);
460 }
461
Vladimir Markoc7591b42016-06-29 14:59:07 +0100462 static void inlinedForNull(Iterable<?> it) {
Nicolas Geoffray19dc2552016-07-06 14:01:50 +0000463 // We're not inlining invoke-interface at the moment.
Vladimir Markofbb184a2015-11-13 14:47:00 +0000464 it.iterator();
465 }
466 }
467
468 /*
469 * A test similar to inlinedInvokeStaticViaStatic() but doing the indirect invoke
470 * twice with the first one to be fully inlined.
471 */
472
473 /// CHECK-START: void Main.inlinedInvokeStaticViaStaticTwice(java.lang.Iterable) liveness (before)
474 /// CHECK: LoadClass gen_clinit_check:true
475 /// CHECK: InvokeStaticOrDirect clinit_check:none
476
477 /// CHECK-START: void Main.inlinedInvokeStaticViaStaticTwice(java.lang.Iterable) liveness (before)
478 /// CHECK-NOT: ClinitCheck
479
Vladimir Markoc7591b42016-06-29 14:59:07 +0100480 static void inlinedInvokeStaticViaStaticTwice(Iterable<?> it) {
Vladimir Markofbb184a2015-11-13 14:47:00 +0000481 ClassWithClinit12.callInlinedForNull(null);
482 ClassWithClinit12.callInlinedForNull(it);
483 }
484
485 static class ClassWithClinit12 {
486 public static int value = 0;
487 static {
488 System.out.println("Main$ClassWithClinit12's static initializer");
489 }
490
Vladimir Markoc7591b42016-06-29 14:59:07 +0100491 static void callInlinedForNull(Iterable<?> it) {
Vladimir Markofbb184a2015-11-13 14:47:00 +0000492 inlinedForNull(it);
493 }
494
Vladimir Markoc7591b42016-06-29 14:59:07 +0100495 static void inlinedForNull(Iterable<?> it) {
Vladimir Markofbb184a2015-11-13 14:47:00 +0000496 if (it != null) {
Nicolas Geoffray19dc2552016-07-06 14:01:50 +0000497 // We're not inlining invoke-interface at the moment.
498 it.iterator();
Vladimir Markofbb184a2015-11-13 14:47:00 +0000499 }
500 }
501 }
502
Vladimir Markoc7591b42016-06-29 14:59:07 +0100503 static class ClassWithClinit13 {
504 static {
505 System.out.println("Main$ClassWithClinit13's static initializer");
506 }
507
508 public static void $inline$forwardToGetIterator(Iterable<?> it) {
509 $noinline$getIterator(it);
510 }
511
512 public static void $noinline$getIterator(Iterable<?> it) {
Nicolas Geoffray19dc2552016-07-06 14:01:50 +0000513 // We're not inlining invoke-interface at the moment.
Vladimir Markoc7591b42016-06-29 14:59:07 +0100514 it.iterator();
515 }
516 }
517
518 // TODO: Write checker statements.
519 static Object $noinline$testInliningAndNewInstance(Iterable<?> it) {
520 if (doThrow) { throw new Error(); }
521 ClassWithClinit13.$inline$forwardToGetIterator(it);
522 return new ClassWithClinit13();
523 }
524
Roland Levillain4c0eb422015-04-24 16:43:49 +0100525 // TODO: Add a test for the case of a static method whose declaring
526 // class type index is not available (i.e. when `storage_index`
527 // equals `DexFile::kDexNoIndex` in
528 // art::HGraphBuilder::BuildInvoke).
529
530 public static void main(String[] args) {
531 invokeStaticInlined();
532 invokeStaticNotInlined();
533 ClassWithClinit3.invokeStaticInlined();
534 ClassWithClinit4.invokeStaticNotInlined();
Roland Levillain5f02c6c2015-04-24 19:14:22 +0100535 SubClassOfClassWithClinit5.invokeStaticInlined();
536 SubClassOfClassWithClinit6.invokeStaticNotInlined();
Vladimir Markofbb184a2015-11-13 14:47:00 +0000537 Iterable it = new Iterable() { public java.util.Iterator iterator() { return null; } };
538 constClassAndInvokeStatic(it);
539 sgetAndInvokeStatic(it);
540 constClassSgetAndInvokeStatic(it);
541 inlinedInvokeStaticViaNonStatic(it);
542 inlinedInvokeStaticViaStatic(it);
543 inlinedInvokeStaticViaStaticTwice(it);
Vladimir Markoc7591b42016-06-29 14:59:07 +0100544 $noinline$testInliningAndNewInstance(it);
Roland Levillain4c0eb422015-04-24 16:43:49 +0100545 }
546}