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