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 { 18 assertIntEquals(int expected, int result)19 public static void assertIntEquals(int expected, int result) { 20 if (expected != result) { 21 throw new Error("Expected: " + expected + ", found: " + result); 22 } 23 } 24 assertStringEquals(String expected, String result)25 public static void assertStringEquals(String expected, String result) { 26 if (expected != null ? !expected.equals(result) : result != null) { 27 throw new Error("Expected: " + expected + ", found: " + result); 28 } 29 } 30 assertClassEquals(Class<?> expected, Class<?> result)31 public static void assertClassEquals(Class<?> expected, Class<?> result) { 32 if (expected != result) { 33 throw new Error("Expected: " + expected + ", found: " + result); 34 } 35 } 36 37 public static boolean doThrow = false; 38 $noinline$foo(int x)39 private static int $noinline$foo(int x) { 40 if (doThrow) { throw new Error(); } 41 return x; 42 } 43 44 /// CHECK-START: int Main.testSimple(int) sharpening (before) 45 /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_via_method 46 47 /// CHECK-START-ARM: int Main.testSimple(int) sharpening (after) 48 /// CHECK-NOT: ArmDexCacheArraysBase 49 /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative 50 51 /// CHECK-START-ARM64: int Main.testSimple(int) sharpening (after) 52 /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative 53 54 /// CHECK-START-MIPS: int Main.testSimple(int) sharpening (after) 55 /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative 56 57 /// CHECK-START-MIPS64: int Main.testSimple(int) sharpening (after) 58 /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative 59 60 /// CHECK-START-X86: int Main.testSimple(int) sharpening (after) 61 /// CHECK-NOT: X86ComputeBaseMethodAddress 62 /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative 63 64 /// CHECK-START-X86_64: int Main.testSimple(int) sharpening (after) 65 /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative 66 67 /// CHECK-START-ARM: int Main.testSimple(int) dex_cache_array_fixups_arm (after) 68 /// CHECK: ArmDexCacheArraysBase 69 /// CHECK-NOT: ArmDexCacheArraysBase 70 71 /// CHECK-START-X86: int Main.testSimple(int) pc_relative_fixups_x86 (after) 72 /// CHECK: X86ComputeBaseMethodAddress 73 /// CHECK-NOT: X86ComputeBaseMethodAddress 74 testSimple(int x)75 public static int testSimple(int x) { 76 // This call should use PC-relative dex cache array load to retrieve the target method. 77 return $noinline$foo(x); 78 } 79 80 /// CHECK-START: int Main.testDiamond(boolean, int) sharpening (before) 81 /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_via_method 82 83 /// CHECK-START-ARM: int Main.testDiamond(boolean, int) sharpening (after) 84 /// CHECK-NOT: ArmDexCacheArraysBase 85 /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative 86 /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative 87 88 /// CHECK-START-ARM64: int Main.testDiamond(boolean, int) sharpening (after) 89 /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative 90 /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative 91 92 /// CHECK-START-MIPS: int Main.testDiamond(boolean, int) sharpening (after) 93 /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative 94 /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative 95 96 /// CHECK-START-MIPS64: int Main.testDiamond(boolean, int) sharpening (after) 97 /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative 98 /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative 99 100 /// CHECK-START-X86: int Main.testDiamond(boolean, int) sharpening (after) 101 /// CHECK-NOT: X86ComputeBaseMethodAddress 102 /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative 103 /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative 104 105 /// CHECK-START-X86_64: int Main.testDiamond(boolean, int) sharpening (after) 106 /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative 107 /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative 108 109 /// CHECK-START-ARM: int Main.testDiamond(boolean, int) dex_cache_array_fixups_arm (after) 110 /// CHECK: ArmDexCacheArraysBase 111 /// CHECK-NOT: ArmDexCacheArraysBase 112 113 /// CHECK-START-ARM: int Main.testDiamond(boolean, int) dex_cache_array_fixups_arm (after) 114 /// CHECK: ArmDexCacheArraysBase 115 /// CHECK-NEXT: If 116 117 /// CHECK-START-X86: int Main.testDiamond(boolean, int) pc_relative_fixups_x86 (after) 118 /// CHECK: X86ComputeBaseMethodAddress 119 /// CHECK-NOT: X86ComputeBaseMethodAddress 120 121 /// CHECK-START-X86: int Main.testDiamond(boolean, int) pc_relative_fixups_x86 (after) 122 /// CHECK: X86ComputeBaseMethodAddress 123 /// CHECK-NEXT: If 124 testDiamond(boolean negate, int x)125 public static int testDiamond(boolean negate, int x) { 126 // These calls should use PC-relative dex cache array loads to retrieve the target method. 127 // PC-relative bases used by ARM, MIPS and X86 should be pulled before the If. 128 if (negate) { 129 return $noinline$foo(-x); 130 } else { 131 return $noinline$foo(x); 132 } 133 } 134 135 /// CHECK-START-X86: int Main.testLoop(int[], int) pc_relative_fixups_x86 (before) 136 /// CHECK-NOT: X86ComputeBaseMethodAddress 137 138 /// CHECK-START-X86: int Main.testLoop(int[], int) pc_relative_fixups_x86 (after) 139 /// CHECK: X86ComputeBaseMethodAddress 140 /// CHECK-NOT: X86ComputeBaseMethodAddress 141 142 /// CHECK-START-X86: int Main.testLoop(int[], int) pc_relative_fixups_x86 (after) 143 /// CHECK: InvokeStaticOrDirect 144 /// CHECK-NOT: InvokeStaticOrDirect 145 146 /// CHECK-START-X86: int Main.testLoop(int[], int) pc_relative_fixups_x86 (after) 147 /// CHECK: ArrayLength 148 /// CHECK-NEXT: X86ComputeBaseMethodAddress 149 /// CHECK-NEXT: Goto 150 /// CHECK: begin_block 151 /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative 152 153 /// CHECK-START-ARM: int Main.testLoop(int[], int) dex_cache_array_fixups_arm (before) 154 /// CHECK-NOT: ArmDexCacheArraysBase 155 156 /// CHECK-START-ARM: int Main.testLoop(int[], int) dex_cache_array_fixups_arm (after) 157 /// CHECK: ArmDexCacheArraysBase 158 /// CHECK-NOT: ArmDexCacheArraysBase 159 160 /// CHECK-START-ARM: int Main.testLoop(int[], int) dex_cache_array_fixups_arm (after) 161 /// CHECK: InvokeStaticOrDirect 162 /// CHECK-NOT: InvokeStaticOrDirect 163 164 /// CHECK-START-ARM: int Main.testLoop(int[], int) dex_cache_array_fixups_arm (after) 165 /// CHECK: ArrayLength 166 /// CHECK-NEXT: ArmDexCacheArraysBase 167 /// CHECK-NEXT: Goto 168 /// CHECK: begin_block 169 /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative 170 testLoop(int[] array, int x)171 public static int testLoop(int[] array, int x) { 172 // PC-relative bases used by ARM, MIPS and X86 should be pulled before the loop. 173 for (int i : array) { 174 x += $noinline$foo(i); 175 } 176 return x; 177 } 178 179 /// CHECK-START-X86: int Main.testLoopWithDiamond(int[], boolean, int) pc_relative_fixups_x86 (before) 180 /// CHECK-NOT: X86ComputeBaseMethodAddress 181 182 /// CHECK-START-X86: int Main.testLoopWithDiamond(int[], boolean, int) pc_relative_fixups_x86 (after) 183 /// CHECK: If 184 /// CHECK: begin_block 185 /// CHECK: ArrayLength 186 /// CHECK-NEXT: X86ComputeBaseMethodAddress 187 /// CHECK-NEXT: Goto 188 189 /// CHECK-START-ARM: int Main.testLoopWithDiamond(int[], boolean, int) dex_cache_array_fixups_arm (before) 190 /// CHECK-NOT: ArmDexCacheArraysBase 191 192 /// CHECK-START-ARM: int Main.testLoopWithDiamond(int[], boolean, int) dex_cache_array_fixups_arm (after) 193 /// CHECK: If 194 /// CHECK: begin_block 195 /// CHECK: ArrayLength 196 /// CHECK-NEXT: ArmDexCacheArraysBase 197 /// CHECK-NEXT: Goto 198 testLoopWithDiamond(int[] array, boolean negate, int x)199 public static int testLoopWithDiamond(int[] array, boolean negate, int x) { 200 // PC-relative bases used by ARM, MIPS and X86 should be pulled before the loop 201 // but not outside the if. 202 if (array != null) { 203 for (int i : array) { 204 if (negate) { 205 x += $noinline$foo(-i); 206 } else { 207 x += $noinline$foo(i); 208 } 209 } 210 } 211 return x; 212 } 213 214 /// CHECK-START: java.lang.String Main.$noinline$getBootImageString() sharpening (before) 215 /// CHECK: LoadString load_kind:DexCacheViaMethod 216 217 /// CHECK-START-X86: java.lang.String Main.$noinline$getBootImageString() sharpening (after) 218 // Note: load kind depends on PIC/non-PIC 219 // TODO: Remove DexCacheViaMethod when read barrier config supports BootImageAddress. 220 /// CHECK: LoadString load_kind:{{BootImageAddress|BssEntry|DexCacheViaMethod}} 221 222 /// CHECK-START-X86_64: java.lang.String Main.$noinline$getBootImageString() sharpening (after) 223 // Note: load kind depends on PIC/non-PIC 224 // TODO: Remove DexCacheViaMethod when read barrier config supports BootImageAddress. 225 /// CHECK: LoadString load_kind:{{BootImageAddress|BssEntry|DexCacheViaMethod}} 226 227 /// CHECK-START-ARM: java.lang.String Main.$noinline$getBootImageString() sharpening (after) 228 // Note: load kind depends on PIC/non-PIC 229 // TODO: Remove DexCacheViaMethod when read barrier config supports BootImageAddress. 230 /// CHECK: LoadString load_kind:{{BootImageAddress|BssEntry|DexCacheViaMethod}} 231 232 /// CHECK-START-ARM64: java.lang.String Main.$noinline$getBootImageString() sharpening (after) 233 // Note: load kind depends on PIC/non-PIC 234 // TODO: Remove DexCacheViaMethod when read barrier config supports BootImageAddress. 235 /// CHECK: LoadString load_kind:{{BootImageAddress|BssEntry|DexCacheViaMethod}} 236 237 /// CHECK-START-MIPS: java.lang.String Main.$noinline$getBootImageString() sharpening (after) 238 // Note: load kind depends on PIC/non-PIC 239 // TODO: Remove DexCacheViaMethod when read barrier config supports BootImageAddress. 240 /// CHECK: LoadString load_kind:{{BootImageAddress|BssEntry|DexCacheViaMethod}} 241 242 /// CHECK-START-MIPS64: java.lang.String Main.$noinline$getBootImageString() sharpening (after) 243 // Note: load kind depends on PIC/non-PIC 244 // TODO: Remove DexCacheViaMethod when read barrier config supports BootImageAddress. 245 /// CHECK: LoadString load_kind:{{BootImageAddress|BssEntry|DexCacheViaMethod}} 246 $noinline$getBootImageString()247 public static String $noinline$getBootImageString() { 248 // Prevent inlining to avoid the string comparison being optimized away. 249 if (doThrow) { throw new Error(); } 250 // Empty string is known to be in the boot image. 251 return ""; 252 } 253 254 /// CHECK-START: java.lang.String Main.$noinline$getNonBootImageString() sharpening (before) 255 /// CHECK: LoadString load_kind:DexCacheViaMethod 256 257 /// CHECK-START-X86: java.lang.String Main.$noinline$getNonBootImageString() sharpening (after) 258 /// CHECK: LoadString load_kind:BssEntry 259 260 /// CHECK-START-X86: java.lang.String Main.$noinline$getNonBootImageString() pc_relative_fixups_x86 (after) 261 /// CHECK-DAG: X86ComputeBaseMethodAddress 262 /// CHECK-DAG: LoadString load_kind:BssEntry 263 264 /// CHECK-START-X86_64: java.lang.String Main.$noinline$getNonBootImageString() sharpening (after) 265 /// CHECK: LoadString load_kind:BssEntry 266 267 /// CHECK-START-ARM: java.lang.String Main.$noinline$getNonBootImageString() sharpening (after) 268 /// CHECK: LoadString load_kind:BssEntry 269 270 /// CHECK-START-ARM64: java.lang.String Main.$noinline$getNonBootImageString() sharpening (after) 271 /// CHECK: LoadString load_kind:BssEntry 272 273 /// CHECK-START-MIPS: java.lang.String Main.$noinline$getNonBootImageString() sharpening (after) 274 /// CHECK: LoadString load_kind:BssEntry 275 276 /// CHECK-START-MIPS64: java.lang.String Main.$noinline$getNonBootImageString() sharpening (after) 277 /// CHECK: LoadString load_kind:BssEntry 278 $noinline$getNonBootImageString()279 public static String $noinline$getNonBootImageString() { 280 // Prevent inlining to avoid the string comparison being optimized away. 281 if (doThrow) { throw new Error(); } 282 // This string is not in the boot image. 283 return "non-boot-image-string"; 284 } 285 286 /// CHECK-START-X86: java.lang.Class Main.$noinline$getStringClass() sharpening (after) 287 // Note: load kind depends on PIC/non-PIC 288 // TODO: Remove DexCacheViaMethod when read barrier config supports BootImageAddress. 289 /// CHECK: LoadClass load_kind:{{BootImageAddress|BssEntry|DexCacheViaMethod}} class_name:java.lang.String 290 291 /// CHECK-START-X86_64: java.lang.Class Main.$noinline$getStringClass() sharpening (after) 292 // Note: load kind depends on PIC/non-PIC 293 // TODO: Remove DexCacheViaMethod when read barrier config supports BootImageAddress. 294 /// CHECK: LoadClass load_kind:{{BootImageAddress|BssEntry|DexCacheViaMethod}} class_name:java.lang.String 295 296 /// CHECK-START-ARM: java.lang.Class Main.$noinline$getStringClass() sharpening (after) 297 // Note: load kind depends on PIC/non-PIC 298 // TODO: Remove DexCacheViaMethod when read barrier config supports BootImageAddress. 299 /// CHECK: LoadClass load_kind:{{BootImageAddress|BssEntry|DexCacheViaMethod}} class_name:java.lang.String 300 301 /// CHECK-START-ARM64: java.lang.Class Main.$noinline$getStringClass() sharpening (after) 302 // Note: load kind depends on PIC/non-PIC 303 // TODO: Remove DexCacheViaMethod when read barrier config supports BootImageAddress. 304 /// CHECK: LoadClass load_kind:{{BootImageAddress|BssEntry|DexCacheViaMethod}} class_name:java.lang.String 305 306 /// CHECK-START-MIPS: java.lang.Class Main.$noinline$getStringClass() sharpening (after) 307 // Note: load kind depends on PIC/non-PIC 308 // TODO: Remove DexCacheViaMethod when read barrier config supports BootImageAddress. 309 /// CHECK: LoadClass load_kind:{{BootImageAddress|BssEntry|DexCacheViaMethod}} class_name:java.lang.String 310 311 /// CHECK-START-MIPS64: java.lang.Class Main.$noinline$getStringClass() sharpening (after) 312 // Note: load kind depends on PIC/non-PIC 313 // TODO: Remove DexCacheViaMethod when read barrier config supports BootImageAddress. 314 /// CHECK: LoadClass load_kind:{{BootImageAddress|BssEntry|DexCacheViaMethod}} class_name:java.lang.String 315 $noinline$getStringClass()316 public static Class<?> $noinline$getStringClass() { 317 // Prevent inlining to avoid the string comparison being optimized away. 318 if (doThrow) { throw new Error(); } 319 // String class is known to be in the boot image. 320 return String.class; 321 } 322 323 /// CHECK-START-X86: java.lang.Class Main.$noinline$getOtherClass() sharpening (after) 324 /// CHECK: LoadClass load_kind:BssEntry class_name:Other 325 326 /// CHECK-START-X86: java.lang.Class Main.$noinline$getOtherClass() pc_relative_fixups_x86 (after) 327 /// CHECK-DAG: X86ComputeBaseMethodAddress 328 /// CHECK-DAG: LoadClass load_kind:BssEntry class_name:Other 329 330 /// CHECK-START-X86_64: java.lang.Class Main.$noinline$getOtherClass() sharpening (after) 331 /// CHECK: LoadClass load_kind:BssEntry class_name:Other 332 333 /// CHECK-START-ARM: java.lang.Class Main.$noinline$getOtherClass() sharpening (after) 334 /// CHECK: LoadClass load_kind:BssEntry class_name:Other 335 336 /// CHECK-START-ARM64: java.lang.Class Main.$noinline$getOtherClass() sharpening (after) 337 /// CHECK: LoadClass load_kind:BssEntry class_name:Other 338 339 /// CHECK-START-MIPS: java.lang.Class Main.$noinline$getOtherClass() sharpening (after) 340 /// CHECK: LoadClass load_kind:BssEntry class_name:Other 341 342 /// CHECK-START-MIPS64: java.lang.Class Main.$noinline$getOtherClass() sharpening (after) 343 /// CHECK: LoadClass load_kind:BssEntry class_name:Other 344 $noinline$getOtherClass()345 public static Class<?> $noinline$getOtherClass() { 346 // Prevent inlining to avoid the string comparison being optimized away. 347 if (doThrow) { throw new Error(); } 348 // Other class is not in the boot image. 349 return Other.class; 350 } 351 main(String[] args)352 public static void main(String[] args) { 353 assertIntEquals(1, testSimple(1)); 354 assertIntEquals(1, testDiamond(false, 1)); 355 assertIntEquals(-1, testDiamond(true, 1)); 356 assertIntEquals(3, testLoop(new int[]{ 2 }, 1)); 357 assertIntEquals(8, testLoop(new int[]{ 3, 4 }, 1)); 358 assertIntEquals(1, testLoopWithDiamond(null, false, 1)); 359 assertIntEquals(3, testLoopWithDiamond(new int[]{ 2 }, false, 1)); 360 assertIntEquals(-6, testLoopWithDiamond(new int[]{ 3, 4 }, true, 1)); 361 assertStringEquals("", $noinline$getBootImageString()); 362 assertStringEquals("non-boot-image-string", $noinline$getNonBootImageString()); 363 assertClassEquals(String.class, $noinline$getStringClass()); 364 assertClassEquals(Other.class, $noinline$getOtherClass()); 365 } 366 } 367 368 class Other { 369 } 370