xref: /aosp_15_r20/art/test/638-checker-inline-caches/src/Main.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2017 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker class SubA extends Super {
getValue()18*795d594fSAndroid Build Coastguard Worker   int getValue() { return 42; }
someSubclassesThrow()19*795d594fSAndroid Build Coastguard Worker   void someSubclassesThrow() throws Error { throw new Error("I always throw"); }
20*795d594fSAndroid Build Coastguard Worker }
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker class SubB extends Super {
getValue()23*795d594fSAndroid Build Coastguard Worker   int getValue() { return 38; }
someSubclassesThrow()24*795d594fSAndroid Build Coastguard Worker   void someSubclassesThrow() { System.out.println("I don't throw"); }
25*795d594fSAndroid Build Coastguard Worker }
26*795d594fSAndroid Build Coastguard Worker 
27*795d594fSAndroid Build Coastguard Worker class SubD extends Super {
getValue()28*795d594fSAndroid Build Coastguard Worker   int getValue() { return 10; }
someSubclassesThrow()29*795d594fSAndroid Build Coastguard Worker   void someSubclassesThrow() { System.out.println("I don't throw"); }
30*795d594fSAndroid Build Coastguard Worker }
31*795d594fSAndroid Build Coastguard Worker 
32*795d594fSAndroid Build Coastguard Worker class SubE extends Super {
getValue()33*795d594fSAndroid Build Coastguard Worker   int getValue() { return -4; }
someSubclassesThrow()34*795d594fSAndroid Build Coastguard Worker   void someSubclassesThrow() { System.out.println("I don't throw"); }
35*795d594fSAndroid Build Coastguard Worker }
36*795d594fSAndroid Build Coastguard Worker 
37*795d594fSAndroid Build Coastguard Worker public class Main {
38*795d594fSAndroid Build Coastguard Worker 
39*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.inlineMonomorphicSubA(Super) inliner (before)
40*795d594fSAndroid Build Coastguard Worker   /// CHECK:       InvokeVirtual method_name:Super.getValue
41*795d594fSAndroid Build Coastguard Worker 
42*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.inlineMonomorphicSubA(Super) inliner (after)
43*795d594fSAndroid Build Coastguard Worker   /// CHECK:  <<SubARet:i\d+>>      IntConstant 42
44*795d594fSAndroid Build Coastguard Worker   /// CHECK:  <<Obj:l\d+>>          NullCheck
45*795d594fSAndroid Build Coastguard Worker   /// CHECK:  <<ObjClass:l\d+>>     InstanceFieldGet [<<Obj>>] field_name:java.lang.Object.shadow$_klass_
46*795d594fSAndroid Build Coastguard Worker   /// CHECK:  <<InlineClass:l\d+>>  LoadClass class_name:SubA
47*795d594fSAndroid Build Coastguard Worker   /// CHECK:  <<Test:z\d+>>         NotEqual [<<InlineClass>>,<<ObjClass>>]
48*795d594fSAndroid Build Coastguard Worker   /// CHECK:  <<DefaultRet:i\d+>>   InvokeVirtual [<<Obj>>] method_name:Super.getValue
49*795d594fSAndroid Build Coastguard Worker 
50*795d594fSAndroid Build Coastguard Worker   /// CHECK:  <<Ret:i\d+>>          Phi [<<SubARet>>,<<DefaultRet>>]
51*795d594fSAndroid Build Coastguard Worker   /// CHECK:                        Return [<<Ret>>]
52*795d594fSAndroid Build Coastguard Worker 
53*795d594fSAndroid Build Coastguard Worker   /// CHECK-NOT:                    Deoptimize
inlineMonomorphicSubA(Super a)54*795d594fSAndroid Build Coastguard Worker   public static int inlineMonomorphicSubA(Super a) {
55*795d594fSAndroid Build Coastguard Worker     return a.getValue();
56*795d594fSAndroid Build Coastguard Worker   }
57*795d594fSAndroid Build Coastguard Worker 
58*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.inlinePolymophicSubASubB(Super) inliner (before)
59*795d594fSAndroid Build Coastguard Worker   /// CHECK:       InvokeVirtual method_name:Super.getValue
60*795d594fSAndroid Build Coastguard Worker 
61*795d594fSAndroid Build Coastguard Worker   // Note that the order in which the types are added to the inline cache in the profile matters.
62*795d594fSAndroid Build Coastguard Worker 
63*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.inlinePolymophicSubASubB(Super) inliner (after)
64*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:  <<SubARet:i\d+>>          IntConstant 42
65*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:  <<SubBRet:i\d+>>          IntConstant 38
66*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:   <<Obj:l\d+>>             NullCheck
67*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:   <<ObjClassSubA:l\d+>>    InstanceFieldGet [<<Obj>>] field_name:java.lang.Object.shadow$_klass_
68*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:   <<InlineClassSubA:l\d+>> LoadClass class_name:SubA
69*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:   <<TestSubA:z\d+>>        NotEqual [<<InlineClassSubA>>,<<ObjClassSubA>>]
70*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                            If [<<TestSubA>>]
71*795d594fSAndroid Build Coastguard Worker 
72*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:   <<ObjClassSubB:l\d+>>    InstanceFieldGet field_name:java.lang.Object.shadow$_klass_
73*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:   <<InlineClassSubB:l\d+>> LoadClass class_name:SubB
74*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:   <<TestSubB:z\d+>>        NotEqual [<<InlineClassSubB>>,<<ObjClassSubB>>]
75*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:   <<DefaultRet:i\d+>>      InvokeVirtual [<<Obj>>] method_name:Super.getValue
76*795d594fSAndroid Build Coastguard Worker 
77*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:  <<FirstMerge:i\d+>>       Phi [<<SubBRet>>,<<DefaultRet>>]
78*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:  <<Ret:i\d+>>              Phi [<<SubARet>>,<<FirstMerge>>]
79*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                            Return [<<Ret>>]
80*795d594fSAndroid Build Coastguard Worker 
81*795d594fSAndroid Build Coastguard Worker   /// CHECK-NOT:                            Deoptimize
inlinePolymophicSubASubB(Super a)82*795d594fSAndroid Build Coastguard Worker   public static int inlinePolymophicSubASubB(Super a) {
83*795d594fSAndroid Build Coastguard Worker     return a.getValue();
84*795d594fSAndroid Build Coastguard Worker   }
85*795d594fSAndroid Build Coastguard Worker 
86*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.inlinePolymophicCrossDexSubASubC(Super) inliner (before)
87*795d594fSAndroid Build Coastguard Worker   /// CHECK:       InvokeVirtual method_name:Super.getValue
88*795d594fSAndroid Build Coastguard Worker 
89*795d594fSAndroid Build Coastguard Worker   // Note that the order in which the types are added to the inline cache in the profile matters.
90*795d594fSAndroid Build Coastguard Worker 
91*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.inlinePolymophicCrossDexSubASubC(Super) inliner (after)
92*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:  <<SubARet:i\d+>>          IntConstant 42
93*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:  <<SubCRet:i\d+>>          IntConstant 24
94*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:  <<Obj:l\d+>>              NullCheck
95*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:  <<ObjClassSubA:l\d+>>     InstanceFieldGet [<<Obj>>] field_name:java.lang.Object.shadow$_klass_
96*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:  <<InlineClassSubA:l\d+>>  LoadClass class_name:SubA
97*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:  <<TestSubA:z\d+>>         NotEqual [<<InlineClassSubA>>,<<ObjClassSubA>>]
98*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                            If [<<TestSubA>>]
99*795d594fSAndroid Build Coastguard Worker 
100*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:  <<ObjClassSubC:l\d+>>     InstanceFieldGet field_name:java.lang.Object.shadow$_klass_
101*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:  <<InlineClassSubC:l\d+>>  LoadClass class_name:SubC
102*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:  <<TestSubC:z\d+>>         NotEqual [<<InlineClassSubC>>,<<ObjClassSubC>>]
103*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:  <<DefaultRet:i\d+>>       InvokeVirtual [<<Obj>>] method_name:Super.getValue
104*795d594fSAndroid Build Coastguard Worker 
105*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:  <<FirstMerge:i\d+>>       Phi [<<SubCRet>>,<<DefaultRet>>]
106*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:  <<Ret:i\d+>>              Phi [<<SubARet>>,<<FirstMerge>>]
107*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                            Return [<<Ret>>]
108*795d594fSAndroid Build Coastguard Worker 
109*795d594fSAndroid Build Coastguard Worker   /// CHECK-NOT:                            Deoptimize
inlinePolymophicCrossDexSubASubC(Super a)110*795d594fSAndroid Build Coastguard Worker   public static int inlinePolymophicCrossDexSubASubC(Super a) {
111*795d594fSAndroid Build Coastguard Worker     return a.getValue();
112*795d594fSAndroid Build Coastguard Worker   }
113*795d594fSAndroid Build Coastguard Worker 
114*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.inlineMegamorphic(Super) inliner (before)
115*795d594fSAndroid Build Coastguard Worker   /// CHECK:       InvokeVirtual method_name:Super.getValue
116*795d594fSAndroid Build Coastguard Worker 
117*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.inlineMegamorphic(Super) inliner (after)
118*795d594fSAndroid Build Coastguard Worker   /// CHECK:       InvokeVirtual method_name:Super.getValue
inlineMegamorphic(Super a)119*795d594fSAndroid Build Coastguard Worker   public static int inlineMegamorphic(Super a) {
120*795d594fSAndroid Build Coastguard Worker     return a.getValue();
121*795d594fSAndroid Build Coastguard Worker   }
122*795d594fSAndroid Build Coastguard Worker 
123*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.inlineMissingTypes(Super) inliner (before)
124*795d594fSAndroid Build Coastguard Worker   /// CHECK:       InvokeVirtual method_name:Super.getValue
125*795d594fSAndroid Build Coastguard Worker 
126*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.inlineMissingTypes(Super) inliner (after)
127*795d594fSAndroid Build Coastguard Worker   /// CHECK:       InvokeVirtual method_name:Super.getValue
inlineMissingTypes(Super a)128*795d594fSAndroid Build Coastguard Worker   public static int inlineMissingTypes(Super a) {
129*795d594fSAndroid Build Coastguard Worker     return a.getValue();
130*795d594fSAndroid Build Coastguard Worker   }
131*795d594fSAndroid Build Coastguard Worker 
132*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.noInlineCache(Super) inliner (before)
133*795d594fSAndroid Build Coastguard Worker   /// CHECK:       InvokeVirtual method_name:Super.getValue
134*795d594fSAndroid Build Coastguard Worker 
135*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.noInlineCache(Super) inliner (after)
136*795d594fSAndroid Build Coastguard Worker   /// CHECK:       InvokeVirtual method_name:Super.getValue
noInlineCache(Super a)137*795d594fSAndroid Build Coastguard Worker   public static int noInlineCache(Super a) {
138*795d594fSAndroid Build Coastguard Worker     return a.getValue();
139*795d594fSAndroid Build Coastguard Worker   }
140*795d594fSAndroid Build Coastguard Worker 
141*795d594fSAndroid Build Coastguard Worker   // We shouldn't inline `someSubclassesThrow` since we are trying a monomorphic inline and it
142*795d594fSAndroid Build Coastguard Worker   // always throws for SubA. However, we shouldn't mark it as `always_throws` since we speculatively
143*795d594fSAndroid Build Coastguard Worker   // tried to inline and other subclasses (e.g. SubB) can call noInlineSomeSubclassesThrow and they
144*795d594fSAndroid Build Coastguard Worker   // don't throw.
145*795d594fSAndroid Build Coastguard Worker 
146*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: void Main.noInlineSomeSubclassesThrow(Super) inliner (before)
147*795d594fSAndroid Build Coastguard Worker   /// CHECK:       InvokeVirtual method_name:Super.someSubclassesThrow always_throws:false
148*795d594fSAndroid Build Coastguard Worker 
149*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: void Main.noInlineSomeSubclassesThrow(Super) inliner (after)
150*795d594fSAndroid Build Coastguard Worker   /// CHECK:       InvokeVirtual method_name:Super.someSubclassesThrow always_throws:false
noInlineSomeSubclassesThrow(Super a)151*795d594fSAndroid Build Coastguard Worker   public static void noInlineSomeSubclassesThrow(Super a) throws Error {
152*795d594fSAndroid Build Coastguard Worker     a.someSubclassesThrow();
153*795d594fSAndroid Build Coastguard Worker   }
154*795d594fSAndroid Build Coastguard Worker 
testInlineMonomorphic()155*795d594fSAndroid Build Coastguard Worker   public static void testInlineMonomorphic() {
156*795d594fSAndroid Build Coastguard Worker     if (inlineMonomorphicSubA(new SubA()) != 42) {
157*795d594fSAndroid Build Coastguard Worker       throw new Error("Expected 42");
158*795d594fSAndroid Build Coastguard Worker     }
159*795d594fSAndroid Build Coastguard Worker 
160*795d594fSAndroid Build Coastguard Worker     // Call with a different type than the one from the inline cache.
161*795d594fSAndroid Build Coastguard Worker     if (inlineMonomorphicSubA(new SubB()) != 38) {
162*795d594fSAndroid Build Coastguard Worker       throw new Error("Expected 38");
163*795d594fSAndroid Build Coastguard Worker     }
164*795d594fSAndroid Build Coastguard Worker   }
165*795d594fSAndroid Build Coastguard Worker 
testInlinePolymorhic()166*795d594fSAndroid Build Coastguard Worker   public static void testInlinePolymorhic() {
167*795d594fSAndroid Build Coastguard Worker     if (inlinePolymophicSubASubB(new SubA()) != 42) {
168*795d594fSAndroid Build Coastguard Worker       throw new Error("Expected 42");
169*795d594fSAndroid Build Coastguard Worker     }
170*795d594fSAndroid Build Coastguard Worker 
171*795d594fSAndroid Build Coastguard Worker     if (inlinePolymophicSubASubB(new SubB()) != 38) {
172*795d594fSAndroid Build Coastguard Worker       throw new Error("Expected 38");
173*795d594fSAndroid Build Coastguard Worker     }
174*795d594fSAndroid Build Coastguard Worker 
175*795d594fSAndroid Build Coastguard Worker     // Call with a different type than the one from the inline cache.
176*795d594fSAndroid Build Coastguard Worker     if (inlinePolymophicSubASubB(new SubC()) != 24) {
177*795d594fSAndroid Build Coastguard Worker       throw new Error("Expected 25");
178*795d594fSAndroid Build Coastguard Worker     }
179*795d594fSAndroid Build Coastguard Worker 
180*795d594fSAndroid Build Coastguard Worker     if (inlinePolymophicCrossDexSubASubC(new SubA()) != 42) {
181*795d594fSAndroid Build Coastguard Worker       throw new Error("Expected 42");
182*795d594fSAndroid Build Coastguard Worker     }
183*795d594fSAndroid Build Coastguard Worker 
184*795d594fSAndroid Build Coastguard Worker     if (inlinePolymophicCrossDexSubASubC(new SubC()) != 24) {
185*795d594fSAndroid Build Coastguard Worker       throw new Error("Expected 24");
186*795d594fSAndroid Build Coastguard Worker     }
187*795d594fSAndroid Build Coastguard Worker 
188*795d594fSAndroid Build Coastguard Worker     // Call with a different type than the one from the inline cache.
189*795d594fSAndroid Build Coastguard Worker     if (inlinePolymophicCrossDexSubASubC(new SubB()) != 38) {
190*795d594fSAndroid Build Coastguard Worker       throw new Error("Expected 38");
191*795d594fSAndroid Build Coastguard Worker     }
192*795d594fSAndroid Build Coastguard Worker   }
193*795d594fSAndroid Build Coastguard Worker 
testInlineMegamorphic()194*795d594fSAndroid Build Coastguard Worker   public static void testInlineMegamorphic() {
195*795d594fSAndroid Build Coastguard Worker     if (inlineMegamorphic(new SubA()) != 42) {
196*795d594fSAndroid Build Coastguard Worker       throw new Error("Expected 42");
197*795d594fSAndroid Build Coastguard Worker     }
198*795d594fSAndroid Build Coastguard Worker   }
199*795d594fSAndroid Build Coastguard Worker 
200*795d594fSAndroid Build Coastguard Worker 
testNoInlineCache()201*795d594fSAndroid Build Coastguard Worker   public static void testNoInlineCache() {
202*795d594fSAndroid Build Coastguard Worker     if (noInlineCache(new SubA()) != 42) {
203*795d594fSAndroid Build Coastguard Worker       throw new Error("Expected 42");
204*795d594fSAndroid Build Coastguard Worker     }
205*795d594fSAndroid Build Coastguard Worker   }
206*795d594fSAndroid Build Coastguard Worker 
$noinline$testsomeSubclassesThrow()207*795d594fSAndroid Build Coastguard Worker   private static void $noinline$testsomeSubclassesThrow() throws Exception {
208*795d594fSAndroid Build Coastguard Worker     try {
209*795d594fSAndroid Build Coastguard Worker       noInlineSomeSubclassesThrow(new SubA());
210*795d594fSAndroid Build Coastguard Worker       throw new Exception("Unreachable");
211*795d594fSAndroid Build Coastguard Worker     } catch (Error expected) {
212*795d594fSAndroid Build Coastguard Worker     }
213*795d594fSAndroid Build Coastguard Worker     noInlineSomeSubclassesThrow(new SubB());
214*795d594fSAndroid Build Coastguard Worker   }
215*795d594fSAndroid Build Coastguard Worker 
main(String[] args)216*795d594fSAndroid Build Coastguard Worker   public static void main(String[] args) throws Exception {
217*795d594fSAndroid Build Coastguard Worker     testInlineMonomorphic();
218*795d594fSAndroid Build Coastguard Worker     testInlinePolymorhic();
219*795d594fSAndroid Build Coastguard Worker     testInlineMegamorphic();
220*795d594fSAndroid Build Coastguard Worker     testNoInlineCache();
221*795d594fSAndroid Build Coastguard Worker     $noinline$testsomeSubclassesThrow();
222*795d594fSAndroid Build Coastguard Worker   }
223*795d594fSAndroid Build Coastguard Worker }
224