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