001/*
002 * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.
008 *
009 * This code is distributed in the hope that it will be useful, but WITHOUT
010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
011 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
012 * version 2 for more details (a copy is included in the LICENSE file that
013 * accompanied this code).
014 *
015 * You should have received a copy of the GNU General Public License version
016 * 2 along with this work; if not, write to the Free Software Foundation,
017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
018 *
019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
020 * or visit www.oracle.com if you need additional information or have any
021 * questions.
022 */
023package com.oracle.graal.replacements.test;
024
025import java.util.*;
026
027import org.junit.*;
028
029import com.oracle.graal.nodes.*;
030import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
031import com.oracle.graal.phases.*;
032import com.oracle.graal.phases.common.*;
033import com.oracle.graal.phases.common.inlining.*;
034import com.oracle.graal.phases.tiers.*;
035import com.oracle.graal.replacements.*;
036import com.oracle.graal.replacements.nodes.*;
037import com.oracle.graal.virtual.phases.ea.*;
038
039/**
040 * Tests {@link ArraysSubstitutions}.
041 */
042public class ArraysSubstitutionsTest extends MethodSubstitutionTest {
043
044    private static final int N = 10;
045
046    @Test
047    public void testEqualsBoolean() {
048        Object[] args1 = new Object[N];
049        Object[] args2 = new Object[N];
050        int n = 0;
051
052        // equal arrays
053        for (int i = 0; i < N / 2; i++, n++) {
054            args1[n] = new boolean[i];
055            args2[n] = new boolean[i];
056        }
057
058        // non-equal arrays
059        for (int i = 0; i < N / 2; i++, n++) {
060            boolean[] a2 = new boolean[i];
061            if (i > 0) {
062                a2[i - 1] = true;
063            }
064            args1[n] = new boolean[i];
065            args2[n] = a2;
066        }
067        Class<?>[] parameterTypes = new Class<?>[]{boolean[].class, boolean[].class};
068        testSubstitution("arraysEqualsBoolean", ArrayEqualsNode.class, Arrays.class, "equals", parameterTypes, false, args1, args2);
069    }
070
071    @SuppressWarnings("all")
072    public static boolean arraysEqualsBoolean(boolean[] a, boolean[] b) {
073        return Arrays.equals(a, b);
074    }
075
076    @Test
077    public void testEqualsByte() {
078        Object[] args1 = new Object[N];
079        Object[] args2 = new Object[N];
080        int n = 0;
081
082        // equal arrays
083        for (int i = 0; i < N / 2; i++, n++) {
084            args1[n] = new byte[i];
085            args2[n] = new byte[i];
086        }
087
088        // non-equal arrays
089        for (int i = 0; i < N / 2; i++, n++) {
090            byte[] a2 = new byte[i];
091            if (i > 0) {
092                a2[i - 1] = 1;
093            }
094            args1[n] = new byte[i];
095            args2[n] = a2;
096        }
097
098        Class<?>[] parameterTypes = new Class<?>[]{byte[].class, byte[].class};
099        testSubstitution("arraysEqualsByte", ArrayEqualsNode.class, Arrays.class, "equals", parameterTypes, false, args1, args2);
100    }
101
102    @SuppressWarnings("all")
103    public static boolean arraysEqualsByte(byte[] a, byte[] b) {
104        return Arrays.equals(a, b);
105    }
106
107    @Test
108    public void testEqualsChar() {
109        Object[] args1 = new Object[N];
110        Object[] args2 = new Object[N];
111        int n = 0;
112
113        // equal arrays
114        for (int i = 0; i < N / 2; i++, n++) {
115            args1[n] = new char[i];
116            args2[n] = new char[i];
117        }
118
119        // non-equal arrays
120        for (int i = 0; i < N / 2; i++, n++) {
121            char[] a2 = new char[i];
122            if (i > 0) {
123                a2[i - 1] = 1;
124            }
125            args1[n] = new char[i];
126            args2[n] = a2;
127        }
128
129        Class<?>[] parameterTypes = new Class<?>[]{char[].class, char[].class};
130        testSubstitution("arraysEqualsChar", ArrayEqualsNode.class, Arrays.class, "equals", parameterTypes, false, args1, args2);
131    }
132
133    @SuppressWarnings("all")
134    public static boolean arraysEqualsChar(char[] a, char[] b) {
135        return Arrays.equals(a, b);
136    }
137
138    @Test
139    public void testEqualsShort() {
140        Object[] args1 = new Object[N];
141        Object[] args2 = new Object[N];
142        int n = 0;
143
144        // equal arrays
145        for (int i = 0; i < N / 2; i++, n++) {
146            args1[n] = new short[i];
147            args2[n] = new short[i];
148        }
149
150        // non-equal arrays
151        for (int i = 0; i < N / 2; i++, n++) {
152            short[] a2 = new short[i];
153            if (i > 0) {
154                a2[i - 1] = 1;
155            }
156            args1[n] = new short[i];
157            args2[n] = a2;
158        }
159
160        Class<?>[] parameterTypes = new Class<?>[]{short[].class, short[].class};
161        testSubstitution("arraysEqualsShort", ArrayEqualsNode.class, Arrays.class, "equals", parameterTypes, false, args1, args2);
162    }
163
164    @SuppressWarnings("all")
165    public static boolean arraysEqualsShort(short[] a, short[] b) {
166        return Arrays.equals(a, b);
167    }
168
169    @Test
170    public void testEqualsInt() {
171        Object[] args1 = new Object[N];
172        Object[] args2 = new Object[N];
173        int n = 0;
174
175        // equal arrays
176        for (int i = 0; i < N / 2; i++, n++) {
177            args1[n] = new int[i];
178            args2[n] = new int[i];
179        }
180
181        // non-equal arrays
182        for (int i = 0; i < N / 2; i++, n++) {
183            int[] a2 = new int[i];
184            if (i > 0) {
185                a2[i - 1] = 1;
186            }
187            args1[n] = new int[i];
188            args2[n] = a2;
189        }
190
191        Class<?>[] parameterTypes = new Class<?>[]{int[].class, int[].class};
192        testSubstitution("arraysEqualsInt", ArrayEqualsNode.class, Arrays.class, "equals", parameterTypes, false, args1, args2);
193    }
194
195    @SuppressWarnings("all")
196    public static boolean arraysEqualsInt(int[] a, int[] b) {
197        return Arrays.equals(a, b);
198    }
199
200    @Test
201    public void testEqualsLong() {
202        Object[] args1 = new Object[N];
203        Object[] args2 = new Object[N];
204        int n = 0;
205
206        // equal arrays
207        for (int i = 0; i < N / 2; i++, n++) {
208            args1[n] = new long[i];
209            args2[n] = new long[i];
210        }
211
212        // non-equal arrays
213        for (int i = 0; i < N / 2; i++, n++) {
214            long[] a2 = new long[i];
215            if (i > 0) {
216                a2[i - 1] = 1;
217            }
218            args1[n] = new long[i];
219            args2[n] = a2;
220        }
221
222        Class<?>[] parameterTypes = new Class<?>[]{long[].class, long[].class};
223        testSubstitution("arraysEqualsLong", ArrayEqualsNode.class, Arrays.class, "equals", parameterTypes, false, args1, args2);
224    }
225
226    @SuppressWarnings("all")
227    public static boolean arraysEqualsLong(long[] a, long[] b) {
228        return Arrays.equals(a, b);
229    }
230
231    @Test
232    public void testEqualsFloat() {
233        Object[] args1 = new Object[N];
234        Object[] args2 = new Object[N];
235        int n = 0;
236
237        // equal arrays
238        for (int i = 0; i < N / 2; i++, n++) {
239            args1[n] = new float[i];
240            args2[n] = new float[i];
241        }
242
243        // non-equal arrays
244        for (int i = 0; i < N / 2; i++, n++) {
245            float[] a2 = new float[i];
246            if (i > 0) {
247                a2[i - 1] = 1;
248            }
249            args1[n] = new float[i];
250            args2[n] = a2;
251        }
252
253        Class<?>[] parameterTypes = new Class<?>[]{float[].class, float[].class};
254        testSubstitution("arraysEqualsFloat", ArrayEqualsNode.class, Arrays.class, "equals", parameterTypes, false, args1, args2);
255    }
256
257    @SuppressWarnings("all")
258    public static boolean arraysEqualsFloat(float[] a, float[] b) {
259        return Arrays.equals(a, b);
260    }
261
262    @Test
263    public void testEqualsDouble() {
264        Object[] args1 = new Object[N];
265        Object[] args2 = new Object[N];
266        int n = 0;
267
268        // equal arrays
269        for (int i = 0; i < N / 2; i++, n++) {
270            args1[n] = new double[i];
271            args2[n] = new double[i];
272        }
273
274        // non-equal arrays
275        for (int i = 0; i < N / 2; i++, n++) {
276            double[] a2 = new double[i];
277            if (i > 0) {
278                a2[i - 1] = 1;
279            }
280            args1[n] = new double[i];
281            args2[n] = a2;
282        }
283
284        Class<?>[] parameterTypes = new Class<?>[]{double[].class, double[].class};
285        testSubstitution("arraysEqualsDouble", ArrayEqualsNode.class, Arrays.class, "equals", parameterTypes, false, args1, args2);
286    }
287
288    @SuppressWarnings("all")
289    public static boolean arraysEqualsDouble(double[] a, double[] b) {
290        return Arrays.equals(a, b);
291    }
292
293    @Test
294    public void testEqualsNodeGVN() {
295        test("testEqualsNodeGVNSnippet", true);
296    }
297
298    public static int[] intArrayCompare = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9};
299    public static int[] intArray;
300
301    public static boolean testEqualsNodeGVNSnippet(boolean b) {
302        int[] newIntArray = new int[]{0, 2, 3, 4, 5, 6, 7, 8, 9};
303        intArray = newIntArray;
304
305        if (b) {
306            newIntArray[0] = 1;
307            return Arrays.equals(newIntArray, intArrayCompare);
308        } else {
309            newIntArray[0] = 1;
310            return Arrays.equals(newIntArray, intArrayCompare);
311        }
312    }
313
314    @Test
315    public void testConstants() {
316        testGraph("testConstantsSnippet");
317    }
318
319    public static final int[] constantArray1 = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9};
320    public static final int[] constantArray2 = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9};
321
322    public static boolean testConstantsSnippet() {
323        constantArray2[0] = 10;
324        try {
325            return Arrays.equals(constantArray1, constantArray2);
326        } finally {
327            constantArray2[0] = 1;
328        }
329    }
330
331    @Test
332    public void testCanonicalLength() {
333        StructuredGraph graph = parseEager("testCanonicalLengthSnippet", AllowAssumptions.NO);
334        HighTierContext context = new HighTierContext(getProviders(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
335        new InliningPhase(new CanonicalizerPhase()).apply(graph, context);
336        new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
337
338        Assert.assertTrue(graph.getNodes(ReturnNode.TYPE).first().result().asJavaConstant().asLong() == 0);
339    }
340
341    public static final int[] constantArray3 = new int[]{1, 2, 3};
342
343    public static boolean testCanonicalLengthSnippet() {
344        return Arrays.equals(constantArray1, constantArray3);
345    }
346
347    @Test
348    public void testCanonicalEqual() {
349        StructuredGraph graph = parseEager("testCanonicalEqualSnippet", AllowAssumptions.NO);
350        HighTierContext context = new HighTierContext(getProviders(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
351        new InliningPhase(new CanonicalizerPhase()).apply(graph, context);
352        new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
353
354        Assert.assertTrue(graph.getNodes(ReturnNode.TYPE).first().result().asJavaConstant().asLong() == 1);
355    }
356
357    public static boolean testCanonicalEqualSnippet() {
358        return Arrays.equals(constantArray1, constantArray1);
359    }
360
361    @Test
362    public void testVirtualEqual() {
363        StructuredGraph graph = parseEager("testVirtualEqualSnippet", AllowAssumptions.NO);
364        HighTierContext context = new HighTierContext(getProviders(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
365        new InliningPhase(new CanonicalizerPhase()).apply(graph, context);
366        new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
367        new PartialEscapePhase(false, new CanonicalizerPhase()).apply(graph, context);
368        new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
369
370        Assert.assertTrue(graph.getNodes(ReturnNode.TYPE).first().result().asJavaConstant().asLong() == 1);
371    }
372
373    public static boolean testVirtualEqualSnippet() {
374        int[] array1 = new int[]{1, 2, 3, 4};
375        int[] array2 = new int[]{1, 2, 3, 4};
376        return Arrays.equals(array1, array2);
377    }
378
379    @Test
380    public void testVirtualNotEqual() {
381        StructuredGraph graph = parseEager("testVirtualNotEqualSnippet", AllowAssumptions.NO);
382        HighTierContext context = getDefaultHighTierContext();
383        new InliningPhase(new CanonicalizerPhase()).apply(graph, context);
384        new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
385        new PartialEscapePhase(false, new CanonicalizerPhase()).apply(graph, context);
386        new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
387
388        Assert.assertTrue(graph.getNodes(ReturnNode.TYPE).first().result().asJavaConstant().asLong() == 0);
389    }
390
391    public static boolean testVirtualNotEqualSnippet(int x) {
392        int[] array1 = new int[]{1, 2, 100, x};
393        int[] array2 = new int[]{1, 2, 3, 4};
394        return Arrays.equals(array1, array2);
395    }
396}