• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 public class Main {
main(String[] args)18     public static void main(String[] args) {
19         testAppendStringAndLong();
20         testAppendStringAndInt();
21         testAppendStringAndFloat();
22         testAppendStringAndDouble();
23         testAppendDoubleAndFloat();
24         testAppendStringAndString();
25         testMiscelaneous();
26         testNoArgs();
27         testInline();
28         testEquals();
29         System.out.println("passed");
30     }
31 
32     private static final String APPEND_LONG_PREFIX = "Long/";
33     private static final String[] APPEND_LONG_TEST_CASES = {
34         "Long/0",
35         "Long/1",
36         "Long/9",
37         "Long/10",
38         "Long/99",
39         "Long/100",
40         "Long/999",
41         "Long/1000",
42         "Long/9999",
43         "Long/10000",
44         "Long/99999",
45         "Long/100000",
46         "Long/999999",
47         "Long/1000000",
48         "Long/9999999",
49         "Long/10000000",
50         "Long/99999999",
51         "Long/100000000",
52         "Long/999999999",
53         "Long/1000000000",
54         "Long/9999999999",
55         "Long/10000000000",
56         "Long/99999999999",
57         "Long/100000000000",
58         "Long/999999999999",
59         "Long/1000000000000",
60         "Long/9999999999999",
61         "Long/10000000000000",
62         "Long/99999999999999",
63         "Long/100000000000000",
64         "Long/999999999999999",
65         "Long/1000000000000000",
66         "Long/9999999999999999",
67         "Long/10000000000000000",
68         "Long/99999999999999999",
69         "Long/100000000000000000",
70         "Long/999999999999999999",
71         "Long/1000000000000000000",
72         "Long/9223372036854775807",  // Long.MAX_VALUE
73         "Long/-1",
74         "Long/-9",
75         "Long/-10",
76         "Long/-99",
77         "Long/-100",
78         "Long/-999",
79         "Long/-1000",
80         "Long/-9999",
81         "Long/-10000",
82         "Long/-99999",
83         "Long/-100000",
84         "Long/-999999",
85         "Long/-1000000",
86         "Long/-9999999",
87         "Long/-10000000",
88         "Long/-99999999",
89         "Long/-100000000",
90         "Long/-999999999",
91         "Long/-1000000000",
92         "Long/-9999999999",
93         "Long/-10000000000",
94         "Long/-99999999999",
95         "Long/-100000000000",
96         "Long/-999999999999",
97         "Long/-1000000000000",
98         "Long/-9999999999999",
99         "Long/-10000000000000",
100         "Long/-99999999999999",
101         "Long/-100000000000000",
102         "Long/-999999999999999",
103         "Long/-1000000000000000",
104         "Long/-9999999999999999",
105         "Long/-10000000000000000",
106         "Long/-99999999999999999",
107         "Long/-100000000000000000",
108         "Long/-999999999999999999",
109         "Long/-1000000000000000000",
110         "Long/-9223372036854775808",  // Long.MIN_VALUE
111     };
112 
113     /// CHECK-START: java.lang.String Main.$noinline$appendStringAndLong(java.lang.String, long) instruction_simplifier (before)
114     /// CHECK-NOT:              StringBuilderAppend
115 
116     /// CHECK-START: java.lang.String Main.$noinline$appendStringAndLong(java.lang.String, long) instruction_simplifier (after)
117     /// CHECK:                  StringBuilderAppend
$noinline$appendStringAndLong(String s, long l)118     public static String $noinline$appendStringAndLong(String s, long l) {
119         return new StringBuilder().append(s).append(l).toString();
120     }
121 
testAppendStringAndLong()122     public static void testAppendStringAndLong() {
123         for (String expected : APPEND_LONG_TEST_CASES) {
124             long l = Long.valueOf(expected.substring(APPEND_LONG_PREFIX.length()));
125             String result = $noinline$appendStringAndLong(APPEND_LONG_PREFIX, l);
126             assertEquals(expected, result);
127         }
128     }
129 
130     private static final String APPEND_INT_PREFIX = "Int/";
131     private static final String[] APPEND_INT_TEST_CASES = {
132         "Int/0",
133         "Int/1",
134         "Int/9",
135         "Int/10",
136         "Int/99",
137         "Int/100",
138         "Int/999",
139         "Int/1000",
140         "Int/9999",
141         "Int/10000",
142         "Int/99999",
143         "Int/100000",
144         "Int/999999",
145         "Int/1000000",
146         "Int/9999999",
147         "Int/10000000",
148         "Int/99999999",
149         "Int/100000000",
150         "Int/999999999",
151         "Int/1000000000",
152         "Int/2147483647",  // Integer.MAX_VALUE
153         "Int/-1",
154         "Int/-9",
155         "Int/-10",
156         "Int/-99",
157         "Int/-100",
158         "Int/-999",
159         "Int/-1000",
160         "Int/-9999",
161         "Int/-10000",
162         "Int/-99999",
163         "Int/-100000",
164         "Int/-999999",
165         "Int/-1000000",
166         "Int/-9999999",
167         "Int/-10000000",
168         "Int/-99999999",
169         "Int/-100000000",
170         "Int/-999999999",
171         "Int/-1000000000",
172         "Int/-2147483648",  // Integer.MIN_VALUE
173     };
174 
175     /// CHECK-START: java.lang.String Main.$noinline$appendStringAndInt(java.lang.String, int) instruction_simplifier (before)
176     /// CHECK-NOT:              StringBuilderAppend
177 
178     /// CHECK-START: java.lang.String Main.$noinline$appendStringAndInt(java.lang.String, int) instruction_simplifier (after)
179     /// CHECK:                  StringBuilderAppend
$noinline$appendStringAndInt(String s, int i)180     public static String $noinline$appendStringAndInt(String s, int i) {
181         return new StringBuilder().append(s).append(i).toString();
182     }
183 
testAppendStringAndInt()184     public static void testAppendStringAndInt() {
185         for (String expected : APPEND_INT_TEST_CASES) {
186             int i = Integer.valueOf(expected.substring(APPEND_INT_PREFIX.length()));
187             String result = $noinline$appendStringAndInt(APPEND_INT_PREFIX, i);
188             assertEquals(expected, result);
189         }
190     }
191 
192     private static final String APPEND_FLOAT_PREFIX = "Float/";
193     private static final String[] APPEND_FLOAT_TEST_CASES = {
194         // We're testing only exact values here, i.e. values that do not require rounding.
195         "Float/1.0",
196         "Float/9.0",
197         "Float/10.0",
198         "Float/99.0",
199         "Float/100.0",
200         "Float/999.0",
201         "Float/1000.0",
202         "Float/9999.0",
203         "Float/10000.0",
204         "Float/99999.0",
205         "Float/100000.0",
206         "Float/999999.0",
207         "Float/1000000.0",
208         "Float/9999999.0",
209         "Float/1.0E7",
210         "Float/1.0E10",
211         "Float/-1.0",
212         "Float/-9.0",
213         "Float/-10.0",
214         "Float/-99.0",
215         "Float/-100.0",
216         "Float/-999.0",
217         "Float/-1000.0",
218         "Float/-9999.0",
219         "Float/-10000.0",
220         "Float/-99999.0",
221         "Float/-100000.0",
222         "Float/-999999.0",
223         "Float/-1000000.0",
224         "Float/-9999999.0",
225         "Float/-1.0E7",
226         "Float/-1.0E10",
227         "Float/0.25",
228         "Float/1.625",
229         "Float/9.3125",
230         "Float/-0.25",
231         "Float/-1.625",
232         "Float/-9.3125",
233     };
234 
235     /// CHECK-START: java.lang.String Main.$noinline$appendStringAndFloat(java.lang.String, float) instruction_simplifier (before)
236     /// CHECK-NOT:              StringBuilderAppend
237 
238     /// CHECK-START: java.lang.String Main.$noinline$appendStringAndFloat(java.lang.String, float) instruction_simplifier (after)
239     /// CHECK:                  StringBuilderAppend
$noinline$appendStringAndFloat(String s, float f)240     public static String $noinline$appendStringAndFloat(String s, float f) {
241         return new StringBuilder().append(s).append(f).toString();
242     }
243 
testAppendStringAndFloat()244     public static void testAppendStringAndFloat() {
245         for (String expected : APPEND_FLOAT_TEST_CASES) {
246             float f = Float.valueOf(expected.substring(APPEND_FLOAT_PREFIX.length()));
247             String result = $noinline$appendStringAndFloat(APPEND_FLOAT_PREFIX, f);
248             assertEquals(expected, result);
249         }
250         // Special values.
251         assertEquals("Float/NaN", $noinline$appendStringAndFloat(APPEND_FLOAT_PREFIX, Float.NaN));
252         assertEquals("Float/Infinity",
253                      $noinline$appendStringAndFloat(APPEND_FLOAT_PREFIX, Float.POSITIVE_INFINITY));
254         assertEquals("Float/-Infinity",
255                      $noinline$appendStringAndFloat(APPEND_FLOAT_PREFIX, Float.NEGATIVE_INFINITY));
256     }
257 
258     private static final String APPEND_DOUBLE_PREFIX = "Double/";
259     private static final String[] APPEND_DOUBLE_TEST_CASES = {
260         // We're testing only exact values here, i.e. values that do not require rounding.
261         "Double/1.0",
262         "Double/9.0",
263         "Double/10.0",
264         "Double/99.0",
265         "Double/100.0",
266         "Double/999.0",
267         "Double/1000.0",
268         "Double/9999.0",
269         "Double/10000.0",
270         "Double/99999.0",
271         "Double/100000.0",
272         "Double/999999.0",
273         "Double/1000000.0",
274         "Double/9999999.0",
275         "Double/1.0E7",
276         "Double/1.0E24",
277         "Double/-1.0",
278         "Double/-9.0",
279         "Double/-10.0",
280         "Double/-99.0",
281         "Double/-100.0",
282         "Double/-999.0",
283         "Double/-1000.0",
284         "Double/-9999.0",
285         "Double/-10000.0",
286         "Double/-99999.0",
287         "Double/-100000.0",
288         "Double/-999999.0",
289         "Double/-1000000.0",
290         "Double/-9999999.0",
291         "Double/-1.0E7",
292         "Double/-1.0E24",
293         "Double/0.25",
294         "Double/1.625",
295         "Double/9.3125",
296         "Double/-0.25",
297         "Double/-1.625",
298         "Double/-9.3125",
299     };
300 
301     /// CHECK-START: java.lang.String Main.$noinline$appendStringAndDouble(java.lang.String, double) instruction_simplifier (before)
302     /// CHECK-NOT:              StringBuilderAppend
303 
304     /// CHECK-START: java.lang.String Main.$noinline$appendStringAndDouble(java.lang.String, double) instruction_simplifier (after)
305     /// CHECK:                  StringBuilderAppend
$noinline$appendStringAndDouble(String s, double d)306     public static String $noinline$appendStringAndDouble(String s, double d) {
307         return new StringBuilder().append(s).append(d).toString();
308     }
309 
testAppendStringAndDouble()310     public static void testAppendStringAndDouble() {
311         for (String expected : APPEND_DOUBLE_TEST_CASES) {
312             double f = Double.valueOf(expected.substring(APPEND_DOUBLE_PREFIX.length()));
313             String result = $noinline$appendStringAndDouble(APPEND_DOUBLE_PREFIX, f);
314             assertEquals(expected, result);
315         }
316         // Special values.
317         assertEquals(
318             "Double/NaN",
319             $noinline$appendStringAndDouble(APPEND_DOUBLE_PREFIX, Double.NaN));
320         assertEquals(
321             "Double/Infinity",
322             $noinline$appendStringAndDouble(APPEND_DOUBLE_PREFIX, Double.POSITIVE_INFINITY));
323         assertEquals(
324             "Double/-Infinity",
325             $noinline$appendStringAndDouble(APPEND_DOUBLE_PREFIX, Double.NEGATIVE_INFINITY));
326     }
327 
328     /// CHECK-START: java.lang.String Main.$noinline$appendDoubleAndFloat(double, float) instruction_simplifier (before)
329     /// CHECK-NOT:              StringBuilderAppend
330 
331     /// CHECK-START: java.lang.String Main.$noinline$appendDoubleAndFloat(double, float) instruction_simplifier (after)
332     /// CHECK:                  StringBuilderAppend
$noinline$appendDoubleAndFloat(double d, float f)333     public static String $noinline$appendDoubleAndFloat(double d, float f) {
334         return new StringBuilder().append(d).append(f).toString();
335     }
336 
testAppendDoubleAndFloat()337     public static void testAppendDoubleAndFloat() {
338         assertEquals("1.50.325", $noinline$appendDoubleAndFloat(1.5, 0.325f));
339         assertEquals("1.5E170.3125", $noinline$appendDoubleAndFloat(1.5E17, 0.3125f));
340         assertEquals("1.0E8NaN", $noinline$appendDoubleAndFloat(1.0E8, Float.NaN));
341         assertEquals("Infinity0.5", $noinline$appendDoubleAndFloat(Double.POSITIVE_INFINITY, 0.5f));
342         assertEquals("2.5-Infinity", $noinline$appendDoubleAndFloat(2.5, Float.NEGATIVE_INFINITY));
343     }
344 
$noinline$appendStringAndString(String s1, String s2)345     public static String $noinline$appendStringAndString(String s1, String s2) {
346         return new StringBuilder().append(s1).append(s2).toString();
347     }
348 
testAppendStringAndString()349     public static void testAppendStringAndString() {
350         assertEquals("nullnull", $noinline$appendStringAndString(null, null));
351         assertEquals("nullTEST", $noinline$appendStringAndString(null, "TEST"));
352         assertEquals("TESTnull", $noinline$appendStringAndString("TEST", null));
353         assertEquals("abcDEFGH", $noinline$appendStringAndString("abc", "DEFGH"));
354         // Test with a non-ASCII character.
355         assertEquals("test\u0131", $noinline$appendStringAndString("test", "\u0131"));
356         assertEquals("\u0131test", $noinline$appendStringAndString("\u0131", "test"));
357         assertEquals("\u0131test\u0131", $noinline$appendStringAndString("\u0131", "test\u0131"));
358     }
359 
360     /// CHECK-START: java.lang.String Main.$noinline$appendSLILC(java.lang.String, long, int, long, char) instruction_simplifier (before)
361     /// CHECK-NOT:              StringBuilderAppend
362 
363     /// CHECK-START: java.lang.String Main.$noinline$appendSLILC(java.lang.String, long, int, long, char) instruction_simplifier (after)
364     /// CHECK:                  StringBuilderAppend
$noinline$appendSLILC(String s, long l1, int i, long l2, char c)365     public static String $noinline$appendSLILC(String s,
366                                                long l1,
367                                                int i,
368                                                long l2,
369                                                char c) {
370         return new StringBuilder().append(s)
371                                   .append(l1)
372                                   .append(i)
373                                   .append(l2)
374                                   .append(c).toString();
375     }
376 
testMiscelaneous()377     public static void testMiscelaneous() {
378         assertEquals("x17-1q",
379                      $noinline$appendSLILC("x", 1L, 7, -1L, 'q'));
380         assertEquals("null17-1q",
381                      $noinline$appendSLILC(null, 1L, 7, -1L, 'q'));
382         assertEquals("x\u013117-1q",
383                      $noinline$appendSLILC("x\u0131", 1L, 7, -1L, 'q'));
384         assertEquals("x427-1q",
385                      $noinline$appendSLILC("x", 42L, 7, -1L, 'q'));
386         assertEquals("x1-42-1q",
387                      $noinline$appendSLILC("x", 1L, -42, -1L, 'q'));
388         assertEquals("x17424242q",
389                      $noinline$appendSLILC("x", 1L, 7, 424242L, 'q'));
390         assertEquals("x17-1\u0131",
391                      $noinline$appendSLILC("x", 1L, 7, -1L, '\u0131'));
392     }
393 
$inline$testInlineInner(StringBuilder sb, String s, int i)394     public static String $inline$testInlineInner(StringBuilder sb, String s, int i) {
395         return sb.append(s).append(i).toString();
396     }
397 
398     /// CHECK-START: java.lang.String Main.$noinline$testInlineOuter(java.lang.String, int) instruction_simplifier$after_inlining (before)
399     /// CHECK-NOT:              StringBuilderAppend
400 
401     /// CHECK-START: java.lang.String Main.$noinline$testInlineOuter(java.lang.String, int) instruction_simplifier$after_inlining (after)
402     /// CHECK:                  StringBuilderAppend
$noinline$testInlineOuter(String s, int i)403     public static String $noinline$testInlineOuter(String s, int i) {
404         StringBuilder sb = new StringBuilder();
405         return $inline$testInlineInner(sb, s, i);
406     }
407 
testInline()408     public static void testInline() {
409         assertEquals("x42", $noinline$testInlineOuter("x", 42));
410     }
411 
412     /// CHECK-START: java.lang.String Main.$noinline$appendNothing() instruction_simplifier (before)
413     /// CHECK-NOT:              StringBuilderAppend
414 
415     /// CHECK-START: java.lang.String Main.$noinline$appendNothing() instruction_simplifier (after)
416     /// CHECK-NOT:              StringBuilderAppend
$noinline$appendNothing()417     public static String $noinline$appendNothing() {
418         return new StringBuilder().toString();
419     }
420 
testNoArgs()421     public static void testNoArgs() {
422         assertEquals("", $noinline$appendNothing());
423     }
424 
425     /// CHECK-START: boolean Main.$noinline$testAppendEquals(java.lang.String, int) instruction_simplifier (before)
426     /// CHECK-NOT:              StringBuilderAppend
427 
428     /// CHECK-START: boolean Main.$noinline$testAppendEquals(java.lang.String, int) instruction_simplifier (after)
429     /// CHECK:                  StringBuilderAppend
$noinline$testAppendEquals(String s, int i)430     public static boolean $noinline$testAppendEquals(String s, int i) {
431       // Regression test for b/151107293 .
432       // When a string is used as both receiver and argument of String.equals(), we DCHECK()
433       // that it cannot be null. However, when replacing the call to StringBuilder.toString()
434       // with the HStringBuilderAppend(), the former reported CanBeNull() as false and
435       // therefore no explicit null checks were needed, but the replacement reported
436       // CanBeNull() as true, so when the result was used in String.equals() for both
437       // receiver and argument, the DCHECK() failed. This was fixed by overriding
438       // CanBeNull() in HStringBuilderAppend to correctly return false; the string that
439       // previously didn't require null check still does not require it.
440       String str = new StringBuilder().append(s).append(i).toString();
441       return str.equals(str);
442     }
443 
testEquals()444     public static void testEquals() {
445       if (!$noinline$testAppendEquals("Test", 42)) {
446         throw new Error("str.equals(str) is false");
447       }
448     }
449 
assertEquals(String expected, String actual)450     public static void assertEquals(String expected, String actual) {
451         if (!expected.equals(actual)) {
452             throw new AssertionError("Expected: " + expected + ", actual: " + actual);
453         }
454     }
455 }
456