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-{ARM,ARM64,X86,X86_64}: int Main.testSimple(int) builder (after) 45 /// CHECK: InvokeStaticOrDirect method_load_kind:BssEntry 46 47 /// CHECK-START-X86: int Main.testSimple(int) pc_relative_fixups_x86 (before) 48 /// CHECK-NOT: X86ComputeBaseMethodAddress 49 50 /// CHECK-START-X86: int Main.testSimple(int) pc_relative_fixups_x86 (after) 51 /// CHECK: X86ComputeBaseMethodAddress 52 /// CHECK-NOT: X86ComputeBaseMethodAddress 53 testSimple(int x)54 public static int testSimple(int x) { 55 // This call should use PC-relative .bss array load to retrieve the target method. 56 return $noinline$foo(x); 57 } 58 59 /// CHECK-START-{ARM,ARM64,X86,X86_64}: int Main.testDiamond(boolean, int) builder (after) 60 /// CHECK: InvokeStaticOrDirect method_load_kind:BssEntry 61 /// CHECK: InvokeStaticOrDirect method_load_kind:BssEntry 62 63 /// CHECK-START-X86: int Main.testDiamond(boolean, int) pc_relative_fixups_x86 (before) 64 /// CHECK-NOT: X86ComputeBaseMethodAddress 65 66 /// CHECK-START-X86: int Main.testDiamond(boolean, int) pc_relative_fixups_x86 (after) 67 /// CHECK: X86ComputeBaseMethodAddress 68 /// CHECK-NOT: X86ComputeBaseMethodAddress 69 70 /// CHECK-START-X86: int Main.testDiamond(boolean, int) pc_relative_fixups_x86 (after) 71 /// CHECK: X86ComputeBaseMethodAddress 72 /// CHECK-NEXT: If 73 testDiamond(boolean negate, int x)74 public static int testDiamond(boolean negate, int x) { 75 // These calls should use PC-relative loads to retrieve the target method. 76 // PC-relative bases used by X86 should be pulled before the If. 77 if (negate) { 78 return $noinline$foo(-x); 79 } else { 80 return $noinline$foo(x); 81 } 82 } 83 84 /// CHECK-START-X86: int Main.testLoop(int[], int) pc_relative_fixups_x86 (before) 85 /// CHECK-NOT: X86ComputeBaseMethodAddress 86 87 /// CHECK-START-X86: int Main.testLoop(int[], int) pc_relative_fixups_x86 (after) 88 /// CHECK: X86ComputeBaseMethodAddress 89 /// CHECK-NOT: X86ComputeBaseMethodAddress 90 91 /// CHECK-START-X86: int Main.testLoop(int[], int) pc_relative_fixups_x86 (after) 92 /// CHECK: InvokeStaticOrDirect 93 /// CHECK-NOT: InvokeStaticOrDirect 94 95 /// CHECK-START-X86: int Main.testLoop(int[], int) pc_relative_fixups_x86 (after) 96 /// CHECK: ArrayLength 97 /// CHECK-NEXT: X86ComputeBaseMethodAddress 98 /// CHECK-NEXT: Goto 99 /// CHECK: begin_block 100 /// CHECK: InvokeStaticOrDirect method_load_kind:BssEntry 101 testLoop(int[] array, int x)102 public static int testLoop(int[] array, int x) { 103 // PC-relative bases used by X86 should be pulled before the loop. 104 for (int i : array) { 105 x += $noinline$foo(i); 106 } 107 return x; 108 } 109 110 /// CHECK-START-X86: int Main.testLoopWithDiamond(int[], boolean, int) pc_relative_fixups_x86 (before) 111 /// CHECK-NOT: X86ComputeBaseMethodAddress 112 113 /// CHECK-START-X86: int Main.testLoopWithDiamond(int[], boolean, int) pc_relative_fixups_x86 (after) 114 /// CHECK: If 115 /// CHECK: begin_block 116 /// CHECK: ArrayLength 117 /// CHECK-NEXT: X86ComputeBaseMethodAddress 118 /// CHECK-NEXT: Goto 119 testLoopWithDiamond(int[] array, boolean negate, int x)120 public static int testLoopWithDiamond(int[] array, boolean negate, int x) { 121 // PC-relative bases used by X86 should be pulled before the loop but not outside the if. 122 if (array != null) { 123 for (int i : array) { 124 if (negate) { 125 x += $noinline$foo(-i); 126 } else { 127 x += $noinline$foo(i); 128 } 129 } 130 } 131 return x; 132 } 133 134 /// CHECK-START-{ARM,ARM64,X86,X86_64}: java.lang.String Main.$noinline$getBootImageString() builder (after) 135 /// CHECK: LoadString load_kind:BootImageRelRo 136 $noinline$getBootImageString()137 public static String $noinline$getBootImageString() { 138 // Prevent inlining to avoid the string comparison being optimized away. 139 if (doThrow) { throw new Error(); } 140 // Empty string is known to be in the boot image. 141 return ""; 142 } 143 144 /// CHECK-START-{ARM,ARM64,X86,X86_64}: java.lang.String Main.$noinline$getNonBootImageString() builder (after) 145 /// CHECK: LoadString load_kind:BssEntry 146 147 /// CHECK-START-X86: java.lang.String Main.$noinline$getNonBootImageString() pc_relative_fixups_x86 (before) 148 /// CHECK-NOT: X86ComputeBaseMethodAddress 149 150 /// CHECK-START-X86: java.lang.String Main.$noinline$getNonBootImageString() pc_relative_fixups_x86 (after) 151 /// CHECK-DAG: X86ComputeBaseMethodAddress 152 /// CHECK-DAG: LoadString load_kind:BssEntry 153 $noinline$getNonBootImageString()154 public static String $noinline$getNonBootImageString() { 155 // Prevent inlining to avoid the string comparison being optimized away. 156 if (doThrow) { throw new Error(); } 157 // This string is not in the boot image. 158 return "non-boot-image-string"; 159 } 160 161 /// CHECK-START-{ARM,ARM64,X86,X86_64}: java.lang.Class Main.$noinline$getStringClass() builder (after) 162 /// CHECK: LoadClass load_kind:BootImageRelRo class_name:java.lang.String 163 $noinline$getStringClass()164 public static Class<?> $noinline$getStringClass() { 165 // Prevent inlining to avoid the string comparison being optimized away. 166 if (doThrow) { throw new Error(); } 167 // String class is known to be in the boot image. 168 return String.class; 169 } 170 171 /// CHECK-START-{ARM,ARM64,X86,X86_64}: java.lang.Class Main.$noinline$getOtherClass() builder (after) 172 /// CHECK: LoadClass load_kind:BssEntry class_name:Other 173 174 /// CHECK-START-X86: java.lang.Class Main.$noinline$getOtherClass() pc_relative_fixups_x86 (before) 175 /// CHECK-NOT: X86ComputeBaseMethodAddress 176 177 /// CHECK-START-X86: java.lang.Class Main.$noinline$getOtherClass() pc_relative_fixups_x86 (after) 178 /// CHECK-DAG: X86ComputeBaseMethodAddress 179 /// CHECK-DAG: LoadClass load_kind:BssEntry class_name:Other 180 $noinline$getOtherClass()181 public static Class<?> $noinline$getOtherClass() { 182 // Prevent inlining to avoid the string comparison being optimized away. 183 if (doThrow) { throw new Error(); } 184 // Other class is not in the boot image. 185 return Other.class; 186 } 187 188 /// CHECK-START-{ARM,ARM64,X86,X86_64}: java.lang.String Main.$noinline$toHexString(int) builder (after) 189 /// CHECK: InvokeStaticOrDirect method_load_kind:BootImageRelRo $noinline$toHexString(int value)190 public static String $noinline$toHexString(int value) { 191 return Integer.toString(value, 16); 192 } 193 194 /// CHECK-START-{ARM,ARM64,X86,X86_64}: java.lang.String Main.$noinline$toHexStringIndirect(int) builder (after) 195 /// CHECK: InvokeStaticOrDirect method_load_kind:BssEntry 196 197 /// CHECK-START-X86: java.lang.String Main.$noinline$toHexStringIndirect(int) pc_relative_fixups_x86 (before) 198 /// CHECK-NOT: X86ComputeBaseMethodAddress 199 200 /// CHECK-START-X86: java.lang.String Main.$noinline$toHexStringIndirect(int) pc_relative_fixups_x86 (after) 201 /// CHECK-DAG: X86ComputeBaseMethodAddress 202 /// CHECK-DAG: InvokeStaticOrDirect method_load_kind:BssEntry $noinline$toHexStringIndirect(int value)203 public static String $noinline$toHexStringIndirect(int value) { 204 return $noinline$toHexString(value); 205 } 206 main(String[] args)207 public static void main(String[] args) { 208 assertIntEquals(1, testSimple(1)); 209 assertIntEquals(1, testDiamond(false, 1)); 210 assertIntEquals(-1, testDiamond(true, 1)); 211 assertIntEquals(3, testLoop(new int[]{ 2 }, 1)); 212 assertIntEquals(8, testLoop(new int[]{ 3, 4 }, 1)); 213 assertIntEquals(1, testLoopWithDiamond(null, false, 1)); 214 assertIntEquals(3, testLoopWithDiamond(new int[]{ 2 }, false, 1)); 215 assertIntEquals(-6, testLoopWithDiamond(new int[]{ 3, 4 }, true, 1)); 216 assertStringEquals("", $noinline$getBootImageString()); 217 assertStringEquals("non-boot-image-string", $noinline$getNonBootImageString()); 218 assertClassEquals(String.class, $noinline$getStringClass()); 219 assertClassEquals(Other.class, $noinline$getOtherClass()); 220 assertStringEquals("12345678", $noinline$toHexString(0x12345678)); 221 assertStringEquals("76543210", $noinline$toHexStringIndirect(0x76543210)); 222 } 223 } 224 225 class Other { 226 } 227