1 /*
2  * Copyright (C) 2017 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 class SubA extends Super {
getValue()18   int getValue() { return 42; }
19 }
20 
21 class SubB extends Super {
getValue()22   int getValue() { return 38; }
23 }
24 
25 class SubD extends Super {
getValue()26   int getValue() { return 10; }
27 }
28 
29 class SubE extends Super {
getValue()30   int getValue() { return -4; }
31 }
32 
33 public class Main {
34 
35   /// CHECK-START: int Main.inlineMonomorphicSubA(Super) inliner (before)
36   /// CHECK:       InvokeVirtual method_name:Super.getValue
37 
38   /// CHECK-START: int Main.inlineMonomorphicSubA(Super) inliner (after)
39   /// CHECK:  <<SubARet:i\d+>>      IntConstant 42
40   /// CHECK:  <<Obj:l\d+>>          NullCheck
41   /// CHECK:  <<ObjClass:l\d+>>     InstanceFieldGet [<<Obj>>] field_name:java.lang.Object.shadow$_klass_
42   /// CHECK:  <<InlineClass:l\d+>>  LoadClass class_name:SubA
43   /// CHECK:  <<Test:z\d+>>         NotEqual [<<InlineClass>>,<<ObjClass>>]
44   /// CHECK:  <<DefaultRet:i\d+>>   InvokeVirtual [<<Obj>>] method_name:Super.getValue
45 
46   /// CHECK:  <<Ret:i\d+>>          Phi [<<SubARet>>,<<DefaultRet>>]
47   /// CHECK:                        Return [<<Ret>>]
48 
49   /// CHECK-NOT:                    Deoptimize
inlineMonomorphicSubA(Super a)50   public static int inlineMonomorphicSubA(Super a) {
51     return a.getValue();
52   }
53 
54   /// CHECK-START: int Main.inlinePolymophicSubASubB(Super) inliner (before)
55   /// CHECK:       InvokeVirtual method_name:Super.getValue
56 
57   // Note that the order in which the types are added to the inline cache in the profile matters.
58 
59   /// CHECK-START: int Main.inlinePolymophicSubASubB(Super) inliner (after)
60   /// CHECK-DAG:  <<SubARet:i\d+>>          IntConstant 42
61   /// CHECK-DAG:  <<SubBRet:i\d+>>          IntConstant 38
62   /// CHECK-DAG:   <<Obj:l\d+>>             NullCheck
63   /// CHECK-DAG:   <<ObjClassSubA:l\d+>>    InstanceFieldGet [<<Obj>>] field_name:java.lang.Object.shadow$_klass_
64   /// CHECK-DAG:   <<InlineClassSubA:l\d+>> LoadClass class_name:SubA
65   /// CHECK-DAG:   <<TestSubA:z\d+>>        NotEqual [<<InlineClassSubA>>,<<ObjClassSubA>>]
66   /// CHECK-DAG:                            If [<<TestSubA>>]
67 
68   /// CHECK-DAG:   <<ObjClassSubB:l\d+>>    InstanceFieldGet field_name:java.lang.Object.shadow$_klass_
69   /// CHECK-DAG:   <<InlineClassSubB:l\d+>> LoadClass class_name:SubB
70   /// CHECK-DAG:   <<TestSubB:z\d+>>        NotEqual [<<InlineClassSubB>>,<<ObjClassSubB>>]
71   /// CHECK-DAG:   <<DefaultRet:i\d+>>      InvokeVirtual [<<Obj>>] method_name:Super.getValue
72 
73   /// CHECK-DAG:  <<FirstMerge:i\d+>>       Phi [<<SubBRet>>,<<DefaultRet>>]
74   /// CHECK-DAG:  <<Ret:i\d+>>              Phi [<<SubARet>>,<<FirstMerge>>]
75   /// CHECK-DAG:                            Return [<<Ret>>]
76 
77   /// CHECK-NOT:                            Deoptimize
inlinePolymophicSubASubB(Super a)78   public static int inlinePolymophicSubASubB(Super a) {
79     return a.getValue();
80   }
81 
82   /// CHECK-START: int Main.inlinePolymophicCrossDexSubASubC(Super) inliner (before)
83   /// CHECK:       InvokeVirtual method_name:Super.getValue
84 
85   // Note that the order in which the types are added to the inline cache in the profile matters.
86 
87   /// CHECK-START: int Main.inlinePolymophicCrossDexSubASubC(Super) inliner (after)
88   /// CHECK-DAG:  <<SubARet:i\d+>>          IntConstant 42
89   /// CHECK-DAG:  <<SubCRet:i\d+>>          IntConstant 24
90   /// CHECK-DAG:  <<Obj:l\d+>>              NullCheck
91   /// CHECK-DAG:  <<ObjClassSubA:l\d+>>     InstanceFieldGet [<<Obj>>] field_name:java.lang.Object.shadow$_klass_
92   /// CHECK-DAG:  <<InlineClassSubA:l\d+>>  LoadClass class_name:SubA
93   /// CHECK-DAG:  <<TestSubA:z\d+>>         NotEqual [<<InlineClassSubA>>,<<ObjClassSubA>>]
94   /// CHECK-DAG:                            If [<<TestSubA>>]
95 
96   /// CHECK-DAG:  <<ObjClassSubC:l\d+>>     InstanceFieldGet field_name:java.lang.Object.shadow$_klass_
97   /// CHECK-DAG:  <<InlineClassSubC:l\d+>>  LoadClass class_name:SubC
98   /// CHECK-DAG:  <<TestSubC:z\d+>>         NotEqual [<<InlineClassSubC>>,<<ObjClassSubC>>]
99   /// CHECK-DAG:  <<DefaultRet:i\d+>>       InvokeVirtual [<<Obj>>] method_name:Super.getValue
100 
101   /// CHECK-DAG:  <<FirstMerge:i\d+>>       Phi [<<SubCRet>>,<<DefaultRet>>]
102   /// CHECK-DAG:  <<Ret:i\d+>>              Phi [<<SubARet>>,<<FirstMerge>>]
103   /// CHECK-DAG:                            Return [<<Ret>>]
104 
105   /// CHECK-NOT:                            Deoptimize
inlinePolymophicCrossDexSubASubC(Super a)106   public static int inlinePolymophicCrossDexSubASubC(Super a) {
107     return a.getValue();
108   }
109 
110   /// CHECK-START: int Main.inlineMegamorphic(Super) inliner (before)
111   /// CHECK:       InvokeVirtual method_name:Super.getValue
112 
113   /// CHECK-START: int Main.inlineMegamorphic(Super) inliner (after)
114   /// CHECK:       InvokeVirtual method_name:Super.getValue
inlineMegamorphic(Super a)115   public static int inlineMegamorphic(Super a) {
116     return a.getValue();
117   }
118 
119   /// CHECK-START: int Main.inlineMissingTypes(Super) inliner (before)
120   /// CHECK:       InvokeVirtual method_name:Super.getValue
121 
122   /// CHECK-START: int Main.inlineMissingTypes(Super) inliner (after)
123   /// CHECK:       InvokeVirtual method_name:Super.getValue
inlineMissingTypes(Super a)124   public static int inlineMissingTypes(Super a) {
125     return a.getValue();
126   }
127 
128   /// CHECK-START: int Main.noInlineCache(Super) inliner (before)
129   /// CHECK:       InvokeVirtual method_name:Super.getValue
130 
131   /// CHECK-START: int Main.noInlineCache(Super) inliner (after)
132   /// CHECK:       InvokeVirtual method_name:Super.getValue
noInlineCache(Super a)133   public static int noInlineCache(Super a) {
134     return a.getValue();
135   }
136 
testInlineMonomorphic()137   public static void testInlineMonomorphic() {
138     if (inlineMonomorphicSubA(new SubA()) != 42) {
139       throw new Error("Expected 42");
140     }
141 
142     // Call with a different type than the one from the inline cache.
143     if (inlineMonomorphicSubA(new SubB()) != 38) {
144       throw new Error("Expected 38");
145     }
146   }
147 
testInlinePolymorhic()148   public static void testInlinePolymorhic() {
149     if (inlinePolymophicSubASubB(new SubA()) != 42) {
150       throw new Error("Expected 42");
151     }
152 
153     if (inlinePolymophicSubASubB(new SubB()) != 38) {
154       throw new Error("Expected 38");
155     }
156 
157     // Call with a different type than the one from the inline cache.
158     if (inlinePolymophicSubASubB(new SubC()) != 24) {
159       throw new Error("Expected 25");
160     }
161 
162     if (inlinePolymophicCrossDexSubASubC(new SubA()) != 42) {
163       throw new Error("Expected 42");
164     }
165 
166     if (inlinePolymophicCrossDexSubASubC(new SubC()) != 24) {
167       throw new Error("Expected 24");
168     }
169 
170     // Call with a different type than the one from the inline cache.
171     if (inlinePolymophicCrossDexSubASubC(new SubB()) != 38) {
172       throw new Error("Expected 38");
173     }
174   }
175 
testInlineMegamorphic()176   public static void testInlineMegamorphic() {
177     if (inlineMegamorphic(new SubA()) != 42) {
178       throw new Error("Expected 42");
179     }
180   }
181 
182 
testNoInlineCache()183   public static void testNoInlineCache() {
184     if (noInlineCache(new SubA()) != 42) {
185       throw new Error("Expected 42");
186     }
187   }
188 
main(String[] args)189   public static void main(String[] args) {
190     testInlineMonomorphic();
191     testInlinePolymorhic();
192     testInlineMegamorphic();
193     testNoInlineCache();
194   }
195 
196 }
197