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 public static String smallString = generateString(100); 19 public static String mediumString = generateString(300); 20 public static String largeString = generateString(2000); 21 22 public static String smallNonAsciiString = generateNonAsciiString(100); 23 public static String mediumNonAsciiString = generateNonAsciiString(300); 24 public static String largeNonAsciiString = generateNonAsciiString(2000); 25 generateString(int length)26 public static String generateString(int length) { 27 // Generate a string in the ASCII range that will 28 // use string compression. 29 StringBuilder sb = new StringBuilder(); 30 for (int i = 0; i < length; i++) { 31 // Generate repeating alphabet. 32 sb.append(Character.valueOf((char)('a' + (i % 26)))); 33 } 34 return sb.toString(); 35 } 36 generateNonAsciiString(int length)37 public static String generateNonAsciiString(int length) { 38 StringBuilder sb = new StringBuilder(); 39 for (int i = 0; i < length; i++) { 40 sb.append(Character.valueOf('\uFFFF')); 41 } 42 return sb.toString(); 43 } 44 assertIntEquals(int expected, int result)45 public static void assertIntEquals(int expected, int result) { 46 if (expected != result) { 47 throw new Error("Expected: " + expected + ", found: " + result); 48 } 49 } 50 assertBooleanEquals(boolean expected, boolean result)51 public static void assertBooleanEquals(boolean expected, boolean result) { 52 if (expected != result) { 53 throw new Error("Expected: " + expected + ", found: " + result); 54 } 55 } 56 assertCharEquals(char expected, char result)57 public static void assertCharEquals(char expected, char result) { 58 if (expected != result) { 59 throw new Error("Expected: " + expected + ", found: " + result); 60 } 61 } 62 assertStringEquals(String expected, String result)63 public static void assertStringEquals(String expected, String result) { 64 if (!expected.equals(result)) { 65 throw new Error("Expected: " + expected + ", found: " + result); 66 } 67 } 68 assertStringContains(String searchTerm, String result)69 public static void assertStringContains(String searchTerm, String result) { 70 if (result == null || !result.contains(searchTerm)) { 71 throw new Error("Search term: " + searchTerm + ", not found in: " + result); 72 } 73 } 74 main(String[] args)75 public static void main(String[] args) { 76 stringEqualsSame(); 77 stringArgumentNotNull("Foo"); 78 79 assertIntEquals(0, $opt$noinline$getStringLength("")); 80 assertIntEquals(3, $opt$noinline$getStringLength("abc")); 81 assertIntEquals(10, $opt$noinline$getStringLength("0123456789")); 82 83 assertBooleanEquals(true, $opt$noinline$isStringEmpty("")); 84 assertBooleanEquals(false, $opt$noinline$isStringEmpty("abc")); 85 assertBooleanEquals(false, $opt$noinline$isStringEmpty("0123456789")); 86 87 assertCharEquals('a', $opt$noinline$stringCharAt("a", 0)); 88 assertCharEquals('a', $opt$noinline$stringCharAt("abc", 0)); 89 assertCharEquals('b', $opt$noinline$stringCharAt("abc", 1)); 90 assertCharEquals('c', $opt$noinline$stringCharAt("abc", 2)); 91 assertCharEquals('7', $opt$noinline$stringCharAt("0123456789", 7)); 92 93 // Single character. 94 assertStringEquals("a", stringGetCharsAndBack("a")); 95 // Strings < 8 characters. 96 assertStringEquals("foobar", stringGetCharsAndBack("foobar")); 97 // Strings > 8 characters of various lengths. 98 assertStringEquals(smallString, stringGetCharsAndBack(smallString)); 99 assertStringEquals(mediumString, stringGetCharsAndBack(mediumString)); 100 assertStringEquals(largeString, stringGetCharsAndBack(largeString)); 101 102 // Get only a substring: 103 // Substring < 8 characters. 104 assertStringEquals(smallString.substring(5, 10), stringGetCharsRange(smallString, 5, 10, 0)); 105 // Substring > 8 characters. 106 assertStringEquals(smallString.substring(7, 28), stringGetCharsRange(smallString, 7, 28, 0)); 107 108 // Get full string with offset in the char array. 109 assertStringEquals(smallString, stringGetCharsAndBackOffset(smallString, 17)); 110 111 // Get a substring with an offset in the char array. 112 // Substring < 8 characters. 113 assertStringEquals(smallString.substring(5, 10), stringGetCharsRange(smallString, 5, 10, 17)); 114 // Substring > 8 characters. 115 assertStringEquals(smallString.substring(7, 28), stringGetCharsRange(smallString, 7, 28, 17)); 116 117 // Single character. 118 assertStringEquals("\uFFFF", stringGetCharsAndBack("\uFFFF")); 119 120 // Strings < 8 characters. 121 assertStringEquals("\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF", 122 stringGetCharsAndBack("\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF")); 123 124 // Strings > 8 characters of various lengths. 125 assertStringEquals(smallNonAsciiString, stringGetCharsAndBack(smallNonAsciiString)); 126 assertStringEquals(mediumNonAsciiString, stringGetCharsAndBack(mediumNonAsciiString)); 127 assertStringEquals(largeNonAsciiString, stringGetCharsAndBack(largeNonAsciiString)); 128 129 // Get only a substring: 130 // Substring < 8 characters. 131 assertStringEquals(smallNonAsciiString.substring(5, 10), 132 stringGetCharsRange(smallNonAsciiString, 5, 10, 0)); 133 // Substring > 8 characters. 134 assertStringEquals(smallNonAsciiString.substring(7, 28), 135 stringGetCharsRange(smallNonAsciiString, 7, 28, 0)); 136 137 // Get full string with offset in the char array. 138 assertStringEquals(smallNonAsciiString, 139 stringGetCharsAndBackOffset(smallNonAsciiString, 17)); 140 141 // Get a substring with an offset in the char array. 142 // Substring < 8 characters. 143 assertStringEquals(smallNonAsciiString.substring(5, 10), 144 stringGetCharsRange(smallNonAsciiString, 5, 10, 17)); 145 // Substring > 8 characters. 146 assertStringEquals(smallNonAsciiString.substring(7, 28), 147 stringGetCharsRange(smallNonAsciiString, 7, 28, 17)); 148 149 try { 150 $opt$noinline$stringCharAt("abc", -1); 151 throw new Error("Should throw SIOOB."); 152 } catch (StringIndexOutOfBoundsException sioob) { 153 assertStringContains("java.lang.String.charAt", sioob.getStackTrace()[0].toString()); 154 assertStringContains("Main.$opt$noinline$stringCharAt", sioob.getStackTrace()[1].toString()); 155 } 156 try { 157 $opt$noinline$stringCharAt("abc", 3); 158 throw new Error("Should throw SIOOB."); 159 } catch (StringIndexOutOfBoundsException sioob) { 160 assertStringContains("java.lang.String.charAt", sioob.getStackTrace()[0].toString()); 161 assertStringContains("Main.$opt$noinline$stringCharAt", sioob.getStackTrace()[1].toString()); 162 } 163 try { 164 $opt$noinline$stringCharAt("abc", Integer.MAX_VALUE); 165 throw new Error("Should throw SIOOB."); 166 } catch (StringIndexOutOfBoundsException sioob) { 167 assertStringContains("java.lang.String.charAt", sioob.getStackTrace()[0].toString()); 168 assertStringContains("Main.$opt$noinline$stringCharAt", sioob.getStackTrace()[1].toString()); 169 } 170 171 assertCharEquals('7', $opt$noinline$stringCharAtCatch("0123456789", 7)); 172 assertCharEquals('\0', $opt$noinline$stringCharAtCatch("0123456789", 10)); 173 174 assertCharEquals('7', $opt$noinline$stringCharAtCatchPhiReturn("0123456789", 7)); 175 assertCharEquals('\0', $opt$noinline$stringCharAtCatchPhiReturn("0123456789", 10)); 176 177 assertIntEquals('a' + 'b' + 'c', $opt$noinline$stringSumChars("abc")); 178 assertIntEquals('a' + 'b' + 'c', $opt$noinline$stringSumLeadingChars("abcdef", 3)); 179 try { 180 $opt$noinline$stringSumLeadingChars("abcdef", 7); 181 throw new Error("Should throw SIOOB."); 182 } catch (StringIndexOutOfBoundsException sioob) { 183 assertStringContains("java.lang.String.charAt", sioob.getStackTrace()[0].toString()); 184 assertStringContains("Main.$opt$noinline$stringSumLeadingChars", 185 sioob.getStackTrace()[1].toString()); 186 } 187 assertIntEquals('a' + 'b' + 'c' + 'd', $opt$noinline$stringSum4LeadingChars("abcdef")); 188 try { 189 $opt$noinline$stringSum4LeadingChars("abc"); 190 throw new Error("Should throw SIOOB."); 191 } catch (StringIndexOutOfBoundsException sioob) { 192 assertStringContains("java.lang.String.charAt", sioob.getStackTrace()[0].toString()); 193 assertStringContains("Main.$opt$noinline$stringSum4LeadingChars", 194 sioob.getStackTrace()[1].toString()); 195 } 196 } 197 198 /// CHECK-START: int Main.$opt$noinline$getStringLength(java.lang.String) builder (after) 199 /// CHECK-DAG: <<String:l\d+>> ParameterValue 200 /// CHECK-DAG: <<NullCk:l\d+>> NullCheck [<<String>>] 201 /// CHECK-DAG: <<Length:i\d+>> ArrayLength [<<NullCk>>] is_string_length:true 202 /// CHECK-DAG: Return [<<Length>>] 203 204 /// CHECK-START: int Main.$opt$noinline$getStringLength(java.lang.String) builder (after) 205 /// CHECK-NOT: InvokeVirtual 206 $opt$noinline$getStringLength(String s)207 static public int $opt$noinline$getStringLength(String s) { 208 return s.length(); 209 } 210 211 /// CHECK-START: boolean Main.$opt$noinline$isStringEmpty(java.lang.String) builder (after) 212 /// CHECK-DAG: <<String:l\d+>> ParameterValue 213 /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 214 /// CHECK-DAG: <<NullCk:l\d+>> NullCheck [<<String>>] 215 /// CHECK-DAG: <<Length:i\d+>> ArrayLength [<<NullCk>>] is_string_length:true 216 /// CHECK-DAG: <<IsEmpty:z\d+>> Equal [<<Length>>,<<Const0>>] 217 /// CHECK-DAG: Return [<<IsEmpty>>] 218 219 /// CHECK-START: boolean Main.$opt$noinline$isStringEmpty(java.lang.String) builder (after) 220 /// CHECK-NOT: InvokeVirtual 221 $opt$noinline$isStringEmpty(String s)222 static public boolean $opt$noinline$isStringEmpty(String s) { 223 return s.isEmpty(); 224 } 225 226 /// CHECK-START: char Main.$opt$noinline$stringCharAt(java.lang.String, int) builder (after) 227 /// CHECK-DAG: <<String:l\d+>> ParameterValue 228 /// CHECK-DAG: <<Pos:i\d+>> ParameterValue 229 /// CHECK-DAG: <<NullCk:l\d+>> NullCheck [<<String>>] 230 /// CHECK-DAG: <<Length:i\d+>> ArrayLength [<<NullCk>>] is_string_length:true 231 /// CHECK-DAG: <<Bounds:i\d+>> BoundsCheck [<<Pos>>,<<Length>>] is_string_char_at:true 232 /// CHECK-DAG: <<Char:c\d+>> ArrayGet [<<NullCk>>,<<Bounds>>] is_string_char_at:true 233 /// CHECK-DAG: Return [<<Char>>] 234 235 /// CHECK-START: char Main.$opt$noinline$stringCharAt(java.lang.String, int) builder (after) 236 /// CHECK-NOT: InvokeVirtual 237 $opt$noinline$stringCharAt(String s, int pos)238 static public char $opt$noinline$stringCharAt(String s, int pos) { 239 return s.charAt(pos); 240 } 241 242 /// CHECK-START: char Main.$opt$noinline$stringCharAtCatch(java.lang.String, int) builder (after) 243 /// CHECK-DAG: <<String:l\d+>> ParameterValue 244 /// CHECK-DAG: <<Pos:i\d+>> ParameterValue 245 /// CHECK-DAG: <<NullCk:l\d+>> NullCheck [<<String>>] 246 /// CHECK-DAG: <<Length:i\d+>> ArrayLength [<<NullCk>>] is_string_length:true 247 /// CHECK-DAG: <<Bounds:i\d+>> BoundsCheck [<<Pos>>,<<Length>>] is_string_char_at:true 248 /// CHECK-DAG: <<Char:c\d+>> ArrayGet [<<NullCk>>,<<Bounds>>] is_string_char_at:true 249 /// CHECK-DAG: Return [{{(c|i)\d+}}] 250 251 /// CHECK-START: char Main.$opt$noinline$stringCharAtCatch(java.lang.String, int) builder (after) 252 /// CHECK-NOT: InvokeVirtual 253 $opt$noinline$stringCharAtCatch(String s, int pos)254 static public char $opt$noinline$stringCharAtCatch(String s, int pos) { 255 try { 256 return s.charAt(pos); 257 } catch (StringIndexOutOfBoundsException ignored) { 258 return '\0'; 259 } 260 } 261 262 /// CHECK-START: char Main.$opt$noinline$stringCharAtCatchPhiReturn(java.lang.String, int) builder (after) 263 /// CHECK-DAG: <<String:l\d+>> ParameterValue 264 /// CHECK-DAG: <<Pos:i\d+>> ParameterValue 265 /// CHECK-DAG: <<Int:i\d+>> IntConstant 0 266 /// CHECK-DAG: <<NullCk:l\d+>> NullCheck [<<String>>] 267 /// CHECK-DAG: <<Length:i\d+>> ArrayLength [<<NullCk>>] is_string_length:true 268 /// CHECK-DAG: <<Bounds:i\d+>> BoundsCheck [<<Pos>>,<<Length>>] is_string_char_at:true 269 /// CHECK-DAG: <<Char:c\d+>> ArrayGet [<<NullCk>>,<<Bounds>>] is_string_char_at:true 270 /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Char>>,<<Int>>] 271 /// CHECK-DAG: Return [<<Phi>>] 272 273 /// CHECK-START: char Main.$opt$noinline$stringCharAtCatchPhiReturn(java.lang.String, int) instruction_simplifier (after) 274 /// CHECK-NOT: InvokeVirtual intrinsic:StringCharAt 275 $opt$noinline$stringCharAtCatchPhiReturn(String s, int pos)276 static public char $opt$noinline$stringCharAtCatchPhiReturn(String s, int pos) { 277 char result; 278 try { 279 result = s.charAt(pos); 280 } catch (StringIndexOutOfBoundsException ignored) { 281 result = '\0'; 282 } 283 return result; 284 } 285 286 /// CHECK-START: int Main.$opt$noinline$stringSumChars(java.lang.String) builder (after) 287 /// CHECK-DAG: ArrayLength is_string_length:true 288 /// CHECK-DAG: ArrayLength is_string_length:true 289 /// CHECK-DAG: BoundsCheck is_string_char_at:true 290 /// CHECK-DAG: ArrayGet is_string_char_at:true 291 292 /// CHECK-START: int Main.$opt$noinline$stringSumChars(java.lang.String) builder (after) 293 /// CHECK-NOT: InvokeVirtual 294 295 /// CHECK-START: int Main.$opt$noinline$stringSumChars(java.lang.String) GVN (after) 296 /// CHECK-DAG: ArrayLength is_string_length:true 297 /// CHECK-NOT: ArrayLength is_string_length:true 298 299 /// CHECK-START: int Main.$opt$noinline$stringSumChars(java.lang.String) BCE (after) 300 /// CHECK-NOT: BoundsCheck 301 $opt$noinline$stringSumChars(String s)302 static public int $opt$noinline$stringSumChars(String s) { 303 int sum = 0; 304 int len = s.length(); 305 for (int i = 0; i < len; ++i) { 306 sum += s.charAt(i); 307 } 308 return sum; 309 } 310 311 /// CHECK-START: int Main.$opt$noinline$stringSumLeadingChars(java.lang.String, int) builder (after) 312 /// CHECK-DAG: ArrayLength is_string_length:true 313 /// CHECK-DAG: BoundsCheck is_string_char_at:true 314 /// CHECK-DAG: ArrayGet is_string_char_at:true 315 316 /// CHECK-START: int Main.$opt$noinline$stringSumLeadingChars(java.lang.String, int) builder (after) 317 /// CHECK-NOT: InvokeVirtual 318 319 /// CHECK-START: int Main.$opt$noinline$stringSumLeadingChars(java.lang.String, int) BCE (after) 320 /// CHECK-DAG: Deoptimize env:[[{{[^\]]*}}]] 321 322 /// CHECK-START: int Main.$opt$noinline$stringSumLeadingChars(java.lang.String, int) BCE (after) 323 /// CHECK-NOT: BoundsCheck is_string_char_at:true 324 $opt$noinline$stringSumLeadingChars(String s, int n)325 static public int $opt$noinline$stringSumLeadingChars(String s, int n) { 326 int sum = 0; 327 for (int i = 0; i < n; ++i) { 328 sum += s.charAt(i); 329 } 330 return sum; 331 } 332 333 /// CHECK-START: int Main.$opt$noinline$stringSum4LeadingChars(java.lang.String) builder (after) 334 /// CHECK-DAG: ArrayLength is_string_length:true 335 /// CHECK-DAG: BoundsCheck is_string_char_at:true 336 /// CHECK-DAG: ArrayGet is_string_char_at:true 337 /// CHECK-DAG: ArrayLength is_string_length:true 338 /// CHECK-DAG: BoundsCheck is_string_char_at:true 339 /// CHECK-DAG: ArrayGet is_string_char_at:true 340 /// CHECK-DAG: ArrayLength is_string_length:true 341 /// CHECK-DAG: BoundsCheck is_string_char_at:true 342 /// CHECK-DAG: ArrayGet is_string_char_at:true 343 /// CHECK-DAG: ArrayLength is_string_length:true 344 /// CHECK-DAG: BoundsCheck is_string_char_at:true 345 /// CHECK-DAG: ArrayGet is_string_char_at:true 346 347 /// CHECK-START: int Main.$opt$noinline$stringSum4LeadingChars(java.lang.String) builder (after) 348 /// CHECK-NOT: InvokeVirtual 349 350 /// CHECK-START: int Main.$opt$noinline$stringSum4LeadingChars(java.lang.String) BCE (after) 351 /// CHECK-DAG: Deoptimize env:[[{{[^\]]*}}]] 352 353 /// CHECK-START: int Main.$opt$noinline$stringSum4LeadingChars(java.lang.String) BCE (after) 354 /// CHECK-NOT: BoundsCheck is_string_char_at:true 355 $opt$noinline$stringSum4LeadingChars(String s)356 static public int $opt$noinline$stringSum4LeadingChars(String s) { 357 int sum = s.charAt(0) + s.charAt(1) + s.charAt(2) + s.charAt(3); 358 return sum; 359 } 360 361 /// CHECK-START: boolean Main.stringEqualsSame() instruction_simplifier (before) 362 /// CHECK: InvokeStaticOrDirect 363 364 /// CHECK-START: boolean Main.stringEqualsSame() register (before) 365 /// CHECK: <<Const1:i\d+>> IntConstant 1 366 /// CHECK: Return [<<Const1>>] 367 368 /// CHECK-START: boolean Main.stringEqualsSame() register (before) 369 /// CHECK-NOT: InvokeStaticOrDirect stringEqualsSame()370 public static boolean stringEqualsSame() { 371 return $inline$callStringEquals("obj", "obj"); 372 } 373 374 /// CHECK-START: boolean Main.stringEqualsNull() register (after) 375 /// CHECK: <<Invoke:z\d+>> InvokeVirtual 376 /// CHECK: Return [<<Invoke>>] stringEqualsNull()377 public static boolean stringEqualsNull() { 378 String o = (String)myObject; 379 return $inline$callStringEquals(o, o); 380 } 381 $inline$callStringEquals(String a, String b)382 public static boolean $inline$callStringEquals(String a, String b) { 383 return a.equals(b); 384 } 385 386 /// CHECK-START-X86: boolean Main.stringArgumentNotNull(java.lang.Object) disassembly (after) 387 /// CHECK: InvokeVirtual {{.*\.equals.*}} intrinsic:StringEquals 388 /// CHECK-NOT: test 389 390 /// CHECK-START-X86_64: boolean Main.stringArgumentNotNull(java.lang.Object) disassembly (after) 391 /// CHECK: InvokeVirtual {{.*\.equals.*}} intrinsic:StringEquals 392 /// CHECK-NOT: test 393 394 /// CHECK-START-ARM: boolean Main.stringArgumentNotNull(java.lang.Object) disassembly (after) 395 /// CHECK: InvokeVirtual {{.*\.equals.*}} intrinsic:StringEquals 396 // CompareAndBranchIfZero() may emit either CBZ or CMP+BEQ. 397 /// CHECK-NOT: cbz 398 /// CHECK-NOT: cmp {{r\d+}}, #0 399 // Terminate the scope for the CHECK-NOT search at the reference or length comparison, 400 // whichever comes first. 401 /// CHECK: cmp {{r\d+}}, {{r\d+}} 402 403 /// CHECK-START-ARM64: boolean Main.stringArgumentNotNull(java.lang.Object) disassembly (after) 404 /// CHECK: InvokeVirtual {{.*\.equals.*}} intrinsic:StringEquals 405 /// CHECK-NOT: cbz 406 // Terminate the scope for the CHECK-NOT search at the reference or length comparison, 407 // whichever comes first. 408 /// CHECK: cmp {{w.*,}} {{w.*|#.*}} stringArgumentNotNull(Object obj)409 public static boolean stringArgumentNotNull(Object obj) { 410 obj.getClass(); 411 return "foo".equals(obj); 412 } 413 414 // Test is very brittle as it depends on the order we emit instructions. 415 /// CHECK-START-X86: boolean Main.stringArgumentIsString() disassembly (after) 416 /// CHECK: InvokeVirtual intrinsic:StringEquals 417 /// CHECK: test 418 /// CHECK: jz/eq 419 // Check that we don't try to compare the classes. 420 /// CHECK-NOT: mov 421 /// CHECK: cmp 422 423 // Test is very brittle as it depends on the order we emit instructions. 424 /// CHECK-START-X86_64: boolean Main.stringArgumentIsString() disassembly (after) 425 /// CHECK: InvokeVirtual intrinsic:StringEquals 426 /// CHECK: test 427 /// CHECK: jz/eq 428 // Check that we don't try to compare the classes. 429 /// CHECK-NOT: mov 430 /// CHECK: cmp 431 432 // Test is brittle as it depends on the class offset being 0. 433 /// CHECK-START-ARM: boolean Main.stringArgumentIsString() disassembly (after) 434 /// CHECK: InvokeVirtual intrinsic:StringEquals 435 /// CHECK: {{cbz|cmp}} 436 // Check that we don't try to compare the classes. 437 // The dissassembler currently explicitly emits the offset 0 but don't rely on it. 438 // We want to terminate the CHECK-NOT search after two CMPs, one for reference 439 // equality and one for length comparison but these may be emitted in different order, 440 // so repeat the check twice. 441 /// CHECK-NOT: ldr{{(|.w)}} {{r\d+}}, [{{r\d+}}] 442 /// CHECK-NOT: ldr{{(|.w)}} {{r\d+}}, [{{r\d+}}, #0] 443 /// CHECK: cmp {{r\d+}}, {{r\d+}} 444 /// CHECK-NOT: ldr{{(|.w)}} {{r\d+}}, [{{r\d+}}] 445 /// CHECK-NOT: ldr{{(|.w)}} {{r\d+}}, [{{r\d+}}, #0] 446 /// CHECK: cmp {{r\d+}}, {{r\d+}} 447 448 // Test is brittle as it depends on the class offset being 0. 449 /// CHECK-START-ARM64: boolean Main.stringArgumentIsString() disassembly (after) 450 /// CHECK: InvokeVirtual intrinsic:StringEquals 451 /// CHECK: cbz 452 // Check that we don't try to compare the classes. 453 // The dissassembler currently does not explicitly emits the offset 0 but don't rely on it. 454 // We want to terminate the CHECK-NOT search after two CMPs, one for reference 455 // equality and one for length comparison but these may be emitted in different order, 456 // so repeat the check twice. 457 /// CHECK-NOT: ldr {{w\d+}}, [{{x\d+}}] 458 /// CHECK-NOT: ldr {{w\d+}}, [{{x\d+}}, #0] 459 /// CHECK: cmp {{w\d+}}, {{w\d+|#.*}} 460 /// CHECK-NOT: ldr {{w\d+}}, [{{x\d+}}] 461 /// CHECK-NOT: ldr {{w\d+}}, [{{x\d+}}, #0] 462 /// CHECK: cmp {{w\d+}}, {{w\d+|#.*}} stringArgumentIsString()463 public static boolean stringArgumentIsString() { 464 return "foo".equals(myString); 465 } 466 467 static String myString; 468 static Object myObject; 469 stringGetCharsAndBack(String src)470 public static String stringGetCharsAndBack(String src) { 471 char[] dst = new char[src.length()]; 472 src.getChars(0, src.length(), dst, 0); 473 return new String(dst); 474 } 475 stringGetCharsAndBackOffset(String src, int offset)476 public static String stringGetCharsAndBackOffset(String src, int offset) { 477 char[] dst = new char[src.length() + offset]; 478 src.getChars(0, src.length(), dst, offset); 479 return new String(dst, offset, src.length()); 480 } 481 stringGetCharsRange(String src, int srcBegin, int srcEnd, int offset)482 public static String stringGetCharsRange(String src, int srcBegin, int srcEnd, int offset) { 483 char[] dst = new char[srcEnd - srcBegin + offset]; 484 src.getChars(srcBegin, srcEnd, dst, offset); 485 return new String(dst, offset, srcEnd - srcBegin); 486 } 487 } 488