1 /*
2  * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 
25 package org.graalvm.compiler.replacements.test;
26 
27 import org.graalvm.compiler.nodes.StructuredGraph;
28 import org.graalvm.compiler.replacements.StringSubstitutions;
29 import org.graalvm.compiler.replacements.nodes.ArrayEqualsNode;
30 import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
31 import org.junit.Test;
32 
33 import jdk.vm.ci.code.InstalledCode;
34 import jdk.vm.ci.meta.ResolvedJavaMethod;
35 
36 /**
37  * Tests {@link StringSubstitutions}.
38  */
39 public class StringSubstitutionsTest extends MethodSubstitutionTest {
40 
testSubstitution(String testMethodName, Class<?> intrinsicClass, Class<?> holder, String methodName, boolean optional, Object[] args1, Object[] args2)41     public void testSubstitution(String testMethodName, Class<?> intrinsicClass, Class<?> holder, String methodName, boolean optional, Object[] args1, Object[] args2) {
42         ResolvedJavaMethod realMethod = getResolvedJavaMethod(holder, methodName);
43         ResolvedJavaMethod testMethod = getResolvedJavaMethod(testMethodName);
44         StructuredGraph graph = testGraph(testMethodName);
45 
46         // Check to see if the resulting graph contains the expected node
47         StructuredGraph replacement = getReplacements().getSubstitution(realMethod, -1, false, null, graph.getOptions());
48         if (replacement == null && !optional) {
49             assertInGraph(graph, intrinsicClass);
50         }
51 
52         // Force compilation
53         InstalledCode code = getCode(testMethod);
54         assert optional || code != null;
55 
56         for (int i = 0; i < args1.length; i++) {
57             Object arg1 = args1[i];
58             Object arg2 = args2[i];
59             Object expected = invokeSafe(realMethod, arg1, arg2);
60             // Verify that the original method and the substitution produce the same value
61             assertDeepEquals(expected, invokeSafe(testMethod, null, arg1, arg2));
62             // Verify that the generated code and the original produce the same value
63             assertDeepEquals(expected, executeVarargsSafe(code, arg1, arg2));
64         }
65     }
66 
67     @Test
testEquals()68     public void testEquals() {
69         if (JavaVersionUtil.JAVA_SPEC > 8) {
70             // StringSubstitutions are disabled in 1.9
71             return;
72         }
73 
74         final int n = 1000;
75         Object[] args1 = new Object[n];
76         Object[] args2 = new Object[n];
77 
78         // equal strings
79         String s1 = "";
80         String s2 = "";
81         for (int i = 0; i < n / 2; i++) {
82             args1[i] = s1;
83             args2[i] = s2;
84             s1 = s1 + "0";
85             s2 = s2 + "0";
86         }
87 
88         // non-equal strings
89         s1 = "";
90         s2 = "";
91         for (int i = n / 2; i < n; i++) {
92             args1[i] = s1;
93             args2[i] = s2;
94             s2 = s1 + "1";
95             s1 = s1 + "0";
96         }
97 
98         testSubstitution("stringEquals", ArrayEqualsNode.class, String.class, "equals", false, args1, args2);
99     }
100 
101     @SuppressWarnings("all")
stringEquals(String a, String b)102     public static boolean stringEquals(String a, String b) {
103         return a.equals(b);
104     }
105 
106     @Test
testIndexOfConstant()107     public void testIndexOfConstant() {
108         test("indexOfConstant");
109     }
110 
indexOfConstant()111     public int indexOfConstant() {
112         String foobar = "foobar";
113         String bar = "bar";
114         return foobar.indexOf(bar);
115     }
116 
117     @Test
testIndexOfConstantUTF16()118     public void testIndexOfConstantUTF16() {
119         test("indexOfConstantUTF16case1");
120         test("indexOfConstantUTF16case2");
121         test("indexOfConstantUTF16case3");
122     }
123 
indexOfConstantUTF16case1()124     public int indexOfConstantUTF16case1() {
125         return ("grga " + ((char) 0x10D) + "varak").indexOf(((char) 0x10D) + "varak");
126     }
127 
indexOfConstantUTF16case2()128     public int indexOfConstantUTF16case2() {
129         int index = ("grga " + ((char) 0xD) + "varak").indexOf(((char) 0x10D) + "varak");
130         return index;
131     }
132 
indexOfConstantUTF16case3()133     public int indexOfConstantUTF16case3() {
134         int index = ("grga " + ((char) 0x100) + "varak").indexOf(((char) 0x10D) + "varak");
135         return index;
136     }
137 
138     @Test
testCompareTo()139     public void testCompareTo() {
140         test("compareTo");
141     }
142 
compareTo()143     public int compareTo() {
144         return "ofar".compareTo("rafo");
145     }
146 }
147