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
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);
|
|
}
|
|
}
|
|
}
|