blob: c63c328aa7b60c2d217872ea16d919bfe838ddd9 [file] [log] [blame]
Vladimir Marko552a1342017-10-31 10:56:47 +00001/*
2 * Copyright 2019 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
17public class Main {
18 public static void main(String[] args) {
19 testAppendStringAndLong();
20 testAppendStringAndInt();
21 testAppendStringAndString();
22 testMiscelaneous();
23 testNoArgs();
Vladimir Marko56f13322019-11-15 14:07:19 +000024 testInline();
Vladimir Markob1fe5e12020-03-10 14:30:49 +000025 testEquals();
Vladimir Marko552a1342017-10-31 10:56:47 +000026 System.out.println("passed");
27 }
28
29 private static final String APPEND_LONG_PREFIX = "Long/";
30 private static final String[] APPEND_LONG_TEST_CASES = {
31 "Long/0",
32 "Long/1",
33 "Long/9",
34 "Long/10",
35 "Long/99",
36 "Long/100",
37 "Long/999",
38 "Long/1000",
39 "Long/9999",
40 "Long/10000",
41 "Long/99999",
42 "Long/100000",
43 "Long/999999",
44 "Long/1000000",
45 "Long/9999999",
46 "Long/10000000",
47 "Long/99999999",
48 "Long/100000000",
49 "Long/999999999",
50 "Long/1000000000",
51 "Long/9999999999",
52 "Long/10000000000",
53 "Long/99999999999",
54 "Long/100000000000",
55 "Long/999999999999",
56 "Long/1000000000000",
57 "Long/9999999999999",
58 "Long/10000000000000",
59 "Long/99999999999999",
60 "Long/100000000000000",
61 "Long/999999999999999",
62 "Long/1000000000000000",
63 "Long/9999999999999999",
64 "Long/10000000000000000",
65 "Long/99999999999999999",
66 "Long/100000000000000000",
67 "Long/999999999999999999",
68 "Long/1000000000000000000",
69 "Long/9223372036854775807", // Long.MAX_VALUE
70 "Long/-1",
71 "Long/-9",
72 "Long/-10",
73 "Long/-99",
74 "Long/-100",
75 "Long/-999",
76 "Long/-1000",
77 "Long/-9999",
78 "Long/-10000",
79 "Long/-99999",
80 "Long/-100000",
81 "Long/-999999",
82 "Long/-1000000",
83 "Long/-9999999",
84 "Long/-10000000",
85 "Long/-99999999",
86 "Long/-100000000",
87 "Long/-999999999",
88 "Long/-1000000000",
89 "Long/-9999999999",
90 "Long/-10000000000",
91 "Long/-99999999999",
92 "Long/-100000000000",
93 "Long/-999999999999",
94 "Long/-1000000000000",
95 "Long/-9999999999999",
96 "Long/-10000000000000",
97 "Long/-99999999999999",
98 "Long/-100000000000000",
99 "Long/-999999999999999",
100 "Long/-1000000000000000",
101 "Long/-9999999999999999",
102 "Long/-10000000000000000",
103 "Long/-99999999999999999",
104 "Long/-100000000000000000",
105 "Long/-999999999999999999",
106 "Long/-1000000000000000000",
107 "Long/-9223372036854775808", // Long.MIN_VALUE
108 };
109
110 /// CHECK-START: java.lang.String Main.$noinline$appendStringAndLong(java.lang.String, long) instruction_simplifier (before)
111 /// CHECK-NOT: StringBuilderAppend
112
113 /// CHECK-START: java.lang.String Main.$noinline$appendStringAndLong(java.lang.String, long) instruction_simplifier (after)
114 /// CHECK: StringBuilderAppend
115 public static String $noinline$appendStringAndLong(String s, long l) {
116 return new StringBuilder().append(s).append(l).toString();
117 }
118
119 public static void testAppendStringAndLong() {
120 for (String expected : APPEND_LONG_TEST_CASES) {
121 long l = Long.valueOf(expected.substring(APPEND_LONG_PREFIX.length()));
122 String result = $noinline$appendStringAndLong(APPEND_LONG_PREFIX, l);
123 assertEquals(expected, result);
124 }
125 }
126
127 private static final String APPEND_INT_PREFIX = "Int/";
128 private static final String[] APPEND_INT_TEST_CASES = {
129 "Int/0",
130 "Int/1",
131 "Int/9",
132 "Int/10",
133 "Int/99",
134 "Int/100",
135 "Int/999",
136 "Int/1000",
137 "Int/9999",
138 "Int/10000",
139 "Int/99999",
140 "Int/100000",
141 "Int/999999",
142 "Int/1000000",
143 "Int/9999999",
144 "Int/10000000",
145 "Int/99999999",
146 "Int/100000000",
147 "Int/999999999",
148 "Int/1000000000",
149 "Int/2147483647", // Integer.MAX_VALUE
150 "Int/-1",
151 "Int/-9",
152 "Int/-10",
153 "Int/-99",
154 "Int/-100",
155 "Int/-999",
156 "Int/-1000",
157 "Int/-9999",
158 "Int/-10000",
159 "Int/-99999",
160 "Int/-100000",
161 "Int/-999999",
162 "Int/-1000000",
163 "Int/-9999999",
164 "Int/-10000000",
165 "Int/-99999999",
166 "Int/-100000000",
167 "Int/-999999999",
168 "Int/-1000000000",
169 "Int/-2147483648", // Integer.MIN_VALUE
170 };
171
172 /// CHECK-START: java.lang.String Main.$noinline$appendStringAndInt(java.lang.String, int) instruction_simplifier (before)
173 /// CHECK-NOT: StringBuilderAppend
174
175 /// CHECK-START: java.lang.String Main.$noinline$appendStringAndInt(java.lang.String, int) instruction_simplifier (after)
176 /// CHECK: StringBuilderAppend
177 public static String $noinline$appendStringAndInt(String s, int i) {
178 return new StringBuilder().append(s).append(i).toString();
179 }
180
181 public static void testAppendStringAndInt() {
182 for (String expected : APPEND_INT_TEST_CASES) {
183 int i = Integer.valueOf(expected.substring(APPEND_INT_PREFIX.length()));
184 String result = $noinline$appendStringAndInt(APPEND_INT_PREFIX, i);
185 assertEquals(expected, result);
186 }
187 }
188
189 public static String $noinline$appendStringAndString(String s1, String s2) {
190 return new StringBuilder().append(s1).append(s2).toString();
191 }
192
193 public static void testAppendStringAndString() {
194 assertEquals("nullnull", $noinline$appendStringAndString(null, null));
195 assertEquals("nullTEST", $noinline$appendStringAndString(null, "TEST"));
196 assertEquals("TESTnull", $noinline$appendStringAndString("TEST", null));
197 assertEquals("abcDEFGH", $noinline$appendStringAndString("abc", "DEFGH"));
198 // Test with a non-ASCII character.
199 assertEquals("test\u0131", $noinline$appendStringAndString("test", "\u0131"));
200 assertEquals("\u0131test", $noinline$appendStringAndString("\u0131", "test"));
201 assertEquals("\u0131test\u0131", $noinline$appendStringAndString("\u0131", "test\u0131"));
202 }
203
204 /// CHECK-START: java.lang.String Main.$noinline$appendSLILC(java.lang.String, long, int, long, char) instruction_simplifier (before)
205 /// CHECK-NOT: StringBuilderAppend
206
207 /// CHECK-START: java.lang.String Main.$noinline$appendSLILC(java.lang.String, long, int, long, char) instruction_simplifier (after)
208 /// CHECK: StringBuilderAppend
209 public static String $noinline$appendSLILC(String s,
210 long l1,
211 int i,
212 long l2,
213 char c) {
214 return new StringBuilder().append(s)
215 .append(l1)
216 .append(i)
217 .append(l2)
218 .append(c).toString();
219 }
220
221 public static void testMiscelaneous() {
222 assertEquals("x17-1q",
223 $noinline$appendSLILC("x", 1L, 7, -1L, 'q'));
224 assertEquals("null17-1q",
225 $noinline$appendSLILC(null, 1L, 7, -1L, 'q'));
226 assertEquals("x\u013117-1q",
227 $noinline$appendSLILC("x\u0131", 1L, 7, -1L, 'q'));
228 assertEquals("x427-1q",
229 $noinline$appendSLILC("x", 42L, 7, -1L, 'q'));
230 assertEquals("x1-42-1q",
231 $noinline$appendSLILC("x", 1L, -42, -1L, 'q'));
232 assertEquals("x17424242q",
233 $noinline$appendSLILC("x", 1L, 7, 424242L, 'q'));
234 assertEquals("x17-1\u0131",
235 $noinline$appendSLILC("x", 1L, 7, -1L, '\u0131'));
236 }
237
Vladimir Marko56f13322019-11-15 14:07:19 +0000238 public static String $inline$testInlineInner(StringBuilder sb, String s, int i) {
239 return sb.append(s).append(i).toString();
240 }
241
242 /// CHECK-START: java.lang.String Main.$noinline$testInlineOuter(java.lang.String, int) instruction_simplifier$after_inlining (before)
243 /// CHECK-NOT: StringBuilderAppend
244
245 /// CHECK-START: java.lang.String Main.$noinline$testInlineOuter(java.lang.String, int) instruction_simplifier$after_inlining (after)
246 /// CHECK: StringBuilderAppend
247 public static String $noinline$testInlineOuter(String s, int i) {
248 StringBuilder sb = new StringBuilder();
249 return $inline$testInlineInner(sb, s, i);
250 }
251
252 public static void testInline() {
253 assertEquals("x42", $noinline$testInlineOuter("x", 42));
254 }
255
Vladimir Marko552a1342017-10-31 10:56:47 +0000256 /// CHECK-START: java.lang.String Main.$noinline$appendNothing() instruction_simplifier (before)
257 /// CHECK-NOT: StringBuilderAppend
258
259 /// CHECK-START: java.lang.String Main.$noinline$appendNothing() instruction_simplifier (after)
260 /// CHECK-NOT: StringBuilderAppend
261 public static String $noinline$appendNothing() {
262 return new StringBuilder().toString();
263 }
264
265 public static void testNoArgs() {
266 assertEquals("", $noinline$appendNothing());
267 }
268
Vladimir Markob1fe5e12020-03-10 14:30:49 +0000269 /// CHECK-START: boolean Main.$noinline$testAppendEquals(java.lang.String, int) instruction_simplifier (before)
270 /// CHECK-NOT: StringBuilderAppend
271
272 /// CHECK-START: boolean Main.$noinline$testAppendEquals(java.lang.String, int) instruction_simplifier (after)
273 /// CHECK: StringBuilderAppend
274 public static boolean $noinline$testAppendEquals(String s, int i) {
275 // Regression test for b/151107293 .
276 // When a string is used as both receiver and argument of String.equals(), we DCHECK()
277 // that it cannot be null. However, when replacing the call to StringBuilder.toString()
278 // with the HStringBuilderAppend(), the former reported CanBeNull() as false and
279 // therefore no explicit null checks were needed, but the replacement reported
280 // CanBeNull() as true, so when the result was used in String.equals() for both
281 // receiver and argument, the DCHECK() failed. This was fixed by overriding
282 // CanBeNull() in HStringBuilderAppend to correctly return false; the string that
283 // previously didn't require null check still does not require it.
284 String str = new StringBuilder().append(s).append(i).toString();
285 return str.equals(str);
286 }
287
288 public static void testEquals() {
289 if (!$noinline$testAppendEquals("Test", 42)) {
290 throw new Error("str.equals(str) is false");
291 }
292 }
293
Vladimir Marko552a1342017-10-31 10:56:47 +0000294 public static void assertEquals(String expected, String actual) {
295 if (!expected.equals(actual)) {
296 throw new AssertionError("Expected: " + expected + ", actual: " + actual);
297 }
298 }
299}