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 public class Main {
$inline$classTypeTest(Object o)18   public static boolean $inline$classTypeTest(Object o) {
19     return o instanceof SubMain;
20   }
21 
$inline$interfaceTypeTest(Object o)22   public static boolean $inline$interfaceTypeTest(Object o) {
23     return o instanceof Itf;
24   }
25 
26   public static SubMain subMain;
27   public static Main mainField;
28   public static Unrelated unrelatedField;
29   public static FinalUnrelated finalUnrelatedField;
30 
31   /// CHECK-START: boolean Main.classTypeTestNull() register (after)
32   /// CHECK-DAG: <<Const:i\d+>> IntConstant 0
33   /// CHECK-DAG:                Return [<<Const>>]
classTypeTestNull()34   public static boolean classTypeTestNull() {
35     return $inline$classTypeTest(null);
36   }
37 
38   /// CHECK-START: boolean Main.classTypeTestExactMain() register (after)
39   /// CHECK-DAG: <<Const:i\d+>> IntConstant 0
40   /// CHECK-DAG:                Return [<<Const>>]
classTypeTestExactMain()41   public static boolean classTypeTestExactMain() {
42     return $inline$classTypeTest(new Main());
43   }
44 
45   /// CHECK-START: boolean Main.classTypeTestExactSubMain() register (after)
46   /// CHECK-DAG: <<Const:i\d+>> IntConstant 1
47   /// CHECK-DAG:                Return [<<Const>>]
classTypeTestExactSubMain()48   public static boolean classTypeTestExactSubMain() {
49     return $inline$classTypeTest(new SubMain());
50   }
51 
52   /// CHECK-START: boolean Main.classTypeTestSubMainOrNull() register (after)
53   /// CHECK-DAG: <<Value:z\d+>> NotEqual
54   /// CHECK-DAG:                Return [<<Value>>]
classTypeTestSubMainOrNull()55   public static boolean classTypeTestSubMainOrNull() {
56     return $inline$classTypeTest(subMain);
57   }
58 
59   /// CHECK-START: boolean Main.classTypeTestMainOrNull() register (after)
60   /// CHECK-DAG: <<Value:z\d+>> InstanceOf
61   /// CHECK-DAG:                Return [<<Value>>]
classTypeTestMainOrNull()62   public static boolean classTypeTestMainOrNull() {
63     return $inline$classTypeTest(mainField);
64   }
65 
66   /// CHECK-START: boolean Main.classTypeTestUnrelated() register (after)
67   /// CHECK-DAG: <<Const:i\d+>> IntConstant 0
68   /// CHECK-DAG:                Return [<<Const>>]
classTypeTestUnrelated()69   public static boolean classTypeTestUnrelated() {
70     return $inline$classTypeTest(unrelatedField);
71   }
72 
73   /// CHECK-START: boolean Main.classTypeTestFinalUnrelated() register (after)
74   /// CHECK-DAG: <<Const:i\d+>> IntConstant 0
75   /// CHECK-DAG:                Return [<<Const>>]
classTypeTestFinalUnrelated()76   public static boolean classTypeTestFinalUnrelated() {
77     return $inline$classTypeTest(finalUnrelatedField);
78   }
79 
80   /// CHECK-START: boolean Main.interfaceTypeTestNull() register (after)
81   /// CHECK-DAG: <<Const:i\d+>> IntConstant 0
82   /// CHECK-DAG:                Return [<<Const>>]
interfaceTypeTestNull()83   public static boolean interfaceTypeTestNull() {
84     return $inline$interfaceTypeTest(null);
85   }
86 
87   /// CHECK-START: boolean Main.interfaceTypeTestExactMain() register (after)
88   /// CHECK-DAG: <<Const:i\d+>> IntConstant 0
89   /// CHECK-DAG:                Return [<<Const>>]
interfaceTypeTestExactMain()90   public static boolean interfaceTypeTestExactMain() {
91     return $inline$interfaceTypeTest(new Main());
92   }
93 
94   /// CHECK-START: boolean Main.interfaceTypeTestExactSubMain() register (after)
95   /// CHECK-DAG: <<Const:i\d+>> IntConstant 1
96   /// CHECK-DAG:                Return [<<Const>>]
interfaceTypeTestExactSubMain()97   public static boolean interfaceTypeTestExactSubMain() {
98     return $inline$interfaceTypeTest(new SubMain());
99   }
100 
101   /// CHECK-START: boolean Main.interfaceTypeTestSubMainOrNull() register (after)
102   /// CHECK-DAG: <<Value:z\d+>> NotEqual
103   /// CHECK-DAG:                Return [<<Value>>]
interfaceTypeTestSubMainOrNull()104   public static boolean interfaceTypeTestSubMainOrNull() {
105     return $inline$interfaceTypeTest(subMain);
106   }
107 
108   /// CHECK-START: boolean Main.interfaceTypeTestMainOrNull() register (after)
109   /// CHECK-DAG: <<Value:z\d+>> InstanceOf
110   /// CHECK-DAG:                Return [<<Value>>]
interfaceTypeTestMainOrNull()111   public static boolean interfaceTypeTestMainOrNull() {
112     return $inline$interfaceTypeTest(mainField);
113   }
114 
115   /// CHECK-START: boolean Main.interfaceTypeTestUnrelated() register (after)
116   /// CHECK-DAG: <<Value:z\d+>> InstanceOf
117   /// CHECK-DAG:                Return [<<Value>>]
interfaceTypeTestUnrelated()118   public static boolean interfaceTypeTestUnrelated() {
119     // This method is the main difference between doing an instanceof on an interface
120     // or a class. We have to keep the instanceof in case a subclass of Unrelated
121     // implements the interface.
122     return $inline$interfaceTypeTest(unrelatedField);
123   }
124 
125   /// CHECK-START: boolean Main.interfaceTypeTestFinalUnrelated() register (after)
126   /// CHECK-DAG: <<Const:i\d+>> IntConstant 0
127   /// CHECK-DAG:                Return [<<Const>>]
interfaceTypeTestFinalUnrelated()128   public static boolean interfaceTypeTestFinalUnrelated() {
129     return $inline$interfaceTypeTest(finalUnrelatedField);
130   }
131 
132   // Check that we remove the LoadClass instruction from the graph.
133   /// CHECK-START: boolean Main.knownTestWithLoadedClass() register (after)
134   /// CHECK-NOT: LoadClass
knownTestWithLoadedClass()135   public static boolean knownTestWithLoadedClass() {
136     return new String() instanceof String;
137   }
138 
139   // Check that we do not remove the LoadClass instruction from the graph.
140   /// CHECK-START: boolean Main.knownTestWithUnloadedClass() register (after)
141   /// CHECK: <<Const:i\d+>> IntConstant 0
142   /// CHECK:                LoadClass
143   /// CHECK:                Return [<<Const>>]
knownTestWithUnloadedClass()144   public static boolean knownTestWithUnloadedClass() {
145     return $inline$returnUnrelated() instanceof String;
146   }
147 
$inline$returnUnrelated()148   public static Object $inline$returnUnrelated() {
149     return new Unrelated();
150   }
151 
expect(boolean expected, boolean actual)152   public static void expect(boolean expected, boolean actual) {
153     if (expected != actual) {
154       throw new Error("Unexpected result");
155     }
156   }
157 
main(String[] args)158   public static void main(String[] args) {
159     expect(false, classTypeTestNull());
160     expect(false, classTypeTestExactMain());
161     expect(true, classTypeTestExactSubMain());
162 
163     subMain = null;
164     expect(false, classTypeTestSubMainOrNull());
165     subMain = new SubMain();
166     expect(true, classTypeTestSubMainOrNull());
167 
168     mainField = null;
169     expect(false, classTypeTestMainOrNull());
170     mainField = new Main();
171     expect(false, classTypeTestMainOrNull());
172     mainField = new SubMain();
173     expect(true, classTypeTestMainOrNull());
174 
175     unrelatedField = null;
176     expect(false, classTypeTestUnrelated());
177     unrelatedField = new Unrelated();
178     expect(false, classTypeTestUnrelated());
179 
180     finalUnrelatedField = null;
181     expect(false, classTypeTestFinalUnrelated());
182     finalUnrelatedField = new FinalUnrelated();
183     expect(false, classTypeTestFinalUnrelated());
184 
185     expect(false, interfaceTypeTestNull());
186     expect(false, interfaceTypeTestExactMain());
187     expect(true, interfaceTypeTestExactSubMain());
188 
189     subMain = null;
190     expect(false, interfaceTypeTestSubMainOrNull());
191     subMain = new SubMain();
192     expect(true, interfaceTypeTestSubMainOrNull());
193 
194     mainField = null;
195     expect(false, interfaceTypeTestMainOrNull());
196     mainField = new Main();
197     expect(false, interfaceTypeTestMainOrNull());
198     mainField = new SubMain();
199     expect(true, interfaceTypeTestMainOrNull());
200 
201     unrelatedField = null;
202     expect(false, interfaceTypeTestUnrelated());
203     unrelatedField = new Unrelated();
204     expect(false, interfaceTypeTestUnrelated());
205 
206     finalUnrelatedField = null;
207     expect(false, interfaceTypeTestFinalUnrelated());
208     finalUnrelatedField = new FinalUnrelated();
209     expect(false, interfaceTypeTestFinalUnrelated());
210   }
211 }
212 
213 interface Itf {
214 }
215 
216 class SubMain extends Main implements Itf {
217 }
218 
219 class Unrelated {
220 }
221 
222 final class FinalUnrelated {
223 }
224