blob: c2982b48dbd07953bf1dd55bc605519d9392a079 [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 Geoffray5bf7bac2016-07-06 14:18:23 +0000106 // Try defeating inlining.
107 if (doThrow) { throw new Error(); }
Roland Levillain4c0eb422015-04-24 16:43:49 +0100108 }
109 }
110
111 /*
112 * Ensure an inlined call to a static method whose declaring class
113 * is statically known to have been initialized does not require an
114 * explicit clinit check.
115 */
116
David Brazdila06d66a2015-05-28 11:14:54 +0100117 /// CHECK-START: void Main$ClassWithClinit3.invokeStaticInlined() builder (after)
118 /// CHECK-DAG: InvokeStaticOrDirect
Roland Levillain4c0eb422015-04-24 16:43:49 +0100119
David Brazdila06d66a2015-05-28 11:14:54 +0100120 /// CHECK-START: void Main$ClassWithClinit3.invokeStaticInlined() builder (after)
121 /// CHECK-NOT: LoadClass
122 /// CHECK-NOT: ClinitCheck
Roland Levillain4c0eb422015-04-24 16:43:49 +0100123
David Brazdila06d66a2015-05-28 11:14:54 +0100124 /// CHECK-START: void Main$ClassWithClinit3.invokeStaticInlined() inliner (after)
125 /// CHECK-NOT: LoadClass
126 /// CHECK-NOT: ClinitCheck
127 /// CHECK-NOT: InvokeStaticOrDirect
Roland Levillain4c0eb422015-04-24 16:43:49 +0100128
129 static class ClassWithClinit3 {
130 static void invokeStaticInlined() {
131 // The invocation of invokeStaticInlined triggers the
132 // initialization of ClassWithClinit3, meaning that the
133 // hereinbelow call to $opt$inline$StaticMethod does not need a
134 // clinit check.
135 $opt$inline$StaticMethod();
136 }
137
138 static {
139 System.out.println("Main$ClassWithClinit3's static initializer");
140 }
141
142 static void $opt$inline$StaticMethod() {
143 }
144 }
145
146 /*
147 * Ensure an non-inlined call to a static method whose declaring
148 * class is statically known to have been initialized does not
149 * require an explicit clinit check.
150 */
151
David Brazdila06d66a2015-05-28 11:14:54 +0100152 /// CHECK-START: void Main$ClassWithClinit4.invokeStaticNotInlined() builder (after)
153 /// CHECK-DAG: InvokeStaticOrDirect
Roland Levillain4c0eb422015-04-24 16:43:49 +0100154
David Brazdila06d66a2015-05-28 11:14:54 +0100155 /// CHECK-START: void Main$ClassWithClinit4.invokeStaticNotInlined() builder (after)
156 /// CHECK-NOT: LoadClass
157 /// CHECK-NOT: ClinitCheck
Roland Levillain4c0eb422015-04-24 16:43:49 +0100158
David Brazdila06d66a2015-05-28 11:14:54 +0100159 /// CHECK-START: void Main$ClassWithClinit4.invokeStaticNotInlined() inliner (after)
160 /// CHECK-DAG: InvokeStaticOrDirect
Roland Levillain4c0eb422015-04-24 16:43:49 +0100161
David Brazdila06d66a2015-05-28 11:14:54 +0100162 /// CHECK-START: void Main$ClassWithClinit4.invokeStaticNotInlined() inliner (after)
163 /// CHECK-NOT: LoadClass
164 /// CHECK-NOT: ClinitCheck
Roland Levillain4c0eb422015-04-24 16:43:49 +0100165
166 static class ClassWithClinit4 {
167 static void invokeStaticNotInlined() {
168 // The invocation of invokeStaticNotInlined triggers the
169 // initialization of ClassWithClinit4, meaning that the
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +0100170 // call to staticMethod below does not need a clinit
Roland Levillain4c0eb422015-04-24 16:43:49 +0100171 // check.
Guillaume "Vermeille" Sancheze918d382015-06-03 15:32:41 +0100172 $noinline$staticMethod();
Roland Levillain4c0eb422015-04-24 16:43:49 +0100173 }
174
175 static {
176 System.out.println("Main$ClassWithClinit4's static initializer");
177 }
178
179 static boolean doThrow = false;
180
Guillaume "Vermeille" Sancheze918d382015-06-03 15:32:41 +0100181 static void $noinline$staticMethod() {
Roland Levillain4c0eb422015-04-24 16:43:49 +0100182 // Try defeating inlining.
Nicolas Geoffray5bf7bac2016-07-06 14:18:23 +0000183 if (doThrow) { throw new Error(); }
Roland Levillain4c0eb422015-04-24 16:43:49 +0100184 }
185 }
186
Roland Levillain5f02c6c2015-04-24 19:14:22 +0100187 /*
188 * Ensure an inlined call to a static method whose declaring class
189 * is a super class of the caller's class does not require an
190 * explicit clinit check.
191 */
192
David Brazdila06d66a2015-05-28 11:14:54 +0100193 /// CHECK-START: void Main$SubClassOfClassWithClinit5.invokeStaticInlined() builder (after)
194 /// CHECK-DAG: InvokeStaticOrDirect
Roland Levillain5f02c6c2015-04-24 19:14:22 +0100195
David Brazdila06d66a2015-05-28 11:14:54 +0100196 /// CHECK-START: void Main$SubClassOfClassWithClinit5.invokeStaticInlined() builder (after)
197 /// CHECK-NOT: LoadClass
198 /// CHECK-NOT: ClinitCheck
Roland Levillain5f02c6c2015-04-24 19:14:22 +0100199
David Brazdila06d66a2015-05-28 11:14:54 +0100200 /// CHECK-START: void Main$SubClassOfClassWithClinit5.invokeStaticInlined() inliner (after)
201 /// CHECK-NOT: LoadClass
202 /// CHECK-NOT: ClinitCheck
203 /// CHECK-NOT: InvokeStaticOrDirect
Roland Levillain5f02c6c2015-04-24 19:14:22 +0100204
205 static class ClassWithClinit5 {
206 static void $opt$inline$StaticMethod() {
207 }
208
209 static {
210 System.out.println("Main$ClassWithClinit5's static initializer");
211 }
212 }
213
214 static class SubClassOfClassWithClinit5 extends ClassWithClinit5 {
215 static void invokeStaticInlined() {
216 ClassWithClinit5.$opt$inline$StaticMethod();
217 }
218 }
219
220 /*
221 * Ensure an non-inlined call to a static method whose declaring
222 * class is a super class of the caller's class does not require an
223 * explicit clinit check.
224 */
225
David Brazdila06d66a2015-05-28 11:14:54 +0100226 /// CHECK-START: void Main$SubClassOfClassWithClinit6.invokeStaticNotInlined() builder (after)
227 /// CHECK-DAG: InvokeStaticOrDirect
Roland Levillain5f02c6c2015-04-24 19:14:22 +0100228
David Brazdila06d66a2015-05-28 11:14:54 +0100229 /// CHECK-START: void Main$SubClassOfClassWithClinit6.invokeStaticNotInlined() builder (after)
230 /// CHECK-NOT: LoadClass
231 /// CHECK-NOT: ClinitCheck
Roland Levillain5f02c6c2015-04-24 19:14:22 +0100232
David Brazdila06d66a2015-05-28 11:14:54 +0100233 /// CHECK-START: void Main$SubClassOfClassWithClinit6.invokeStaticNotInlined() inliner (after)
234 /// CHECK-DAG: InvokeStaticOrDirect
Roland Levillain5f02c6c2015-04-24 19:14:22 +0100235
David Brazdila06d66a2015-05-28 11:14:54 +0100236 /// CHECK-START: void Main$SubClassOfClassWithClinit6.invokeStaticNotInlined() inliner (after)
237 /// CHECK-NOT: LoadClass
238 /// CHECK-NOT: ClinitCheck
Roland Levillain5f02c6c2015-04-24 19:14:22 +0100239
240 static class ClassWithClinit6 {
241 static boolean doThrow = false;
242
Guillaume "Vermeille" Sancheze918d382015-06-03 15:32:41 +0100243 static void $noinline$staticMethod() {
Roland Levillain5f02c6c2015-04-24 19:14:22 +0100244 // Try defeating inlining.
Nicolas Geoffray5bf7bac2016-07-06 14:18:23 +0000245 if (doThrow) { throw new Error(); }
Roland Levillain5f02c6c2015-04-24 19:14:22 +0100246 }
247
248 static {
249 System.out.println("Main$ClassWithClinit6's static initializer");
250 }
251 }
252
253 static class SubClassOfClassWithClinit6 extends ClassWithClinit6 {
254 static void invokeStaticNotInlined() {
Guillaume "Vermeille" Sancheze918d382015-06-03 15:32:41 +0100255 ClassWithClinit6.$noinline$staticMethod();
Roland Levillain5f02c6c2015-04-24 19:14:22 +0100256 }
257 }
258
Calin Juravle0ba218d2015-05-19 18:46:01 +0100259
260 /*
261 * Verify that if we have a static call immediately after the load class
262 * we don't do generate a clinit check.
263 */
264
David Brazdila06d66a2015-05-28 11:14:54 +0100265 /// CHECK-START: void Main.noClinitBecauseOfInvokeStatic() liveness (before)
266 /// CHECK-DAG: <<IntConstant:i\d+>> IntConstant 0
267 /// CHECK-DAG: <<LoadClass:l\d+>> LoadClass gen_clinit_check:false
Vladimir Markofbb184a2015-11-13 14:47:00 +0000268 /// CHECK-DAG: InvokeStaticOrDirect clinit_check:implicit
David Brazdila06d66a2015-05-28 11:14:54 +0100269 /// CHECK-DAG: StaticFieldSet [<<LoadClass>>,<<IntConstant>>]
Calin Juravle0ba218d2015-05-19 18:46:01 +0100270
David Brazdila06d66a2015-05-28 11:14:54 +0100271 /// CHECK-START: void Main.noClinitBecauseOfInvokeStatic() liveness (before)
272 /// CHECK-NOT: ClinitCheck
Calin Juravle0ba218d2015-05-19 18:46:01 +0100273
274 static void noClinitBecauseOfInvokeStatic() {
Guillaume "Vermeille" Sancheze918d382015-06-03 15:32:41 +0100275 ClassWithClinit2.$noinline$staticMethod();
Calin Juravle0ba218d2015-05-19 18:46:01 +0100276 ClassWithClinit2.doThrow = false;
277 }
278
279 /*
280 * Verify that if the static call is after a field access, the load class
281 * will generate a clinit check.
282 */
283
David Brazdila06d66a2015-05-28 11:14:54 +0100284 /// CHECK-START: void Main.clinitBecauseOfFieldAccess() liveness (before)
285 /// CHECK-DAG: <<IntConstant:i\d+>> IntConstant 0
286 /// CHECK-DAG: <<LoadClass:l\d+>> LoadClass gen_clinit_check:true
287 /// CHECK-DAG: StaticFieldSet [<<LoadClass>>,<<IntConstant>>]
Vladimir Markofbb184a2015-11-13 14:47:00 +0000288 /// CHECK-DAG: InvokeStaticOrDirect clinit_check:none
Calin Juravle0ba218d2015-05-19 18:46:01 +0100289
David Brazdila06d66a2015-05-28 11:14:54 +0100290 /// CHECK-START: void Main.clinitBecauseOfFieldAccess() liveness (before)
291 /// CHECK-NOT: ClinitCheck
Calin Juravle0ba218d2015-05-19 18:46:01 +0100292 static void clinitBecauseOfFieldAccess() {
293 ClassWithClinit2.doThrow = false;
Guillaume "Vermeille" Sancheze918d382015-06-03 15:32:41 +0100294 ClassWithClinit2.$noinline$staticMethod();
Calin Juravle0ba218d2015-05-19 18:46:01 +0100295 }
296
Vladimir Markofbb184a2015-11-13 14:47:00 +0000297 /*
298 * Verify that LoadClass from const-class is not merged with
299 * later invoke-static (or it's ClinitCheck).
300 */
301
302 /// CHECK-START: void Main.constClassAndInvokeStatic(java.lang.Iterable) liveness (before)
303 /// CHECK: LoadClass gen_clinit_check:false
304 /// CHECK: InvokeStaticOrDirect clinit_check:implicit
305
306 /// CHECK-START: void Main.constClassAndInvokeStatic(java.lang.Iterable) liveness (before)
307 /// CHECK-NOT: ClinitCheck
308
Vladimir Markoc7591b42016-06-29 14:59:07 +0100309 static void constClassAndInvokeStatic(Iterable<?> it) {
Vladimir Markofbb184a2015-11-13 14:47:00 +0000310 $opt$inline$ignoreClass(ClassWithClinit7.class);
Nicolas Geoffray5bf7bac2016-07-06 14:18:23 +0000311 ClassWithClinit7.$noinline$someStaticMethod(it);
Vladimir Markofbb184a2015-11-13 14:47:00 +0000312 }
313
Vladimir Markoc7591b42016-06-29 14:59:07 +0100314 static void $opt$inline$ignoreClass(Class<?> c) {
Vladimir Markofbb184a2015-11-13 14:47:00 +0000315 }
316
317 static class ClassWithClinit7 {
318 static {
319 System.out.println("Main$ClassWithClinit7's static initializer");
320 }
321
Nicolas Geoffray5bf7bac2016-07-06 14:18:23 +0000322 static void $noinline$someStaticMethod(Iterable<?> it) {
Vladimir Markofbb184a2015-11-13 14:47:00 +0000323 it.iterator();
Nicolas Geoffray5bf7bac2016-07-06 14:18:23 +0000324 // We're not inlining throw at the moment.
325 if (doThrow) { throw new Error(""); }
Vladimir Markofbb184a2015-11-13 14:47:00 +0000326 }
327 }
328
329 /*
330 * Verify that LoadClass from sget is not merged with later invoke-static.
331 */
332
333 /// CHECK-START: void Main.sgetAndInvokeStatic(java.lang.Iterable) liveness (before)
334 /// CHECK: LoadClass gen_clinit_check:true
335 /// CHECK: InvokeStaticOrDirect clinit_check:none
336
337 /// CHECK-START: void Main.sgetAndInvokeStatic(java.lang.Iterable) liveness (before)
338 /// CHECK-NOT: ClinitCheck
339
Vladimir Markoc7591b42016-06-29 14:59:07 +0100340 static void sgetAndInvokeStatic(Iterable<?> it) {
Vladimir Markofbb184a2015-11-13 14:47:00 +0000341 $opt$inline$ignoreInt(ClassWithClinit8.value);
Nicolas Geoffray5bf7bac2016-07-06 14:18:23 +0000342 ClassWithClinit8.$noinline$someStaticMethod(it);
Vladimir Markofbb184a2015-11-13 14:47:00 +0000343 }
344
345 static void $opt$inline$ignoreInt(int i) {
346 }
347
348 static class ClassWithClinit8 {
349 public static int value = 0;
350 static {
351 System.out.println("Main$ClassWithClinit8's static initializer");
352 }
353
Nicolas Geoffray5bf7bac2016-07-06 14:18:23 +0000354 static void $noinline$someStaticMethod(Iterable<?> it) {
Vladimir Markofbb184a2015-11-13 14:47:00 +0000355 it.iterator();
Nicolas Geoffray5bf7bac2016-07-06 14:18:23 +0000356 // We're not inlining throw at the moment.
357 if (doThrow) { throw new Error(""); }
Vladimir Markofbb184a2015-11-13 14:47:00 +0000358 }
359 }
360
361 /*
362 * Verify that LoadClass from const-class, ClinitCheck from sget and
363 * InvokeStaticOrDirect from invoke-static are not merged.
364 */
365
366 /// CHECK-START: void Main.constClassSgetAndInvokeStatic(java.lang.Iterable) liveness (before)
367 /// CHECK: LoadClass gen_clinit_check:false
368 /// CHECK: ClinitCheck
369 /// CHECK: InvokeStaticOrDirect clinit_check:none
370
Vladimir Markoc7591b42016-06-29 14:59:07 +0100371 static void constClassSgetAndInvokeStatic(Iterable<?> it) {
Vladimir Markofbb184a2015-11-13 14:47:00 +0000372 $opt$inline$ignoreClass(ClassWithClinit9.class);
373 $opt$inline$ignoreInt(ClassWithClinit9.value);
Nicolas Geoffray5bf7bac2016-07-06 14:18:23 +0000374 ClassWithClinit9.$noinline$someStaticMethod(it);
Vladimir Markofbb184a2015-11-13 14:47:00 +0000375 }
376
377 static class ClassWithClinit9 {
378 public static int value = 0;
379 static {
380 System.out.println("Main$ClassWithClinit9's static initializer");
381 }
382
Nicolas Geoffray5bf7bac2016-07-06 14:18:23 +0000383 static void $noinline$someStaticMethod(Iterable<?> it) {
Vladimir Markofbb184a2015-11-13 14:47:00 +0000384 it.iterator();
Nicolas Geoffray5bf7bac2016-07-06 14:18:23 +0000385 // We're not inlining throw at the moment.
386 if (doThrow) { throw new Error(""); }
Vladimir Markofbb184a2015-11-13 14:47:00 +0000387 }
388 }
389
390 /*
391 * Verify that LoadClass from a fully-inlined invoke-static is not merged
392 * with InvokeStaticOrDirect from a later invoke-static to the same method.
393 */
394
395 /// CHECK-START: void Main.inlinedInvokeStaticViaNonStatic(java.lang.Iterable) liveness (before)
396 /// CHECK: LoadClass gen_clinit_check:true
397 /// CHECK: InvokeStaticOrDirect clinit_check:none
398
399 /// CHECK-START: void Main.inlinedInvokeStaticViaNonStatic(java.lang.Iterable) liveness (before)
400 /// CHECK-NOT: ClinitCheck
401
Vladimir Markoc7591b42016-06-29 14:59:07 +0100402 static void inlinedInvokeStaticViaNonStatic(Iterable<?> it) {
Vladimir Markofbb184a2015-11-13 14:47:00 +0000403 inlinedInvokeStaticViaNonStaticHelper(null);
404 inlinedInvokeStaticViaNonStaticHelper(it);
405 }
406
Vladimir Markoc7591b42016-06-29 14:59:07 +0100407 static void inlinedInvokeStaticViaNonStaticHelper(Iterable<?> it) {
Vladimir Markofbb184a2015-11-13 14:47:00 +0000408 ClassWithClinit10.inlinedForNull(it);
409 }
410
411 static class ClassWithClinit10 {
412 public static int value = 0;
413 static {
414 System.out.println("Main$ClassWithClinit10's static initializer");
415 }
416
Vladimir Markoc7591b42016-06-29 14:59:07 +0100417 static void inlinedForNull(Iterable<?> it) {
Vladimir Markofbb184a2015-11-13 14:47:00 +0000418 if (it != null) {
Vladimir Markofbb184a2015-11-13 14:47:00 +0000419 it.iterator();
Nicolas Geoffray5bf7bac2016-07-06 14:18:23 +0000420 // We're not inlining throw at the moment.
421 if (doThrow) { throw new Error(""); }
Vladimir Markofbb184a2015-11-13 14:47:00 +0000422 }
423 }
424 }
425
426 /*
427 * Check that the LoadClass from an invoke-static C.foo() doesn't get merged with
428 * an invoke-static inside C.foo(). This would mess up the stack walk in the
429 * resolution trampoline where we would have to load C (if C isn't loaded yet)
430 * which is not permitted there.
431 *
432 * Note: In case of failure, we would get an failed assertion during compilation,
433 * so we wouldn't really get to the checker tests below.
434 */
435
436 /// CHECK-START: void Main.inlinedInvokeStaticViaStatic(java.lang.Iterable) liveness (before)
437 /// CHECK: LoadClass gen_clinit_check:true
438 /// CHECK: InvokeStaticOrDirect clinit_check:none
439
440 /// CHECK-START: void Main.inlinedInvokeStaticViaStatic(java.lang.Iterable) liveness (before)
441 /// CHECK-NOT: ClinitCheck
442
Vladimir Markoc7591b42016-06-29 14:59:07 +0100443 static void inlinedInvokeStaticViaStatic(Iterable<?> it) {
Vladimir Markofbb184a2015-11-13 14:47:00 +0000444 ClassWithClinit11.callInlinedForNull(it);
445 }
446
447 static class ClassWithClinit11 {
448 public static int value = 0;
449 static {
450 System.out.println("Main$ClassWithClinit11's static initializer");
451 }
452
Vladimir Markoc7591b42016-06-29 14:59:07 +0100453 static void callInlinedForNull(Iterable<?> it) {
Vladimir Markofbb184a2015-11-13 14:47:00 +0000454 inlinedForNull(it);
455 }
456
Vladimir Markoc7591b42016-06-29 14:59:07 +0100457 static void inlinedForNull(Iterable<?> it) {
Vladimir Markofbb184a2015-11-13 14:47:00 +0000458 it.iterator();
Nicolas Geoffray5bf7bac2016-07-06 14:18:23 +0000459 if (it != null) {
460 // We're not inlining throw at the moment.
461 if (doThrow) { throw new Error(""); }
462 }
Vladimir Markofbb184a2015-11-13 14:47:00 +0000463 }
464 }
465
466 /*
467 * A test similar to inlinedInvokeStaticViaStatic() but doing the indirect invoke
468 * twice with the first one to be fully inlined.
469 */
470
471 /// CHECK-START: void Main.inlinedInvokeStaticViaStaticTwice(java.lang.Iterable) liveness (before)
472 /// CHECK: LoadClass gen_clinit_check:true
473 /// CHECK: InvokeStaticOrDirect clinit_check:none
474
475 /// CHECK-START: void Main.inlinedInvokeStaticViaStaticTwice(java.lang.Iterable) liveness (before)
476 /// CHECK-NOT: ClinitCheck
477
Vladimir Markoc7591b42016-06-29 14:59:07 +0100478 static void inlinedInvokeStaticViaStaticTwice(Iterable<?> it) {
Vladimir Markofbb184a2015-11-13 14:47:00 +0000479 ClassWithClinit12.callInlinedForNull(null);
480 ClassWithClinit12.callInlinedForNull(it);
481 }
482
483 static class ClassWithClinit12 {
484 public static int value = 0;
485 static {
486 System.out.println("Main$ClassWithClinit12's static initializer");
487 }
488
Vladimir Markoc7591b42016-06-29 14:59:07 +0100489 static void callInlinedForNull(Iterable<?> it) {
Vladimir Markofbb184a2015-11-13 14:47:00 +0000490 inlinedForNull(it);
491 }
492
Vladimir Markoc7591b42016-06-29 14:59:07 +0100493 static void inlinedForNull(Iterable<?> it) {
Vladimir Markofbb184a2015-11-13 14:47:00 +0000494 if (it != null) {
Nicolas Geoffray5bf7bac2016-07-06 14:18:23 +0000495 // We're not inlining throw at the moment.
496 if (doThrow) { throw new Error(""); }
Vladimir Markofbb184a2015-11-13 14:47:00 +0000497 }
498 }
499 }
500
Vladimir Markoc7591b42016-06-29 14:59:07 +0100501 static class ClassWithClinit13 {
502 static {
503 System.out.println("Main$ClassWithClinit13's static initializer");
504 }
505
506 public static void $inline$forwardToGetIterator(Iterable<?> it) {
507 $noinline$getIterator(it);
508 }
509
510 public static void $noinline$getIterator(Iterable<?> it) {
Vladimir Markoc7591b42016-06-29 14:59:07 +0100511 it.iterator();
Nicolas Geoffray5bf7bac2016-07-06 14:18:23 +0000512 // We're not inlining throw at the moment.
513 if (doThrow) { throw new Error(""); }
Vladimir Markoc7591b42016-06-29 14:59:07 +0100514 }
515 }
516
517 // TODO: Write checker statements.
518 static Object $noinline$testInliningAndNewInstance(Iterable<?> it) {
519 if (doThrow) { throw new Error(); }
520 ClassWithClinit13.$inline$forwardToGetIterator(it);
521 return new ClassWithClinit13();
522 }
523
Roland Levillain4c0eb422015-04-24 16:43:49 +0100524 // TODO: Add a test for the case of a static method whose declaring
525 // class type index is not available (i.e. when `storage_index`
526 // equals `DexFile::kDexNoIndex` in
527 // art::HGraphBuilder::BuildInvoke).
528
529 public static void main(String[] args) {
530 invokeStaticInlined();
531 invokeStaticNotInlined();
532 ClassWithClinit3.invokeStaticInlined();
533 ClassWithClinit4.invokeStaticNotInlined();
Roland Levillain5f02c6c2015-04-24 19:14:22 +0100534 SubClassOfClassWithClinit5.invokeStaticInlined();
535 SubClassOfClassWithClinit6.invokeStaticNotInlined();
Vladimir Markofbb184a2015-11-13 14:47:00 +0000536 Iterable it = new Iterable() { public java.util.Iterator iterator() { return null; } };
537 constClassAndInvokeStatic(it);
538 sgetAndInvokeStatic(it);
539 constClassSgetAndInvokeStatic(it);
540 inlinedInvokeStaticViaNonStatic(it);
541 inlinedInvokeStaticViaStatic(it);
542 inlinedInvokeStaticViaStaticTwice(it);
Vladimir Markoc7591b42016-06-29 14:59:07 +0100543 $noinline$testInliningAndNewInstance(it);
Roland Levillain4c0eb422015-04-24 16:43:49 +0100544 }
545}