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