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