1 /*
2  * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
3  * Copyright (c) 2016 SAP SE. All rights reserved.
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This code is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 only, as
8  * published by the Free Software Foundation.
9  *
10  * This code is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * version 2 for more details (a copy is included in the LICENSE file that
14  * accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License version
17  * 2 along with this work; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19  *
20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21  * or visit www.oracle.com if you need additional information or have any
22  * questions.
23  */
24 
25 /*
26  * @test
27  * @bug 8145336
28  * @summary PPC64: fix string intrinsics after CompactStrings change
29  * @modules java.base/jdk.internal.misc
30  * @library /test/lib
31  *
32  * @build sun.hotspot.WhiteBox
33  * @run driver ClassFileInstaller sun.hotspot.WhiteBox
34  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
35  *
36  * @run main/othervm
37  *        -Xbootclasspath/a:.
38  *        -Xmixed
39  *        -XX:+UnlockDiagnosticVMOptions
40  *        -XX:+WhiteBoxAPI
41  *        -XX:MaxInlineSize=70
42  *        -XX:MinInliningThreshold=0
43  *        compiler.intrinsics.string.TestStringIntrinsics2
44  */
45 
46 package compiler.intrinsics.string;
47 
48 import sun.hotspot.WhiteBox;
49 
50 import java.lang.annotation.ElementType;
51 import java.lang.annotation.Retention;
52 import java.lang.annotation.RetentionPolicy;
53 import java.lang.annotation.Target;
54 import java.util.Arrays;
55 import java.util.function.Consumer;
56 
57 import static jdk.test.lib.Asserts.assertEquals;
58 import static jdk.test.lib.Asserts.assertFalse;
59 import static jdk.test.lib.Asserts.assertTrue;
60 
61 public class TestStringIntrinsics2 {
62     // ------------------------------------------------------------------------
63     //
64     // We test the following cases:
65     // - no match in string.  Do we miss the end condition? Will crash if we read
66     //   past the string.
67     // - no match in string, but after the string there is a match.
68     //   Do we incorrectly report this match?  We had a case where we stepped
69     //   a few chars past the string, this test would report that error. The
70     //   one above would not.
71     // - The needle is exactly at the end of the string.
72     // - The needle spans the end of the string
73     //
74     // A special case are needles of length 1. For these we test:
75     // - needle is first char
76     // - needle is last char
77     // - no match
78     // - match behind string.
79     //
80     // We test all these for an unknown needle, and needles known to the compiler
81     // of lengths 5, 2 and 1.
82 
83 
84     private static final WhiteBox WB = WhiteBox.getWhiteBox();
85 
86     public enum Role {
87         TEST_ENTRY,
88         TEST_HELPER
89     }
90 
91     @Retention(RetentionPolicy.RUNTIME)
92     @Target(ElementType.METHOD)
93     @interface Test {
role()94         Role role();
compileAt()95         int compileAt() default 0;
warmup()96         int warmup() default 0;
warmupArgs()97         String[] warmupArgs() default {};
98     }
99 
100     // All this mess is needed to avoid try/catch inside the lambdas below.
101     // See: http://stackoverflow.com/questions/27644361/how-can-i-throw-checked-exceptions-from-inside-java-8-streams
102     @SuppressWarnings ("unchecked")
throwAsUnchecked(Exception exception)103     private static <E extends Throwable> void throwAsUnchecked(Exception exception) throws E {
104         throw (E)exception;
105     }
106     @FunctionalInterface
107     public interface Consumer_WithExceptions<T, E extends Exception> {
accept(T t)108         void accept(T t) throws E;
109     }
rethrowConsumer(Consumer_WithExceptions<T, E> consumer)110     public static <T, E extends Exception> Consumer<T> rethrowConsumer(Consumer_WithExceptions<T, E> consumer) {
111         return t -> {
112             try { consumer.accept(t); }
113             catch (Exception exception) { throwAsUnchecked(exception); }
114         };
115     }
116 
117     public static void main(String[] args) throws Exception {
118 
119         // Warmup helper methods
120         Arrays.stream(TestStringIntrinsics2.class.getDeclaredMethods())
121             .filter(m -> m.isAnnotationPresent(Test.class))
122             .filter(m -> m.getAnnotation(Test.class).warmup() > 0)
123             .forEach(rethrowConsumer(m -> {
124                         Test a = m.getAnnotation(Test.class);
125                         System.out.println("Warming up " + m + " " + a.warmup() + " time(s) ");
126                         for (int i=0; i < a.warmup(); i++) {
127                             m.invoke(null, (Object[])a.warmupArgs());
128                         }
129                     }));
130 
131         // Compile helper methods
132         Arrays.stream(TestStringIntrinsics2.class.getDeclaredMethods())
133             .filter(m -> m.isAnnotationPresent(Test.class))
134             .filter(m -> m.getAnnotation(Test.class).compileAt() > 0)
135             .forEach(rethrowConsumer(m -> {
136                         Test a = m.getAnnotation(Test.class);
137                         if (WB.isMethodCompilable(m, a.compileAt())) {
138                             WB.enqueueMethodForCompilation(m, a.compileAt());
139                             while (WB.isMethodQueuedForCompilation(m)) Thread.sleep(10);
140                             System.out.println(m + " compiled at " + WB.getMethodCompilationLevel(m));
141                         } else {
142                             System.out.println("Can't compile " + m + " at level " + a.compileAt());
143                         }
144                     }));
145 
146         // Run test methods
147         Arrays.stream(TestStringIntrinsics2.class.getDeclaredMethods())
148             .filter(m -> m.isAnnotationPresent(Test.class))
149             .filter(m -> m.getAnnotation(Test.class).role() == Role.TEST_ENTRY)
150             .forEach(rethrowConsumer(m -> {
151                         System.out.print("Executing " + m);
152                         m.invoke(null, (Object[])null);
153                         System.out.println(" - OK");
154                     }));
155     }
156 
157     static String text = "<t><t><t><t><t><t>\n" + "<hit>";
158     static String text2 = "<t><t><t><t><t><t><t>\n" + "<hit>";
159     static String[] ss = text.split("\n");
160     static String[] ss2 = null;
161     static String needle = "<miss>";
162 
163     @Test(role = Role.TEST_ENTRY)
164     public static void test_indexOf_no_match() {
165         int res = indexOf_no_match_unknown_needle(ss[0], "<miss>");
166         assertEquals(res, -1, "test_indexOf_no_match_unknown_needle matched at: " + res);
167         res = indexOf_no_match_imm_needle(ss[0]);
168         assertEquals(res, -1, "test_indexOf_no_match_imm_needle matched at: " + res);
169         res = indexOf_no_match_imm2_needle(ss[0]);
170         assertEquals(res, -1, "test_indexOf_no_match_imm2_needle matched at: " + res);
171 
172         if (ss2 == null) ss2 = text.split("\n");
173         res = indexOf_no_match_unknown_needle(ss2[0], "<miss>");
174         assertEquals(res, -1, "test_indexOf_no_match_unknown_needle matched at: " + res);
175         res = indexOf_no_match_imm_needle(ss2[0]);
176         assertEquals(res, -1, "test_indexOf_no_match_imm_needle matched at: " + res);
177         res = indexOf_no_match_imm2_needle(ss2[0]);
178         assertEquals(res, -1, "test_indexOf_no_match_imm2_needle matched at: " + res);
179         res = indexOf_no_match_imm1_needle(ss2[0]);
180         assertEquals(res, -1, "test_indexOf_no_match_imm1_needle matched at: " + res);
181     }
182 
183     @Test(role = Role.TEST_HELPER, compileAt = 4, warmup = 1, warmupArgs = { "<t><t><t>", "<miss>" })
184     static int indexOf_no_match_unknown_needle(String s, String needle) {
185         int index = s.indexOf(needle);
186         return index;
187     }
188 
189     @Test(role = Role.TEST_HELPER, compileAt = 4, warmup = 1, warmupArgs = { "<t><t><t>" })
190     static int indexOf_no_match_imm_needle(String s) {
191         int index = s.indexOf("<hitt>");
192         return index;
193     }
194 
195     @Test(role = Role.TEST_HELPER, compileAt = 4, warmup = 1, warmupArgs = { "<t><t><t>" })
196     static int indexOf_no_match_imm2_needle(String s) {
197         int index = s.indexOf("<m");
198         return index;
199     }
200 
201     @Test(role = Role.TEST_HELPER, compileAt = 4, warmup = 1, warmupArgs = { "<t><t><t>" })
202     static int indexOf_no_match_imm1_needle(String s) {
203         int index = s.indexOf("m");
204         return index;
205     }
206 
207     @Test(role = Role.TEST_ENTRY)
208     public static void test_indexOf_reads_past_string() {
209         if (ss == null) ss = text.split("\n");
210         String res = indexOf_reads_past_string_unknown_needle(ss[0], "<hit>");
211         assertEquals(res, null, "test_indexOf_reads_past_string_unknown_needle " + res);
212         res = indexOf_reads_past_string_imm_needle(ss[0]);
213         assertEquals(res, null, "test_indexOf_reads_past_string_imm_needle " + res);
214         res = indexOf_reads_past_string_imm2_needle(ss[0]);
215         assertEquals(res, null, "test_indexOf_reads_past_string_imm2_needle " + res);
216         res = indexOf_reads_past_string_imm1_needle(ss[0]);
217         assertEquals(res, null, "test_indexOf_reads_past_string_imm1_needle " + res);
218     }
219 
220     @Test(role = Role.TEST_HELPER, compileAt = 4, warmup = 1, warmupArgs = { "<t><t><t>", "<hit>" })
221     static String indexOf_reads_past_string_unknown_needle(String s, String needle) {
222         int index = s.indexOf(needle);
223         if (index > s.length()) {
224             return "Found needle \"" + needle + "\" behind string of length " + s.length()
225                 + " at position " + index + ".";
226         }
227         return null;
228     }
229 
230     @Test(role = Role.TEST_HELPER, compileAt = 4, warmup = 1, warmupArgs = { "<t><t><t>" })
231     static String indexOf_reads_past_string_imm_needle(String s) {
232         int index = s.indexOf("<hit>");
233         if (index > s.length()) {
234             return "Found needle \"<hit>\" behind string of length " + s.length() + " at position " + index + ".";
235         }
236         return null;
237     }
238 
239     @Test(role = Role.TEST_HELPER, compileAt = 4, warmup = 1, warmupArgs = { "<t><t><t>" })
240     static String indexOf_reads_past_string_imm2_needle(String s) {
241         int index = s.indexOf("<h");
242         if (index > s.length()) {
243             return "Found needle \"<h\" behind string of length " + s.length() + " at position " + index + ".";
244         }
245         return null;
246     }
247 
248     @Test(role = Role.TEST_HELPER, compileAt = 4, warmup = 1, warmupArgs = { "<t><t><t>" })
249     static String indexOf_reads_past_string_imm1_needle(String s) {
250         int index = s.indexOf("h");
251         if (index > s.length()) {
252             return "Found needle \"<h\" behind string of length " + s.length() + " at position " + index + ".";
253         }
254         return null;
255     }
256 
257     static String text3 =    "<t><hi><t><h><hit<t><hit>";
258     static String text4 =   "a<t><hi><t><h><hit<t><hit>";
259     static String text5 =  "gg<t><hi><t><h><hit<t><hit>";
260     static String text6 = "ccc<t><hi><t><h><hit<t><hit>";
261     static int len3 = text3.length();
262     static int len4 = text4.length();
263     static int len5 = text5.length();
264     static int len6 = text6.length();
265 
266     static String text7  =    "<t><t><t><t><t<t><h";
267     static String text8  =   "a<t><t><t><t><t<t><h";
268     static String text9  =  "gg<t><t><t><t><t<t><h";
269     static String text10 = "ccc<t><t><t><t><t<t><h";
270 
271     @Test(role = Role.TEST_ENTRY)
272     public static void test_indexOf_match_at_end_of_string() {
273         String testname = "test_indexOf_match_at_end_of_string";
274         int res = 0;
275         res = indexOf_match_at_end_of_string_unknown_needle(text3, "<hit>");
276         assertEquals(len3, res + 5, testname);
277         res = indexOf_match_at_end_of_string_unknown_needle(text4, "<hit>");
278         assertEquals(len4, res + 5, testname);
279         res = indexOf_match_at_end_of_string_unknown_needle(text5, "<hit>");
280         assertEquals(len5, res + 5, testname);
281         res = indexOf_match_at_end_of_string_unknown_needle(text6, "<hit>");
282         assertEquals(len6, res + 5, testname);
283 
284         res = indexOf_match_at_end_of_string_imm_needle(text3);
285         assertEquals(len3, res + 5, testname);
286         res = indexOf_match_at_end_of_string_imm_needle(text4);
287         assertEquals(len4, res + 5, testname);
288         res = indexOf_match_at_end_of_string_imm_needle(text5);
289         assertEquals(len5, res + 5, testname);
290         res = indexOf_match_at_end_of_string_imm_needle(text6);
291         assertEquals(len6, res + 5, testname);
292 
293         res = indexOf_match_at_end_of_string_imm2_needle(text7);
294         assertEquals(text7.length(),  res + 2, testname);
295         res = indexOf_match_at_end_of_string_imm2_needle(text8);
296         assertEquals(text8.length(),  res + 2, testname);
297         res = indexOf_match_at_end_of_string_imm2_needle(text9);
298         assertEquals(text9.length(),  res + 2, testname);
299         res = indexOf_match_at_end_of_string_imm2_needle(text10);
300         assertEquals(text10.length(), res + 2, testname);
301 
302         res = indexOf_match_at_end_of_string_imm1_needle(text7);
303         assertEquals(text7.length(),  res + 1, testname);
304         res = indexOf_match_at_end_of_string_imm1_needle(text8);
305         assertEquals(text8.length(),  res + 1, testname);
306         res = indexOf_match_at_end_of_string_imm1_needle(text9);
307         assertEquals(text9.length(),  res + 1, testname);
308         res = indexOf_match_at_end_of_string_imm1_needle(text10);
309         assertEquals(text10.length(), res + 1, testname);
310     }
311 
312     @Test(role = Role.TEST_HELPER, compileAt = 4, warmup = 1, warmupArgs = { "<t><hi><t><h><hit<t><hit>", "<hit>" })
313     static int indexOf_match_at_end_of_string_unknown_needle(String s, String needle) {
314         int index = s.indexOf(needle);
315         return index;
316     }
317 
318     @Test(role = Role.TEST_HELPER, compileAt = 4, warmup = 1, warmupArgs = { "<t><hi><t><h><hit<t><hit>" })
319     static int indexOf_match_at_end_of_string_imm_needle(String s) {
320         int index = s.indexOf("<hit>");
321         return index;
322     }
323 
324     @Test(role = Role.TEST_HELPER, compileAt = 4, warmup = 1, warmupArgs = { "<t><hi><t><h><hit<t><hit>" })
325     static int indexOf_match_at_end_of_string_imm2_needle(String s) {
326         int index = s.indexOf("<h");
327         return index;
328     }
329 
330     @Test(role = Role.TEST_HELPER, compileAt = 4, warmup = 1, warmupArgs = { "<t><hi><t><h><hit<t><hit>" })
331     static int indexOf_match_at_end_of_string_imm1_needle(String s) {
332         int index = s.indexOf("h");
333         return index;
334     }
335 
336     static String s0_1 = text3.substring(0, len3-1);
337     static String s0_2 = text3.substring(0, len3-2);
338     static String s0_3 = text3.substring(0, len3-3);
339     static String s0_4 = text3.substring(0, len3-4);
340     static String s1_1 = text4.substring(0, len4-1);
341     static String s1_2 = text4.substring(0, len4-2);
342     static String s1_3 = text4.substring(0, len4-3);
343     static String s1_4 = text4.substring(0, len4-4);
344     static String s2_1 = text5.substring(0, len5-1);
345     static String s2_2 = text5.substring(0, len5-2);
346     static String s2_3 = text5.substring(0, len5-3);
347     static String s2_4 = text5.substring(0, len5-4);
348     static String s3_1 = text6.substring(0, len6-1);
349     static String s3_2 = text6.substring(0, len6-2);
350     static String s3_3 = text6.substring(0, len6-3);
351     static String s3_4 = text6.substring(0, len6-4);
352 
353     static String s0_1x = text7 .substring(0, text7 .length()-1);
354     static String s1_1x = text8 .substring(0, text8 .length()-1);
355     static String s2_1x = text9 .substring(0, text9 .length()-1);
356     static String s3_1x = text10.substring(0, text10.length()-1);
357 
358     @Test(role = Role.TEST_ENTRY)
359     public static void test_indexOf_match_spans_end_of_string() {
360         String res = null;
361         res = indexOf_match_spans_end_of_string_unknown_needle(s0_1, "<hit>");
362         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_unknown_needle s0_1 " + res);
363         res = indexOf_match_spans_end_of_string_unknown_needle(s0_2, "<hit>");
364         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_unknown_needle s0_2 " + res);
365         res = indexOf_match_spans_end_of_string_unknown_needle(s0_3, "<hit>");
366         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_unknown_needle s0_3 " + res);
367         res = indexOf_match_spans_end_of_string_unknown_needle(s0_4, "<hit>");
368         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_unknown_needle s0_4 " + res);
369         res = indexOf_match_spans_end_of_string_unknown_needle(s1_1, "<hit>");
370         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_unknown_needle s1_1 " + res);
371         res = indexOf_match_spans_end_of_string_unknown_needle(s1_2, "<hit>");
372         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_unknown_needle s1_2 " + res);
373         res = indexOf_match_spans_end_of_string_unknown_needle(s1_3, "<hit>");
374         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_unknown_needle s1_3 " + res);
375         res = indexOf_match_spans_end_of_string_unknown_needle(s1_4, "<hit>");
376         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_unknown_needle s1_4 " + res);
377         res = indexOf_match_spans_end_of_string_unknown_needle(s2_1, "<hit>");
378         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_unknown_needle s2_1 " + res);
379         res = indexOf_match_spans_end_of_string_unknown_needle(s2_2, "<hit>");
380         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_unknown_needle s2_2 " + res);
381         res = indexOf_match_spans_end_of_string_unknown_needle(s2_3, "<hit>");
382         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_unknown_needle s2_3 " + res);
383         res = indexOf_match_spans_end_of_string_unknown_needle(s2_4, "<hit>");
384         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_unknown_needle s2_4 " + res);
385         res = indexOf_match_spans_end_of_string_unknown_needle(s3_1, "<hit>");
386         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_unknown_needle s3_1 " + res);
387         res = indexOf_match_spans_end_of_string_unknown_needle(s3_2, "<hit>");
388         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_unknown_needle s3_2 " + res);
389         res = indexOf_match_spans_end_of_string_unknown_needle(s3_3, "<hit>");
390         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_unknown_needle s3_3 " + res);
391         res = indexOf_match_spans_end_of_string_unknown_needle(s3_4, "<hit>");
392         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_unknown_needle s3_4 " + res);
393 
394         res = indexOf_match_spans_end_of_string_imm_needle(s0_1);
395         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_imm_needle s0_1 " + res);
396         res = indexOf_match_spans_end_of_string_imm_needle(s0_2);
397         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_imm_needle s0_2 " + res);
398         res = indexOf_match_spans_end_of_string_imm_needle(s0_3);
399         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_imm_needle s0_3 " + res);
400         res = indexOf_match_spans_end_of_string_imm_needle(s0_4);
401         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_imm_needle s0_4 " + res);
402         res = indexOf_match_spans_end_of_string_imm_needle(s1_1);
403         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_imm_needle s1_1 " + res);
404         res = indexOf_match_spans_end_of_string_imm_needle(s1_2);
405         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_imm_needle s1_2 " + res);
406         res = indexOf_match_spans_end_of_string_imm_needle(s1_3);
407         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_imm_needle s1_3 " + res);
408         res = indexOf_match_spans_end_of_string_imm_needle(s1_4);
409         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_imm_needle s1_4 " + res);
410         res = indexOf_match_spans_end_of_string_imm_needle(s2_1);
411         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_imm_needle s2_1 " + res);
412         res = indexOf_match_spans_end_of_string_imm_needle(s2_2);
413         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_imm_needle s2_2 " + res);
414         res = indexOf_match_spans_end_of_string_imm_needle(s2_3);
415         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_imm_needle s2_3 " + res);
416         res = indexOf_match_spans_end_of_string_imm_needle(s2_4);
417         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_imm_needle s2_4 " + res);
418         res = indexOf_match_spans_end_of_string_imm_needle(s3_1);
419         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_imm_needle s3_1 " + res);
420         res = indexOf_match_spans_end_of_string_imm_needle(s3_2);
421         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_imm_needle s3_2 " + res);
422         res = indexOf_match_spans_end_of_string_imm_needle(s3_3);
423         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_imm_needle s3_3 " + res);
424         res = indexOf_match_spans_end_of_string_imm_needle(s3_4);
425         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_imm_needle s3_4 " + res);
426 
427         res = indexOf_match_spans_end_of_string_imm2_needle(s0_1x);
428         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_imm2_needle s0_1x " + res);
429         res = indexOf_match_spans_end_of_string_imm2_needle(s1_1x);
430         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_imm2_needle s1_1x " + res);
431         res = indexOf_match_spans_end_of_string_imm2_needle(s2_1x);
432         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_imm2_needle s2_1x " + res);
433         res = indexOf_match_spans_end_of_string_imm2_needle(s3_1x);
434         assertEquals(res, null, "test_indexOf_match_spans_end_of_string_imm2_needle s3_1x " + res);
435     }
436 
437     @Test(role = Role.TEST_HELPER, compileAt = 4, warmup = 1, warmupArgs = { "<t><hi><t><h><hit<t><hit", "<hit>" })
438     static String indexOf_match_spans_end_of_string_unknown_needle(String s, String needle) {
439         int index = s.indexOf(needle);
440         if (index > -1) {
441             return "Found needle \"" + needle + "\" that is spanning the end of the string: " + s + ".";
442         }
443         return null;
444     }
445 
446     @Test(role = Role.TEST_HELPER, compileAt = 4, warmup = 1, warmupArgs = { "<t><hi><t><h><hit<t><hit" })
447     static String indexOf_match_spans_end_of_string_imm_needle(String s) {
448         int index = s.indexOf("<hit>");
449         if (index > -1) {
450             return "Found needle \"<hit>\" that is spanning the end of the string: " + s + ".";
451         }
452         return null;
453     }
454 
455     @Test(role = Role.TEST_HELPER, compileAt = 4, warmup = 1, warmupArgs = { "<t><t><t><t><t<t><" })
456     static String indexOf_match_spans_end_of_string_imm2_needle(String s) {
457         int index = s.indexOf("<h");
458         if (index > -1) {
459             return "Found needle \"<h\" that is spanning the end of the string: " + s + ".";
460         }
461         return null;
462     }
463 
464     static String text16 = "ooooooo";
465     static String text11 = "1ooooooo";
466     static String text12 = "ooooooo1";
467     static String text13 = "oooooooo1";
468     static String text14 = "ooooooooo1";
469     static String text15 = "oooooooooo1";
470     static int len12 = text12.length();
471     static int len13 = text13.length();
472     static int len14 = text14.length();
473     static int len15 = text15.length();
474 
475     static String text12_1 = text12.substring(0, len12-1);
476     static String text13_1 = text13.substring(0, len13-1);
477     static String text14_1 = text14.substring(0, len14-1);
478     static String text15_1 = text15.substring(0, len15-1);
479 
480     @Test(role = Role.TEST_ENTRY)
481     public static void test_indexOf_imm1_needle() {
482         assertEquals(     -1, indexOf_imm1_needle(text16), "test_indexOf_imm1_needle no_match");
483 
484         assertEquals(      0, indexOf_imm1_needle(text11), "test_indexOf_imm1_needle first_matches");
485 
486         assertEquals(len12-1, indexOf_imm1_needle(text12), "test_indexOf_imm1_needle last_matches");
487         assertEquals(len13-1, indexOf_imm1_needle(text13), "test_indexOf_imm1_needle last_matches");
488         assertEquals(len14-1, indexOf_imm1_needle(text14), "test_indexOf_imm1_needle last_matches");
489         assertEquals(len15-1, indexOf_imm1_needle(text15), "test_indexOf_imm1_needle last_matches");
490 
491         assertEquals(     -1, indexOf_imm1_needle(text12_1), "test_indexOf_imm1_needle walked_past");
492         assertEquals(     -1, indexOf_imm1_needle(text13_1), "test_indexOf_imm1_needle walked_past");
493         assertEquals(     -1, indexOf_imm1_needle(text14_1), "test_indexOf_imm1_needle walked_past");
494         assertEquals(     -1, indexOf_imm1_needle(text15_1), "test_indexOf_imm1_needle walked_past");
495     }
496 
497     @Test(role = Role.TEST_HELPER, compileAt = 4, warmup = 1, warmupArgs = { "ooooooo1" })
498     static int indexOf_imm1_needle(String s) {
499         return s.indexOf("1");
500     }
501 
502     static String text1UTF16 = "A" + "\u05d0" + "\u05d1" + "B";
503 
504     @Test(role = Role.TEST_ENTRY)
505     public static void test_indexOf_immUTF16() {
506         assertEquals(      3, indexOf_imm1Latin1_needle(text1UTF16), "test_indexOf_immUTF16");
507         assertEquals(      1, indexOf_imm1UTF16_needle(text1UTF16), "test_indexOf_immUTF16");
508         assertEquals(      1, indexOf_immUTF16_needle(text1UTF16), "test_indexOf_immUTF16");
509     }
510 
511     @Test(role = Role.TEST_HELPER, compileAt = 4, warmup = 1, warmupArgs = { "A" + "\u05d0" + "\u05d1" + "B" })
512     static int indexOf_imm1Latin1_needle(String s) {
513         return s.indexOf("B");
514     }
515 
516     @Test(role = Role.TEST_HELPER, compileAt = 4, warmup = 1, warmupArgs = { "A" + "\u05d0" + "\u05d1" + "B" })
517     static int indexOf_imm1UTF16_needle(String s) {
518         return s.indexOf("\u05d0");
519     }
520 
521     @Test(role = Role.TEST_HELPER, compileAt = 4, warmup = 1, warmupArgs = { "A" + "\u05d0" + "\u05d1" + "B" })
522     static int indexOf_immUTF16_needle(String s) {
523         return s.indexOf("\u05d0" + "\u05d1");
524     }
525 
526     @Test(role = Role.TEST_HELPER, compileAt = 4, warmup = 1, warmupArgs = { "abc", "abcd" })
527     public static int asmStringCompareTo(String a, String b) {
528         return a.compareTo(b);
529     }
530 
531     @Test(role = Role.TEST_ENTRY)
532     public static void test_asmStringCompareTo() {
533         // null
534         try {
535             asmStringCompareTo("not null", null);
536             assertTrue(false,
537                        "TestOther.asmStringCompareTo(\"not null\", null) doesn't throw exception");
538         } catch (NullPointerException e) {
539             assertEquals("java.lang.String.compareTo",
540                          e.getStackTrace()[0].getClassName() + "." +
541                          e.getStackTrace()[0].getMethodName(),
542                          "TestOther.asmStringCompareTo(\"not null\", null) throws exception");
543         }
544 
545         // ==0
546         {
547             // check length 0 optimization
548             assertEquals(0, asmStringCompareTo("", ""),
549                          "TestOther.asmStringCompareTo(\"\", \"\")");
550 
551             // check first character optimization
552             assertEquals(0, asmStringCompareTo("A", "A"),
553                          "TestOther.asmStringCompareTo(\"A\", \"A\")");
554 
555             // check real comparisons
556             assertEquals(0, asmStringCompareTo(new String("eq") + new String("ual"), "equal"),
557                          "TestOther.asmStringCompareTo(\"equal\", \"equal\")");
558             assertEquals(0, asmStringCompareTo("textABC", "textABC"),
559                          "TestOther.asmStringCompareTo(\"textABC\", \"textABC\")");
560             assertEquals(0,
561                          asmStringCompareTo(new String("abcdefgh01234") +
562                                             new String("56abcdefgh0123456abcdefgh0123456"),
563                                             "abcdefgh0123456abcdefgh0123456abcdefgh0123456"),
564                          "TestOther.asmStringCompareTo(\"abcdefgh0123456abcdefgh0123456abcdefgh0123456\", " +
565                          "\"abcdefgh0123456abcdefgh0123456abcdefgh0123456\")");
566         }
567 
568         // <0
569         {
570             // check first character optimization
571             assertEquals(-1, asmStringCompareTo("4", "5"),
572                          "TestOther.asmStringCompareTo(\"4\", \"5\")");
573 
574             // check real comparisons
575             assertEquals(-1, asmStringCompareTo("diff4", "diff5"),
576                          "TestOther.asmStringCompareTo(\"diff4\", \"diff5\")");
577             assertEquals(-10, asmStringCompareTo("", "123456789A"),
578                          "TestOther.asmStringCompareTo(\"\", \"123456789A\")");
579             assertEquals(-10, asmStringCompareTo("ZYX", "ZYX123456789A"),
580                          "TestOther.asmStringCompareTo(\"ZYX\", \"ZYX123456789A\")");
581         }
582 
583         // >0
584         {
585             // check first character optimization
586             assertEquals(1, asmStringCompareTo("5", "4"),
587                          "TestOther.asmStringCompareTo(\"5\", \"4\")");
588 
589             // check real comparisons
590             assertEquals(1, asmStringCompareTo("diff5", "diff4"),
591                          "TestOther.asmStringCompareTo(\"diff5\", \"diff4\")");
592             assertEquals(10, asmStringCompareTo("123456789A", ""),
593                          "TestOther.asmStringCompareTo(\"123456789A\", \"\")");
594             assertEquals(10, asmStringCompareTo("ZYX123456789A", "ZYX"),
595                          "TestOther.asmStringCompareTo(\"ZYX123456789A\", \"ZYX\")");
596         }
597 
598         // very long strings (100k)
599         {
600             char[] ac = new char[(100 * 1024)];
601             for (int i = 0; i < (100 * 1024); i += 315)
602                 ac[i] = (char) ((i % 12) + 'a');
603             char[] bc = new char[(100 * 1024)];
604             for (int i = 0; i < (100 * 1024); i += 315)
605                 bc[i] = (char) ((i % 12) + 'a');
606 
607             ac[(100 * 1024) - 1] = '2';
608             bc[(100 * 1024) - 1] = '2';
609             String a1 = new String(ac);
610             String b1 = new String(bc);
611             assertEquals(0, asmStringCompareTo(a1, b1),
612                          "TestOther.asmStringCompareTo(very_long_strings_1)");
613 
614             ac[(100 * 1024) - 1] = 'X';
615             bc[(100 * 1024) - 1] = 'Z';
616             String a2 = new String(ac);
617             String b2 = new String(bc);
618             assertEquals(-2, asmStringCompareTo(a2, b2),
619                          "TestOther.asmStringCompareTo(very_long_strings_2)");
620         }
621 
622         // very very long strings (2M)
623         {
624             char[] ac = new char[(2 * 1024 * 1024)];
625             for (int i = 0; i < (2 * 1024 * 1024); i += 315)
626                 ac[i] = (char) ((i % 12) + 'a');
627             char[] bc = new char[(2 * 1024 * 1024)];
628             for (int i = 0; i < (2 * 1024 * 1024); i += 315)
629                 bc[i] = (char) ((i % 12) + 'a');
630 
631             ac[(2 * 1024 * 1024) - 1] = '3';
632             bc[(2 * 1024 * 1024) - 1] = '3';
633             String a1 = new String(ac);
634             String b1 = new String(bc);
635             assertEquals(0, asmStringCompareTo(a1, b1),
636                          "TestOther.asmStringCompareTo(very_very_long_strings_1)");
637 
638             ac[(2 * 1024 * 1024) - 1] = 'W';
639             bc[(2 * 1024 * 1024) - 1] = 'Z';
640             String a2 = new String(ac);
641             String b2 = new String(bc);
642             assertEquals(-3, asmStringCompareTo(a2, b2),
643                          "TestOther.asmStringCompareTo(very_very_long_strings_2)");
644         }
645 
646         // See bug 8215100
647         {
648             assertEquals(-20, asmStringCompareTo("e.\u0259.", "y.e."));
649             assertEquals(20, asmStringCompareTo("y.e.", "e.\u0259."));
650         }
651     }
652 
653 
654     @Test(role = Role.TEST_HELPER, compileAt = 4, warmup = 1, warmupArgs = { "abc", "abcd" })
655     public static boolean asmStringEquals(String a, String b) {
656         return a.equals(b);
657     }
658 
659     static String a1 = "abcd";
660     static String b1 = "abcd";
661     static final String a2 = "1234";
662     static final String b2 = "1234";
663 
664     @Test(role = Role.TEST_HELPER, compileAt = 4, warmup = 1)
665     public static boolean asmStringEqualsConst() {
666         boolean ret = a1.equals(b1);
667         ret &= a2.equals(b2);
668         ret &= !a2.equals(b1);
669         ret &= "ABCD".equals("ABCD");
670         return ret;
671     }
672 
673 
674     @Test(role = Role.TEST_ENTRY)
675     public static void test_asmStringEquals() {
676         // null
677         {
678             assertFalse(asmStringEquals("not null", null),
679                         "TestOther.asmStringEquals(\"not null\", null)");
680         }
681 
682         // true
683         {
684             // check constant optimization
685             assertTrue(asmStringEqualsConst(),
686                        "TestOther.asmStringEqualsConst(\"\", \"\")");
687 
688             // check length 0 optimization
689             assertTrue(asmStringEquals("", ""),
690                        "TestOther.asmStringEquals(\"\", \"\")");
691 
692             // check first character optimization
693             assertTrue(asmStringEquals("A", "A"),
694                        "TestOther.asmStringEquals(\"A\", \"A\")");
695 
696             // check real comparisons
697             assertTrue(asmStringEquals(new String("eq") + new String("ual"), "equal"),
698                        "TestOther.asmStringEquals(\"equal\", \"equal\")");
699             assertTrue(asmStringEquals("textABC", "textABC"),
700                        "TestOther.asmStringEquals(\"textABC\", \"textABC\")");
701             assertTrue(asmStringEquals(new String("abcdefgh01234") +
702                                        new String("56abcdefgh0123456abcdefgh0123456"),
703                                        "abcdefgh0123456abcdefgh0123456abcdefgh0123456"),
704                        "TestOther.asmStringEquals(\"abcdefgh0123456abcdefgh0123456abcdefgh0123456\", " +
705                        "\"abcdefgh0123456abcdefgh0123456abcdefgh0123456\")");
706         }
707     }
708 
709 }
710