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 static org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
28 
29 import java.util.Arrays;
30 
31 import org.graalvm.compiler.nodes.ReturnNode;
32 import org.graalvm.compiler.nodes.StructuredGraph;
33 import org.graalvm.compiler.phases.OptimisticOptimizations;
34 import org.graalvm.compiler.phases.tiers.HighTierContext;
35 import org.graalvm.compiler.replacements.nodes.ArrayEqualsNode;
36 import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase;
37 import org.junit.Assert;
38 import org.junit.Test;
39 
40 public class ArraysSubstitutionsTest extends ArraysSubstitutionsTestBase {
41 
42     private static final int N = 10;
43 
testEquals(String methodName, Class<?>[] parameterTypes, ArrayBuilder builder)44     private void testEquals(String methodName, Class<?>[] parameterTypes, ArrayBuilder builder) {
45         Object[] args1 = new Object[N];
46         Object[] args2 = new Object[N];
47         int n = 0;
48         // equal arrays
49         for (int i = 0; i < N / 2; i++, n++) {
50             args1[n] = builder.newArray(i, 0, 1);
51             args2[n] = builder.newArray(i, 0, 1);
52         }
53         // non-equal arrays
54         for (int i = 0; i < N / 2; i++, n++) {
55             args1[n] = builder.newArray(i, 0, 1);
56             args2[n] = builder.newArray(i, 1, 1);
57         }
58         testSubstitution(methodName, ArrayEqualsNode.class, Arrays.class, "equals", parameterTypes, false, false, args1, args2);
59     }
60 
61     @Test
testEqualsBoolean()62     public void testEqualsBoolean() {
63         testEquals("arraysEqualsBoolean", new Class<?>[]{boolean[].class, boolean[].class}, ArraysSubstitutionsTestBase::booleanArray);
64     }
65 
66     @Test
testEqualsByte()67     public void testEqualsByte() {
68         testEquals("arraysEqualsByte", new Class<?>[]{byte[].class, byte[].class}, ArraysSubstitutionsTestBase::byteArray);
69     }
70 
71     @Test
testEqualsChar()72     public void testEqualsChar() {
73         testEquals("arraysEqualsChar", new Class<?>[]{char[].class, char[].class}, ArraysSubstitutionsTestBase::charArray);
74     }
75 
76     @Test
testEqualsShort()77     public void testEqualsShort() {
78         testEquals("arraysEqualsShort", new Class<?>[]{short[].class, short[].class}, ArraysSubstitutionsTestBase::shortArray);
79     }
80 
81     @Test
testEqualsInt()82     public void testEqualsInt() {
83         testEquals("arraysEqualsInt", new Class<?>[]{int[].class, int[].class}, ArraysSubstitutionsTestBase::intArray);
84     }
85 
86     @Test
testEqualsLong()87     public void testEqualsLong() {
88         testEquals("arraysEqualsLong", new Class<?>[]{long[].class, long[].class}, ArraysSubstitutionsTestBase::longArray);
89     }
90 
91     @Test
testEqualsNodeGVN()92     public void testEqualsNodeGVN() {
93         test("testEqualsNodeGVNSnippet", true);
94     }
95 
96     public static int[] intArrayCompare = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9};
97     public static int[] intArray;
98 
testEqualsNodeGVNSnippet(boolean b)99     public static boolean testEqualsNodeGVNSnippet(boolean b) {
100         int[] newIntArray = new int[]{0, 2, 3, 4, 5, 6, 7, 8, 9};
101         intArray = newIntArray;
102 
103         if (b) {
104             newIntArray[0] = 1;
105             return Arrays.equals(newIntArray, intArrayCompare);
106         } else {
107             newIntArray[0] = 1;
108             return Arrays.equals(newIntArray, intArrayCompare);
109         }
110     }
111 
112     @Test
testConstants()113     public void testConstants() {
114         testGraph("testConstantsSnippet");
115     }
116 
117     public static final int[] constantArray1 = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9};
118     public static final int[] constantArray2 = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9};
119 
testConstantsSnippet()120     public static boolean testConstantsSnippet() {
121         constantArray2[0] = 10;
122         try {
123             return Arrays.equals(constantArray1, constantArray2);
124         } finally {
125             constantArray2[0] = 1;
126         }
127     }
128 
129     @Test
testCanonicalLength()130     public void testCanonicalLength() {
131         StructuredGraph graph = parseEager("testCanonicalLengthSnippet", AllowAssumptions.NO);
132         HighTierContext context = new HighTierContext(getProviders(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
133         createInliningPhase().apply(graph, context);
134         createCanonicalizerPhase().apply(graph, getProviders());
135 
136         Assert.assertTrue(graph.getNodes(ReturnNode.TYPE).first().result().asJavaConstant().asLong() == 0);
137     }
138 
139     public static final int[] constantArray3 = new int[]{1, 2, 3};
140 
testCanonicalLengthSnippet()141     public static boolean testCanonicalLengthSnippet() {
142         return Arrays.equals(constantArray1, constantArray3);
143     }
144 
145     @Test
testCanonicalEqual()146     public void testCanonicalEqual() {
147         StructuredGraph graph = parseEager("testCanonicalEqualSnippet", AllowAssumptions.NO);
148         HighTierContext context = new HighTierContext(getProviders(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
149         createInliningPhase().apply(graph, context);
150         createCanonicalizerPhase().apply(graph, getProviders());
151 
152         Assert.assertTrue(graph.getNodes(ReturnNode.TYPE).first().result().asJavaConstant().asLong() == 1);
153     }
154 
testCanonicalEqualSnippet()155     public static boolean testCanonicalEqualSnippet() {
156         return Arrays.equals(constantArray1, constantArray1);
157     }
158 
159     @Test
testVirtualEqual()160     public void testVirtualEqual() {
161         StructuredGraph graph = parseEager("testVirtualEqualSnippet", AllowAssumptions.NO);
162         HighTierContext context = new HighTierContext(getProviders(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
163         createInliningPhase().apply(graph, context);
164         createCanonicalizerPhase().apply(graph, getProviders());
165         new PartialEscapePhase(false, this.createCanonicalizerPhase(), graph.getOptions()).apply(graph, context);
166         createCanonicalizerPhase().apply(graph, getProviders());
167 
168         Assert.assertTrue(graph.getNodes(ReturnNode.TYPE).first().result().asJavaConstant().asLong() == 1);
169     }
170 
testVirtualEqualSnippet()171     public static boolean testVirtualEqualSnippet() {
172         int[] array1 = new int[]{1, 2, 3, 4};
173         int[] array2 = new int[]{1, 2, 3, 4};
174         return Arrays.equals(array1, array2);
175     }
176 
177     @Test
testVirtualNotEqual()178     public void testVirtualNotEqual() {
179         StructuredGraph graph = parseEager("testVirtualNotEqualSnippet", AllowAssumptions.NO);
180         HighTierContext context = getDefaultHighTierContext();
181         createInliningPhase().apply(graph, context);
182         createCanonicalizerPhase().apply(graph, getProviders());
183         new PartialEscapePhase(false, this.createCanonicalizerPhase(), graph.getOptions()).apply(graph, context);
184         createCanonicalizerPhase().apply(graph, getProviders());
185 
186         Assert.assertTrue(graph.getNodes(ReturnNode.TYPE).first().result().asJavaConstant().asLong() == 0);
187     }
188 
testVirtualNotEqualSnippet(int x)189     public static boolean testVirtualNotEqualSnippet(int x) {
190         int[] array1 = new int[]{1, 2, 100, x};
191         int[] array2 = new int[]{1, 2, 3, 4};
192         return Arrays.equals(array1, array2);
193     }
194 }
195