• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 interface SuperInterface {
superInterfaceMethod()18   void superInterfaceMethod();
19 }
20 
21 interface OtherInterface extends SuperInterface {
22 }
23 
24 interface Interface extends SuperInterface {
$noinline$f()25   void $noinline$f();
26 }
27 
28 class Super implements Interface {
superInterfaceMethod()29   public void superInterfaceMethod() {}
$noinline$f()30   public void $noinline$f() {
31     throw new RuntimeException();
32   }
33 
$inline$h(boolean cond)34   public int $inline$h(boolean cond) {
35     Super obj = (cond ? this : null);
36     return obj.hashCode();
37   }
38 }
39 
40 class SubclassA extends Super {
$noinline$f()41   public void $noinline$f() {
42     throw new RuntimeException();
43   }
44 
$noinline$h()45   public String $noinline$h() {
46     throw new RuntimeException();
47   }
48 
$noinline$g()49   void $noinline$g() {
50     throw new RuntimeException();
51   }
52 }
53 
54 class SubclassC extends SubclassA {
55 }
56 
57 class SubclassB extends Super {
$noinline$f()58   public void $noinline$f() {
59     throw new RuntimeException();
60   }
61 
$noinline$g()62   void $noinline$g() {
63     throw new RuntimeException();
64   }
65 }
66 
67 class Generic<A> {
68   private A a = null;
get()69   public A get() {
70     return a;
71   }
72 }
73 
74 final class Final {}
75 
76 final class FinalException extends Exception {}
77 
78 public class Main {
79 
80   /// CHECK-START: void Main.testSimpleRemove() instruction_simplifier (before)
81   /// CHECK:         CheckCast
82 
83   /// CHECK-START: void Main.testSimpleRemove() instruction_simplifier (after)
84   /// CHECK-NOT:     CheckCast
testSimpleRemove()85   public void testSimpleRemove() {
86     Super s = new SubclassA();
87     ((SubclassA)s).$noinline$g();
88   }
89 
90   /// CHECK-START: void Main.testSimpleKeep(Super) instruction_simplifier (before)
91   /// CHECK:         CheckCast
92 
93   /// CHECK-START: void Main.testSimpleKeep(Super) instruction_simplifier (after)
94   /// CHECK:         CheckCast
testSimpleKeep(Super s)95   public void testSimpleKeep(Super s) {
96     ((SubclassA)s).$noinline$f();
97   }
98 
99   /// CHECK-START: java.lang.String Main.testClassRemove() instruction_simplifier (before)
100   /// CHECK:         CheckCast
101 
102   /// CHECK-START: java.lang.String Main.testClassRemove() instruction_simplifier (after)
103   /// CHECK-NOT:     CheckCast
testClassRemove()104   public String testClassRemove() {
105     Object s = SubclassA.class;
106     return ((Class<?>)s).getName();
107   }
108 
109   /// CHECK-START: java.lang.String Main.testClassKeep() instruction_simplifier (before)
110   /// CHECK:         CheckCast
111 
112   /// CHECK-START: java.lang.String Main.testClassKeep() instruction_simplifier (after)
113   /// CHECK:         CheckCast
testClassKeep()114   public String testClassKeep() {
115     Object s = SubclassA.class;
116     return ((SubclassA)s).$noinline$h();
117   }
118 
119   /// CHECK-START: void Main.testIfRemove(int) instruction_simplifier (before)
120   /// CHECK:         CheckCast
121 
122   /// CHECK-START: void Main.testIfRemove(int) instruction_simplifier (after)
123   /// CHECK-NOT:     CheckCast
testIfRemove(int x)124   public void testIfRemove(int x) {
125     Super s;
126     if (x % 2 == 0) {
127       s = new SubclassA();
128     } else {
129       s = new SubclassC();
130     }
131     ((SubclassA)s).$noinline$g();
132   }
133 
134   /// CHECK-START: void Main.testIfKeep(int) instruction_simplifier (before)
135   /// CHECK:         CheckCast
136 
137   /// CHECK-START: void Main.testIfKeep(int) instruction_simplifier (after)
138   /// CHECK:         CheckCast
testIfKeep(int x)139   public void testIfKeep(int x) {
140     Super s;
141     if (x % 2 == 0) {
142       s = new SubclassA();
143     } else {
144       s = new SubclassB();
145     }
146     ((SubclassA)s).$noinline$g();
147   }
148 
149   /// CHECK-START: void Main.testForRemove(int) instruction_simplifier (before)
150   /// CHECK:         CheckCast
151 
152   /// CHECK-START: void Main.testForRemove(int) instruction_simplifier (after)
153   /// CHECK-NOT:     CheckCast
testForRemove(int x)154   public void testForRemove(int x) {
155     Super s = new SubclassA();
156     for (int i = 0 ; i < x; i++) {
157       if (x % 2 == 0) {
158         s = new SubclassC();
159       }
160     }
161     ((SubclassA)s).$noinline$g();
162   }
163 
164   /// CHECK-START: void Main.testForKeep(int) instruction_simplifier (before)
165   /// CHECK:         CheckCast
166 
167   /// CHECK-START: void Main.testForKeep(int) instruction_simplifier (after)
168   /// CHECK:         CheckCast
testForKeep(int x)169   public void testForKeep(int x) {
170     Super s = new SubclassA();
171     for (int i = 0 ; i < x; i++) {
172       if (x % 2 == 0) {
173         s = new SubclassC();
174       }
175     }
176     ((SubclassC)s).$noinline$g();
177   }
178 
179   /// CHECK-START: void Main.testPhiFromCall(int) instruction_simplifier (before)
180   /// CHECK:         CheckCast
181 
182   /// CHECK-START: void Main.testPhiFromCall(int) instruction_simplifier (after)
183   /// CHECK:         CheckCast
testPhiFromCall(int i)184   public void testPhiFromCall(int i) {
185     Object x;
186     if (i % 2 == 0) {
187       x = new SubclassC();
188     } else {
189       x = newObject();  // this one will have an unknown type.
190     }
191     ((SubclassC)x).$noinline$g();
192   }
193 
194   /// CHECK-START: void Main.testInstanceOf(java.lang.Object) instruction_simplifier (before)
195   /// CHECK:         CheckCast
196   /// CHECK:         CheckCast
197   /// CHECK-NOT:     CheckCast
198 
199   /// CHECK-START: void Main.testInstanceOf(java.lang.Object) instruction_simplifier (after)
200   /// CHECK-NOT:     CheckCast
testInstanceOf(Object o)201   public void testInstanceOf(Object o) {
202     if (o instanceof SubclassC) {
203       ((SubclassC)o).$noinline$g();
204     }
205     if (o instanceof SubclassB) {
206       ((SubclassB)o).$noinline$g();
207     }
208   }
209 
$inline$InstanceofSubclassB(Object o)210   public static boolean $inline$InstanceofSubclassB(Object o) { return o instanceof SubclassB; }
$inline$InstanceofSubclassC(Object o)211   public static boolean $inline$InstanceofSubclassC(Object o) { return o instanceof SubclassC; }
212 
213   /// CHECK-START: void Main.testInstanceOf_Inlined(java.lang.Object) inliner (after)
214   /// CHECK-DAG:     <<IOf:z\d+>>  InstanceOf
215   /// CHECK-DAG:                   If [<<IOf>>]
216 
217   /// CHECK-START: void Main.testInstanceOf_Inlined(java.lang.Object) instruction_simplifier$after_inlining (before)
218   /// CHECK:         CheckCast
219   /// CHECK-NOT:     CheckCast
220 
221   /// CHECK-START: void Main.testInstanceOf_Inlined(java.lang.Object) instruction_simplifier$after_inlining (after)
222   /// CHECK-NOT:     CheckCast
testInstanceOf_Inlined(Object o)223   public void testInstanceOf_Inlined(Object o) {
224     if (!$inline$InstanceofSubclassC(o)) {
225       // Empty branch to flip the condition.
226     } else {
227       ((SubclassC)o).$noinline$g();
228     }
229   }
230 
231   /// CHECK-START: void Main.testInstanceOfKeep(java.lang.Object) instruction_simplifier (before)
232   /// CHECK:         CheckCast
233   /// CHECK:         CheckCast
234 
235   /// CHECK-START: void Main.testInstanceOfKeep(java.lang.Object) instruction_simplifier (after)
236   /// CHECK:         CheckCast
237   /// CHECK:         CheckCast
testInstanceOfKeep(Object o)238   public void testInstanceOfKeep(Object o) {
239     if (o instanceof SubclassC) {
240       ((SubclassB)o).$noinline$g();
241     }
242     if (o instanceof SubclassB) {
243       ((SubclassA)o).$noinline$g();
244     }
245   }
246 
247   /// CHECK-START: void Main.testInstanceOfNested(java.lang.Object) instruction_simplifier (before)
248   /// CHECK:         CheckCast
249   /// CHECK:         CheckCast
250 
251   /// CHECK-START: void Main.testInstanceOfNested(java.lang.Object) instruction_simplifier (after)
252   /// CHECK-NOT:     CheckCast
testInstanceOfNested(Object o)253   public void testInstanceOfNested(Object o) {
254     if (o instanceof SubclassC) {
255       if (o instanceof SubclassB) {
256         ((SubclassB)o).$noinline$g();
257       } else {
258         ((SubclassC)o).$noinline$g();
259       }
260     }
261   }
262 
263   /// CHECK-START: void Main.testInstanceOfWithPhi(int) instruction_simplifier (before)
264   /// CHECK:         CheckCast
265 
266   /// CHECK-START: void Main.testInstanceOfWithPhi(int) instruction_simplifier (after)
267   /// CHECK-NOT:     CheckCast
testInstanceOfWithPhi(int i)268   public void testInstanceOfWithPhi(int i) {
269     Object o;
270     if (i == 0) {
271       o = new SubclassA();
272     } else {
273       o = new SubclassB();
274     }
275 
276     if (o instanceof SubclassB) {
277       ((SubclassB)o).$noinline$g();
278     }
279   }
280 
281   /// CHECK-START: void Main.testInstanceOfInFor(int) instruction_simplifier (before)
282   /// CHECK:         CheckCast
283 
284   /// CHECK-START: void Main.testInstanceOfInFor(int) instruction_simplifier (after)
285   /// CHECK-NOT:     CheckCast
testInstanceOfInFor(int n)286   public void testInstanceOfInFor(int n) {
287     Object o = new SubclassA();
288     for (int i = 0; i < n; i++) {
289       if (i / 2 == 0) {
290         o = new SubclassB();
291       }
292       if (o instanceof SubclassB) {
293         ((SubclassB)o).$noinline$g();
294       }
295     }
296   }
297 
298   /// CHECK-START: void Main.testInstanceOfSubclass() instruction_simplifier (before)
299   /// CHECK:         CheckCast
300 
301   /// CHECK-START: void Main.testInstanceOfSubclass() instruction_simplifier (after)
302   /// CHECK-NOT:     CheckCast
testInstanceOfSubclass()303   public void testInstanceOfSubclass() {
304     Object o = new SubclassA();
305     if (o instanceof Super) {
306       ((SubclassA)o).$noinline$g();
307     }
308   }
309 
310   /// CHECK-START: void Main.testInstanceOfWithPhiSubclass(int) instruction_simplifier (before)
311   /// CHECK:         CheckCast
312 
313   /// CHECK-START: void Main.testInstanceOfWithPhiSubclass(int) instruction_simplifier (after)
314   /// CHECK-NOT:     CheckCast
testInstanceOfWithPhiSubclass(int i)315   public void testInstanceOfWithPhiSubclass(int i) {
316     Object o;
317     if (i == 0) {
318       o = new SubclassA();
319     } else {
320       o = new SubclassC();
321     }
322 
323     if (o instanceof Super) {
324       ((SubclassA)o).$noinline$g();
325     }
326   }
327 
328   /// CHECK-START: void Main.testInstanceOfWithPhiTop(int) instruction_simplifier (before)
329   /// CHECK:         CheckCast
330 
331   /// CHECK-START: void Main.testInstanceOfWithPhiTop(int) instruction_simplifier (after)
332   /// CHECK-NOT:     CheckCast
testInstanceOfWithPhiTop(int i)333   public void testInstanceOfWithPhiTop(int i) {
334     Object o;
335     if (i == 0) {
336       o = new Object();
337     } else {
338       o = new SubclassC();
339     }
340 
341     if (o instanceof Super) {
342       ((Super)o).$noinline$f();
343     }
344   }
345 
346   /// CHECK-START: void Main.testInstanceOfSubclassInFor(int) instruction_simplifier (before)
347   /// CHECK:         CheckCast
348 
349   /// CHECK-START: void Main.testInstanceOfSubclassInFor(int) instruction_simplifier (after)
350   /// CHECK-NOT:     CheckCast
testInstanceOfSubclassInFor(int n)351   public void testInstanceOfSubclassInFor(int n) {
352     Object o = new SubclassA();
353     for (int i = 0; i < n; i++) {
354       if (o instanceof Super) {
355         ((SubclassA)o).$noinline$g();
356       }
357       if (i / 2 == 0) {
358         o = new SubclassC();
359       }
360     }
361   }
362 
363   /// CHECK-START: void Main.testInstanceOfTopInFor(int) instruction_simplifier (before)
364   /// CHECK:         CheckCast
365 
366   /// CHECK-START: void Main.testInstanceOfTopInFor(int) instruction_simplifier (after)
367   /// CHECK-NOT:     CheckCast
testInstanceOfTopInFor(int n)368   public void testInstanceOfTopInFor(int n) {
369     Object o = new SubclassA();
370     for (int i = 0; i < n; i++) {
371       if (o instanceof Super) {
372         ((Super)o).$noinline$f();
373       }
374       if (i / 2 == 0) {
375         o = new Object();
376       }
377     }
378   }
379 
newObject()380   public Object newObject() {
381     try {
382       return Object.class.newInstance();
383     } catch (Exception e) {
384       return null;
385     }
386   }
387 
388   public SubclassA a = new SubclassA();
389   public static SubclassA b = new SubclassA();
390 
391   /// CHECK-START: void Main.testInstanceFieldGetSimpleRemove() instruction_simplifier (before)
392   /// CHECK:         CheckCast
393 
394   /// CHECK-START: void Main.testInstanceFieldGetSimpleRemove() instruction_simplifier (after)
395   /// CHECK-NOT:     CheckCast
testInstanceFieldGetSimpleRemove()396   public void testInstanceFieldGetSimpleRemove() {
397     Main m = new Main();
398     Super a = m.a;
399     ((SubclassA)a).$noinline$g();
400   }
401 
402   /// CHECK-START: void Main.testStaticFieldGetSimpleRemove() instruction_simplifier (before)
403   /// CHECK:         CheckCast
404 
405   /// CHECK-START: void Main.testStaticFieldGetSimpleRemove() instruction_simplifier (after)
406   /// CHECK-NOT:     CheckCast
testStaticFieldGetSimpleRemove()407   public void testStaticFieldGetSimpleRemove() {
408     Super b = Main.b;
409     ((SubclassA)b).$noinline$g();
410   }
411 
$noinline$getSubclass()412   public SubclassA $noinline$getSubclass() { throw new RuntimeException(); }
413 
414   /// CHECK-START: void Main.testArraySimpleRemove() instruction_simplifier (before)
415   /// CHECK:         CheckCast
416 
417   /// CHECK-START: void Main.testArraySimpleRemove() instruction_simplifier (after)
418   /// CHECK-NOT:     CheckCast
testArraySimpleRemove()419   public void testArraySimpleRemove() {
420     Super[] b = new SubclassA[10];
421     SubclassA[] c = (SubclassA[])b;
422   }
423 
424   /// CHECK-START: void Main.testInvokeSimpleRemove() instruction_simplifier (before)
425   /// CHECK:         CheckCast
426 
427   /// CHECK-START: void Main.testInvokeSimpleRemove() instruction_simplifier (after)
428   /// CHECK-NOT:     CheckCast
testInvokeSimpleRemove()429   public void testInvokeSimpleRemove() {
430     Super b = $noinline$getSubclass();
431     ((SubclassA)b).$noinline$g();
432   }
433   /// CHECK-START: void Main.testArrayGetSimpleRemove() instruction_simplifier (before)
434   /// CHECK:         CheckCast
435 
436   /// CHECK-START: void Main.testArrayGetSimpleRemove() instruction_simplifier (after)
437   /// CHECK-NOT:     CheckCast
testArrayGetSimpleRemove()438   public void testArrayGetSimpleRemove() {
439     Super[] a = new SubclassA[10];
440     ((SubclassA)a[0]).$noinline$g();
441   }
442 
443   /// CHECK-START: int Main.testLoadExceptionInCatchNonExact(int, int) builder (after)
444   /// CHECK:         LoadException klass:java.lang.ArithmeticException can_be_null:false exact:false
testLoadExceptionInCatchNonExact(int x, int y)445   public int testLoadExceptionInCatchNonExact(int x, int y) {
446     try {
447       return x / y;
448     } catch (ArithmeticException ex) {
449       return ex.hashCode();
450     }
451   }
452 
453   /// CHECK-START: int Main.testLoadExceptionInCatchExact(int) builder (after)
454   /// CHECK:         LoadException klass:FinalException can_be_null:false exact:true
testLoadExceptionInCatchExact(int x)455   public int testLoadExceptionInCatchExact(int x) {
456     try {
457       if (x == 42) {
458         throw new FinalException();
459       } else {
460         return x;
461       }
462     } catch (FinalException ex) {
463       return ex.hashCode();
464     }
465   }
466 
467   /// CHECK-START: int Main.testLoadExceptionInCatchAll(int, int) builder (after)
468   /// CHECK:         LoadException klass:java.lang.Throwable can_be_null:false exact:false
testLoadExceptionInCatchAll(int x, int y)469   public int testLoadExceptionInCatchAll(int x, int y) {
470     try {
471       x = x / y;
472     } finally {
473       return x;
474     }
475   }
476 
477   private Generic<SubclassC> genericC = new Generic<SubclassC>();
478   private Generic<Final> genericFinal = new Generic<Final>();
479 
get()480   private SubclassC get() {
481     return genericC.get();
482   }
483 
getFinal()484   private Final getFinal() {
485     return genericFinal.get();
486   }
487 
488   /// CHECK-START: SubclassC Main.inlineGenerics() builder (after)
489   /// CHECK:      <<Invoke:l\d+>>    InvokeStaticOrDirect klass:SubclassC exact:false
490   /// CHECK-NEXT:                    Return [<<Invoke>>]
491 
492   /// CHECK-START: SubclassC Main.inlineGenerics() inliner (after)
493   /// CHECK:      <<BoundType:l\d+>> BoundType klass:SubclassC exact:false
494   /// CHECK:                         Return [<<BoundType>>]
inlineGenerics()495   private SubclassC inlineGenerics() {
496     SubclassC c = get();
497     return c;
498   }
499 
500   /// CHECK-START: Final Main.inlineGenericsFinal() builder (after)
501   /// CHECK:      <<Invoke:l\d+>>    InvokeStaticOrDirect klass:Final exact:true
502   /// CHECK-NEXT:                    Return [<<Invoke>>]
503 
504   /// CHECK-START: Final Main.inlineGenericsFinal() inliner (after)
505   /// CHECK:      <<BoundType:l\d+>> BoundType klass:Final exact:true
506   /// CHECK:                         Return [<<BoundType>>]
inlineGenericsFinal()507   private Final inlineGenericsFinal() {
508     Final f = getFinal();
509     return f;
510   }
511 
512   /// CHECK-START: void Main.boundOnlyOnceIfNotNull(java.lang.Object) inliner (after)
513   /// CHECK:      BoundType
514   /// CHECK-NOT:  BoundType
boundOnlyOnceIfNotNull(Object o)515   private void boundOnlyOnceIfNotNull(Object o) {
516     if (o != null) {
517       o.toString();
518     }
519   }
520 
521   /// CHECK-START: void Main.boundOnlyOnceIfInstanceOf(java.lang.Object) inliner (after)
522   /// CHECK:      BoundType
523   /// CHECK-NOT:  BoundType
boundOnlyOnceIfInstanceOf(Object o)524   private void boundOnlyOnceIfInstanceOf(Object o) {
525     if (o instanceof Main) {
526       o.toString();
527     }
528   }
529 
530   /// CHECK-START: Final Main.boundOnlyOnceCheckCast(Generic) inliner (after)
531   /// CHECK:      BoundType
532   /// CHECK-NOT:  BoundType
boundOnlyOnceCheckCast(Generic<Final> o)533   private Final boundOnlyOnceCheckCast(Generic<Final> o) {
534     Final f = o.get();
535     return f;
536   }
537 
getSuper()538   private Super getSuper() {
539     return new SubclassA();
540   }
541 
542   /// CHECK-START: void Main.updateNodesInTheSameBlockAsPhi(boolean) builder (after)
543   /// CHECK:      <<Phi:l\d+>> Phi klass:Super
544   /// CHECK:                   NullCheck [<<Phi>>] klass:Super
545 
546   /// CHECK-START: void Main.updateNodesInTheSameBlockAsPhi(boolean) inliner (after)
547   /// CHECK:      <<Phi:l\d+>> Phi klass:SubclassA
548   /// CHECK:                   NullCheck [<<Phi>>] klass:SubclassA
updateNodesInTheSameBlockAsPhi(boolean cond)549   private void updateNodesInTheSameBlockAsPhi(boolean cond) {
550     Super s = getSuper();
551     if (cond) {
552       s = new SubclassA();
553     }
554     s.$noinline$f();
555   }
556 
557   /// CHECK-START: java.lang.String Main.checkcastPreserveNullCheck(java.lang.Object) inliner (after)
558   /// CHECK:      <<This:l\d+>>     ParameterValue
559   /// CHECK:      <<Param:l\d+>>    ParameterValue
560   /// CHECK:      <<Clazz:l\d+>>    LoadClass
561   /// CHECK:                        CheckCast [<<Param>>,<<Clazz>>]
562   /// CHECK:                        BoundType [<<Param>>] can_be_null:true
563 
564   /// CHECK-START: java.lang.String Main.checkcastPreserveNullCheck(java.lang.Object) instruction_simplifier (after)
565   /// CHECK:      <<This:l\d+>>     ParameterValue
566   /// CHECK:      <<Param:l\d+>>    ParameterValue
567   /// CHECK:      <<Clazz:l\d+>>    LoadClass
568   /// CHECK:                        CheckCast [<<Param>>,<<Clazz>>]
569   /// CHECK:      <<Bound:l\d+>>    BoundType [<<Param>>]
570   /// CHECK:                        NullCheck [<<Bound>>]
checkcastPreserveNullCheck(Object a)571   public String checkcastPreserveNullCheck(Object a) {
572     return ((SubclassA)a).toString();
573   }
574 
575 
576   /// CHECK-START: void Main.argumentCheck(Super, double, SubclassA, Final) builder (after)
577   /// CHECK:      ParameterValue klass:Main can_be_null:false exact:false
578   /// CHECK:      ParameterValue klass:Super can_be_null:true exact:false
579   /// CHECK:      ParameterValue
580   /// CHECK:      ParameterValue klass:SubclassA can_be_null:true exact:false
581   /// CHECK:      ParameterValue klass:Final can_be_null:true exact:true
582   /// CHECK-NOT:  ParameterValue
argumentCheck(Super s, double d, SubclassA a, Final f)583   private void argumentCheck(Super s, double d, SubclassA a, Final f) {
584   }
585 
getNull()586   private Main getNull() {
587     return null;
588   }
589 
590   private int mainField = 0;
591 
592   /// CHECK-START: SuperInterface Main.getWiderType(boolean, Interface, OtherInterface) builder (after)
593   /// CHECK:      <<Phi:l\d+>>       Phi klass:java.lang.Object
594   /// CHECK:                         Return [<<Phi>>]
getWiderType(boolean cond, Interface a, OtherInterface b)595   private SuperInterface getWiderType(boolean cond, Interface a, OtherInterface b) {
596     return cond ? a : b;
597   }
598 
599   /// CHECK-START: void Main.testInlinerWidensReturnType(boolean, Interface, OtherInterface) inliner (before)
600   /// CHECK:      <<Invoke:l\d+>>    InvokeStaticOrDirect klass:SuperInterface
601   /// CHECK:      <<NullCheck:l\d+>> NullCheck [<<Invoke>>] klass:SuperInterface exact:false
602   /// CHECK:                         InvokeInterface [<<NullCheck>>]
603 
604   /// CHECK-START: void Main.testInlinerWidensReturnType(boolean, Interface, OtherInterface) inliner (after)
605   /// CHECK:      <<Phi:l\d+>>       Phi klass:java.lang.Object
606   /// CHECK:      <<NullCheck:l\d+>> NullCheck [<<Phi>>] klass:SuperInterface exact:false
607   /// CHECK:                         InvokeInterface [<<NullCheck>>]
testInlinerWidensReturnType(boolean cond, Interface a, OtherInterface b)608   private void testInlinerWidensReturnType(boolean cond, Interface a, OtherInterface b) {
609     getWiderType(cond, a, b).superInterfaceMethod();
610   }
611 
612   /// CHECK-START: void Main.testInlinerReturnsNull() inliner (before)
613   /// CHECK:      <<Int:i\d+>>       IntConstant 0
614   /// CHECK:      <<Invoke:l\d+>>    InvokeStaticOrDirect klass:Main
615   /// CHECK:      <<NullCheck:l\d+>> NullCheck [<<Invoke>>] klass:Main exact:false
616   /// CHECK:                         InstanceFieldSet [<<NullCheck>>,<<Int>>]
617 
618   /// CHECK-START: void Main.testInlinerReturnsNull() inliner (after)
619   /// CHECK:      <<Int:i\d+>>       IntConstant 0
620   /// CHECK:      <<Null:l\d+>>      NullConstant klass:java.lang.Object
621   /// CHECK:      <<NullCheck:l\d+>> NullCheck [<<Null>>] klass:Main exact:false
622   /// CHECK:                         InstanceFieldSet [<<NullCheck>>,<<Int>>]
testInlinerReturnsNull()623   private void testInlinerReturnsNull() {
624     Main o = getNull();
625     o.mainField = 0;
626   }
627 
628   /// CHECK-START: void Main.testThisArgumentMoreSpecific(boolean) inliner (before)
629   /// CHECK-DAG:     <<Arg:l\d+>>   NewInstance
630   /// CHECK-DAG:                    InvokeVirtual [<<Arg>>,{{z\d+}}] method_name:Super.$inline$h
631 
632   /// CHECK-START: void Main.testThisArgumentMoreSpecific(boolean) inliner (after)
633   /// CHECK-DAG:     <<Arg:l\d+>>   NewInstance
634   /// CHECK-DAG:     <<Null:l\d+>>  NullConstant
635   /// CHECK-DAG:     <<Phi:l\d+>>   Phi [<<Arg>>,<<Null>>] klass:SubclassA
636   /// CHECK-DAG:     <<NCPhi:l\d+>> NullCheck [<<Phi>>]
637   /// CHECK-DAG:                    InvokeVirtual [<<NCPhi>>] method_name:Super.hashCode
638 
testThisArgumentMoreSpecific(boolean cond)639   public void testThisArgumentMoreSpecific(boolean cond) {
640     // Inlining method from Super will build it with `this` typed as Super.
641     // Running RTP will sharpen it to SubclassA.
642     SubclassA obj = new SubclassA();
643     ((Super) obj).$inline$h(cond);
644   }
645 
$inline$hashCode(Super obj)646   public static int $inline$hashCode(Super obj) {
647     return obj.hashCode();
648   }
649 
650   /// CHECK-START: void Main.testExplicitArgumentMoreSpecific(SubclassA) inliner (before)
651   /// CHECK-DAG:     <<Arg:l\d+>>   ParameterValue klass:SubclassA
652   // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
653   /// CHECK-DAG:                    InvokeStaticOrDirect [<<Arg>>{{(,[ij]\d+)?}}] method_name:Main.$inline$hashCode
654 
655   /// CHECK-START: void Main.testExplicitArgumentMoreSpecific(SubclassA) inliner (after)
656   /// CHECK-DAG:     <<Arg:l\d+>>   ParameterValue klass:SubclassA
657   /// CHECK-DAG:     <<NCArg:l\d+>> NullCheck [<<Arg>>] klass:SubclassA
658   /// CHECK-DAG:                    InvokeVirtual [<<NCArg>>] method_name:Super.hashCode
659 
testExplicitArgumentMoreSpecific(SubclassA obj)660   public void testExplicitArgumentMoreSpecific(SubclassA obj) {
661     // Inlining a method will build it with reference types from its signature,
662     // here the callee graph is built with Super as the type of its only argument.
663     // Running RTP after its ParameterValue instructions are replaced with actual
664     // arguments will type the inner graph more precisely.
665     $inline$hashCode(obj);
666   }
667 
668   /// CHECK-START: void Main.testPhiHasOnlyNullInputs(boolean) inliner (before)
669   /// CHECK:      <<Int:i\d+>>       IntConstant 0
670   /// CHECK:      <<Phi:l\d+>>       Phi klass:Main exact:false
671   /// CHECK:      <<NullCheck:l\d+>> NullCheck [<<Phi>>] klass:Main exact:false
672   /// CHECK:                         InstanceFieldSet [<<NullCheck>>,<<Int>>]
673 
674   /// CHECK-START: void Main.testPhiHasOnlyNullInputs(boolean) inliner (after)
675   /// CHECK:      <<Int:i\d+>>       IntConstant 0
676   /// CHECK:      <<Null:l\d+>>      NullConstant klass:java.lang.Object
677   /// CHECK:      <<Phi:l\d+>>       Phi [<<Null>>,<<Null>>] klass:java.lang.Object exact:false
678   /// CHECK:      <<NullCheck:l\d+>> NullCheck [<<Phi>>] klass:java.lang.Object exact:false
679   /// CHECK:                         InstanceFieldSet [<<NullCheck>>,<<Int>>]
testPhiHasOnlyNullInputs(boolean cond)680   private void testPhiHasOnlyNullInputs(boolean cond) {
681     Main o = cond ? null : getNull();
682     o.mainField = 0;
683     // getSuper() will force a type propagation after inlining
684     // because returns a more precise type.
685     getSuper();
686   }
687 
688   /// CHECK-START: void Main.testLoopPhiWithNullFirstInput(boolean) builder (after)
689   /// CHECK-DAG:  <<Null:l\d+>>      NullConstant
690   /// CHECK-DAG:  <<Main:l\d+>>      NewInstance klass:Main exact:true
691   /// CHECK-DAG:  <<LoopPhi:l\d+>>   Phi [<<Null>>,<<LoopPhi>>,<<Main>>] klass:Main exact:true
testLoopPhiWithNullFirstInput(boolean cond)692   private void testLoopPhiWithNullFirstInput(boolean cond) {
693     Main a = null;
694     while (a == null) {
695       if (cond) {
696         a = new Main();
697       }
698     }
699   }
700 
701   /// CHECK-START: java.lang.Object[] Main.testInstructionsWithUntypedParent() builder (after)
702   /// CHECK-DAG:  <<Null:l\d+>>      NullConstant
703   /// CHECK-DAG:  <<LoopPhi:l\d+>>   Phi [<<Null>>,<<Phi:l\d+>>] klass:java.lang.Object[] exact:true
704   /// CHECK-DAG:  <<Array:l\d+>>     NewArray klass:java.lang.Object[] exact:true
705   /// CHECK-DAG:  <<Phi>>            Phi [<<Array>>,<<LoopPhi>>] klass:java.lang.Object[] exact:true
706   /// CHECK-DAG:  <<NC:l\d+>>        NullCheck [<<LoopPhi>>] klass:java.lang.Object[] exact:true
707   /// CHECK-DAG:                     ArrayGet [<<NC>>,{{i\d+}}] klass:java.lang.Object exact:false
testInstructionsWithUntypedParent()708   private Object[] testInstructionsWithUntypedParent() {
709     Object[] array = null;
710     boolean cond = true;
711     for (int i = 0; i < 10; ++i) {
712       if (cond) {
713         array = new Object[10];
714         array[0] = new Object();
715         cond = false;
716       } else {
717         array[i] = array[0];
718       }
719     }
720     return array;
721   }
722 
main(String[] args)723   public static void main(String[] args) {
724   }
725 }
726