You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

300 lines
11 KiB

/*
* Copyright 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
public class Main {
public static void main(String[] args) {
testAppendStringAndLong();
testAppendStringAndInt();
testAppendStringAndString();
testMiscelaneous();
testNoArgs();
testInline();
testEquals();
System.out.println("passed");
}
private static final String APPEND_LONG_PREFIX = "Long/";
private static final String[] APPEND_LONG_TEST_CASES = {
"Long/0",
"Long/1",
"Long/9",
"Long/10",
"Long/99",
"Long/100",
"Long/999",
"Long/1000",
"Long/9999",
"Long/10000",
"Long/99999",
"Long/100000",
"Long/999999",
"Long/1000000",
"Long/9999999",
"Long/10000000",
"Long/99999999",
"Long/100000000",
"Long/999999999",
"Long/1000000000",
"Long/9999999999",
"Long/10000000000",
"Long/99999999999",
"Long/100000000000",
"Long/999999999999",
"Long/1000000000000",
"Long/9999999999999",
"Long/10000000000000",
"Long/99999999999999",
"Long/100000000000000",
"Long/999999999999999",
"Long/1000000000000000",
"Long/9999999999999999",
"Long/10000000000000000",
"Long/99999999999999999",
"Long/100000000000000000",
"Long/999999999999999999",
"Long/1000000000000000000",
"Long/9223372036854775807", // Long.MAX_VALUE
"Long/-1",
"Long/-9",
"Long/-10",
"Long/-99",
"Long/-100",
"Long/-999",
"Long/-1000",
"Long/-9999",
"Long/-10000",
"Long/-99999",
"Long/-100000",
"Long/-999999",
"Long/-1000000",
"Long/-9999999",
"Long/-10000000",
"Long/-99999999",
"Long/-100000000",
"Long/-999999999",
"Long/-1000000000",
"Long/-9999999999",
"Long/-10000000000",
"Long/-99999999999",
"Long/-100000000000",
"Long/-999999999999",
"Long/-1000000000000",
"Long/-9999999999999",
"Long/-10000000000000",
"Long/-99999999999999",
"Long/-100000000000000",
"Long/-999999999999999",
"Long/-1000000000000000",
"Long/-9999999999999999",
"Long/-10000000000000000",
"Long/-99999999999999999",
"Long/-100000000000000000",
"Long/-999999999999999999",
"Long/-1000000000000000000",
"Long/-9223372036854775808", // Long.MIN_VALUE
};
/// CHECK-START: java.lang.String Main.$noinline$appendStringAndLong(java.lang.String, long) instruction_simplifier (before)
/// CHECK-NOT: StringBuilderAppend
/// CHECK-START: java.lang.String Main.$noinline$appendStringAndLong(java.lang.String, long) instruction_simplifier (after)
/// CHECK: StringBuilderAppend
public static String $noinline$appendStringAndLong(String s, long l) {
return new StringBuilder().append(s).append(l).toString();
}
public static void testAppendStringAndLong() {
for (String expected : APPEND_LONG_TEST_CASES) {
long l = Long.valueOf(expected.substring(APPEND_LONG_PREFIX.length()));
String result = $noinline$appendStringAndLong(APPEND_LONG_PREFIX, l);
assertEquals(expected, result);
}
}
private static final String APPEND_INT_PREFIX = "Int/";
private static final String[] APPEND_INT_TEST_CASES = {
"Int/0",
"Int/1",
"Int/9",
"Int/10",
"Int/99",
"Int/100",
"Int/999",
"Int/1000",
"Int/9999",
"Int/10000",
"Int/99999",
"Int/100000",
"Int/999999",
"Int/1000000",
"Int/9999999",
"Int/10000000",
"Int/99999999",
"Int/100000000",
"Int/999999999",
"Int/1000000000",
"Int/2147483647", // Integer.MAX_VALUE
"Int/-1",
"Int/-9",
"Int/-10",
"Int/-99",
"Int/-100",
"Int/-999",
"Int/-1000",
"Int/-9999",
"Int/-10000",
"Int/-99999",
"Int/-100000",
"Int/-999999",
"Int/-1000000",
"Int/-9999999",
"Int/-10000000",
"Int/-99999999",
"Int/-100000000",
"Int/-999999999",
"Int/-1000000000",
"Int/-2147483648", // Integer.MIN_VALUE
};
/// CHECK-START: java.lang.String Main.$noinline$appendStringAndInt(java.lang.String, int) instruction_simplifier (before)
/// CHECK-NOT: StringBuilderAppend
/// CHECK-START: java.lang.String Main.$noinline$appendStringAndInt(java.lang.String, int) instruction_simplifier (after)
/// CHECK: StringBuilderAppend
public static String $noinline$appendStringAndInt(String s, int i) {
return new StringBuilder().append(s).append(i).toString();
}
public static void testAppendStringAndInt() {
for (String expected : APPEND_INT_TEST_CASES) {
int i = Integer.valueOf(expected.substring(APPEND_INT_PREFIX.length()));
String result = $noinline$appendStringAndInt(APPEND_INT_PREFIX, i);
assertEquals(expected, result);
}
}
public static String $noinline$appendStringAndString(String s1, String s2) {
return new StringBuilder().append(s1).append(s2).toString();
}
public static void testAppendStringAndString() {
assertEquals("nullnull", $noinline$appendStringAndString(null, null));
assertEquals("nullTEST", $noinline$appendStringAndString(null, "TEST"));
assertEquals("TESTnull", $noinline$appendStringAndString("TEST", null));
assertEquals("abcDEFGH", $noinline$appendStringAndString("abc", "DEFGH"));
// Test with a non-ASCII character.
assertEquals("test\u0131", $noinline$appendStringAndString("test", "\u0131"));
assertEquals("\u0131test", $noinline$appendStringAndString("\u0131", "test"));
assertEquals("\u0131test\u0131", $noinline$appendStringAndString("\u0131", "test\u0131"));
}
/// CHECK-START: java.lang.String Main.$noinline$appendSLILC(java.lang.String, long, int, long, char) instruction_simplifier (before)
/// CHECK-NOT: StringBuilderAppend
/// CHECK-START: java.lang.String Main.$noinline$appendSLILC(java.lang.String, long, int, long, char) instruction_simplifier (after)
/// CHECK: StringBuilderAppend
public static String $noinline$appendSLILC(String s,
long l1,
int i,
long l2,
char c) {
return new StringBuilder().append(s)
.append(l1)
.append(i)
.append(l2)
.append(c).toString();
}
public static void testMiscelaneous() {
assertEquals("x17-1q",
$noinline$appendSLILC("x", 1L, 7, -1L, 'q'));
assertEquals("null17-1q",
$noinline$appendSLILC(null, 1L, 7, -1L, 'q'));
assertEquals("x\u013117-1q",
$noinline$appendSLILC("x\u0131", 1L, 7, -1L, 'q'));
assertEquals("x427-1q",
$noinline$appendSLILC("x", 42L, 7, -1L, 'q'));
assertEquals("x1-42-1q",
$noinline$appendSLILC("x", 1L, -42, -1L, 'q'));
assertEquals("x17424242q",
$noinline$appendSLILC("x", 1L, 7, 424242L, 'q'));
assertEquals("x17-1\u0131",
$noinline$appendSLILC("x", 1L, 7, -1L, '\u0131'));
}
public static String $inline$testInlineInner(StringBuilder sb, String s, int i) {
return sb.append(s).append(i).toString();
}
/// CHECK-START: java.lang.String Main.$noinline$testInlineOuter(java.lang.String, int) instruction_simplifier$after_inlining (before)
/// CHECK-NOT: StringBuilderAppend
/// CHECK-START: java.lang.String Main.$noinline$testInlineOuter(java.lang.String, int) instruction_simplifier$after_inlining (after)
/// CHECK: StringBuilderAppend
public static String $noinline$testInlineOuter(String s, int i) {
StringBuilder sb = new StringBuilder();
return $inline$testInlineInner(sb, s, i);
}
public static void testInline() {
assertEquals("x42", $noinline$testInlineOuter("x", 42));
}
/// CHECK-START: java.lang.String Main.$noinline$appendNothing() instruction_simplifier (before)
/// CHECK-NOT: StringBuilderAppend
/// CHECK-START: java.lang.String Main.$noinline$appendNothing() instruction_simplifier (after)
/// CHECK-NOT: StringBuilderAppend
public static String $noinline$appendNothing() {
return new StringBuilder().toString();
}
public static void testNoArgs() {
assertEquals("", $noinline$appendNothing());
}
/// CHECK-START: boolean Main.$noinline$testAppendEquals(java.lang.String, int) instruction_simplifier (before)
/// CHECK-NOT: StringBuilderAppend
/// CHECK-START: boolean Main.$noinline$testAppendEquals(java.lang.String, int) instruction_simplifier (after)
/// CHECK: StringBuilderAppend
public static boolean $noinline$testAppendEquals(String s, int i) {
// Regression test for b/151107293 .
// When a string is used as both receiver and argument of String.equals(), we DCHECK()
// that it cannot be null. However, when replacing the call to StringBuilder.toString()
// with the HStringBuilderAppend(), the former reported CanBeNull() as false and
// therefore no explicit null checks were needed, but the replacement reported
// CanBeNull() as true, so when the result was used in String.equals() for both
// receiver and argument, the DCHECK() failed. This was fixed by overriding
// CanBeNull() in HStringBuilderAppend to correctly return false; the string that
// previously didn't require null check still does not require it.
String str = new StringBuilder().append(s).append(i).toString();
return str.equals(str);
}
public static void testEquals() {
if (!$noinline$testAppendEquals("Test", 42)) {
throw new Error("str.equals(str) is false");
}
}
public static void assertEquals(String expected, String actual) {
if (!expected.equals(actual)) {
throw new AssertionError("Expected: " + expected + ", actual: " + actual);
}
}
}