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