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 java.util.Arrays; 28 29 import org.junit.Assert; 30 import org.junit.Test; 31 32 import org.graalvm.compiler.nodes.ReturnNode; 33 import org.graalvm.compiler.nodes.StructuredGraph; 34 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; 35 import org.graalvm.compiler.phases.OptimisticOptimizations; 36 import org.graalvm.compiler.phases.common.CanonicalizerPhase; 37 import org.graalvm.compiler.phases.common.inlining.InliningPhase; 38 import org.graalvm.compiler.phases.tiers.HighTierContext; 39 import org.graalvm.compiler.phases.tiers.PhaseContext; 40 import org.graalvm.compiler.replacements.ArraysSubstitutions; 41 import org.graalvm.compiler.replacements.nodes.ArrayEqualsNode; 42 import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; 43 44 /** 45 * Tests {@link ArraysSubstitutions}. 46 */ 47 public class ArraysSubstitutionsTest extends MethodSubstitutionTest { 48 49 private static final int N = 10; 50 51 @Test 52 public void testEqualsBoolean() { 53 Object[] args1 = new Object[N]; 54 Object[] args2 = new Object[N]; 55 int n = 0; 56 57 // equal arrays 58 for (int i = 0; i < N / 2; i++, n++) { 59 args1[n] = new boolean[i]; 60 args2[n] = new boolean[i]; 61 } 62 63 // non-equal arrays 64 for (int i = 0; i < N / 2; i++, n++) { 65 boolean[] a2 = new boolean[i]; 66 if (i > 0) { 67 a2[i - 1] = true; 68 } 69 args1[n] = new boolean[i]; 70 args2[n] = a2; 71 } 72 Class<?>[] parameterTypes = new Class<?>[]{boolean[].class, boolean[].class}; 73 testSubstitution("arraysEqualsBoolean", ArrayEqualsNode.class, Arrays.class, "equals", parameterTypes, false, args1, args2); 74 } 75 76 @SuppressWarnings("all") 77 public static boolean arraysEqualsBoolean(boolean[] a, boolean[] b) { 78 return Arrays.equals(a, b); 79 } 80 81 @Test 82 public void testEqualsByte() { 83 Object[] args1 = new Object[N]; 84 Object[] args2 = new Object[N]; 85 int n = 0; 86 87 // equal arrays 88 for (int i = 0; i < N / 2; i++, n++) { 89 args1[n] = new byte[i]; 90 args2[n] = new byte[i]; 91 } 92 93 // non-equal arrays 94 for (int i = 0; i < N / 2; i++, n++) { 95 byte[] a2 = new byte[i]; 96 if (i > 0) { 97 a2[i - 1] = 1; 98 } 99 args1[n] = new byte[i]; 100 args2[n] = a2; 101 } 102 103 Class<?>[] parameterTypes = new Class<?>[]{byte[].class, byte[].class}; 104 testSubstitution("arraysEqualsByte", ArrayEqualsNode.class, Arrays.class, "equals", parameterTypes, false, args1, args2); 105 } 106 107 @SuppressWarnings("all") 108 public static boolean arraysEqualsByte(byte[] a, byte[] b) { 109 return Arrays.equals(a, b); 110 } 111 112 @Test 113 public void testEqualsChar() { 114 Object[] args1 = new Object[N]; 115 Object[] args2 = new Object[N]; 116 int n = 0; 117 118 // equal arrays 119 for (int i = 0; i < N / 2; i++, n++) { 120 args1[n] = new char[i]; 121 args2[n] = new char[i]; 122 } 123 124 // non-equal arrays 125 for (int i = 0; i < N / 2; i++, n++) { 126 char[] a2 = new char[i]; 127 if (i > 0) { 128 a2[i - 1] = 1; 129 } 130 args1[n] = new char[i]; 131 args2[n] = a2; 132 } 133 134 Class<?>[] parameterTypes = new Class<?>[]{char[].class, char[].class}; 135 testSubstitution("arraysEqualsChar", ArrayEqualsNode.class, Arrays.class, "equals", parameterTypes, false, args1, args2); 136 } 137 138 @SuppressWarnings("all") 139 public static boolean arraysEqualsChar(char[] a, char[] b) { 140 return Arrays.equals(a, b); 141 } 142 143 @Test 144 public void testEqualsShort() { 145 Object[] args1 = new Object[N]; 146 Object[] args2 = new Object[N]; 147 int n = 0; 148 149 // equal arrays 150 for (int i = 0; i < N / 2; i++, n++) { 151 args1[n] = new short[i]; 152 args2[n] = new short[i]; 153 } 154 155 // non-equal arrays 156 for (int i = 0; i < N / 2; i++, n++) { 157 short[] a2 = new short[i]; 158 if (i > 0) { 159 a2[i - 1] = 1; 160 } 161 args1[n] = new short[i]; 162 args2[n] = a2; 163 } 164 165 Class<?>[] parameterTypes = new Class<?>[]{short[].class, short[].class}; 166 testSubstitution("arraysEqualsShort", ArrayEqualsNode.class, Arrays.class, "equals", parameterTypes, false, args1, args2); 167 } 168 169 @SuppressWarnings("all") 170 public static boolean arraysEqualsShort(short[] a, short[] b) { 171 return Arrays.equals(a, b); 172 } 173 174 @Test 175 public void testEqualsInt() { 176 Object[] args1 = new Object[N]; 177 Object[] args2 = new Object[N]; 178 int n = 0; 179 180 // equal arrays 181 for (int i = 0; i < N / 2; i++, n++) { 182 args1[n] = new int[i]; 183 args2[n] = new int[i]; 184 } 185 186 // non-equal arrays 187 for (int i = 0; i < N / 2; i++, n++) { 188 int[] a2 = new int[i]; 189 if (i > 0) { 190 a2[i - 1] = 1; 191 } 192 args1[n] = new int[i]; 193 args2[n] = a2; 194 } 195 196 Class<?>[] parameterTypes = new Class<?>[]{int[].class, int[].class}; 197 testSubstitution("arraysEqualsInt", ArrayEqualsNode.class, Arrays.class, "equals", parameterTypes, false, args1, args2); 198 } 199 200 @SuppressWarnings("all") 201 public static boolean arraysEqualsInt(int[] a, int[] b) { 202 return Arrays.equals(a, b); 203 } 204 205 @Test 206 public void testEqualsLong() { 207 Object[] args1 = new Object[N]; 208 Object[] args2 = new Object[N]; 209 int n = 0; 210 211 // equal arrays 212 for (int i = 0; i < N / 2; i++, n++) { 213 args1[n] = new long[i]; 214 args2[n] = new long[i]; 215 } 216 217 // non-equal arrays 218 for (int i = 0; i < N / 2; i++, n++) { 219 long[] a2 = new long[i]; 220 if (i > 0) { 221 a2[i - 1] = 1; 222 } 223 args1[n] = new long[i]; 224 args2[n] = a2; 225 } 226 227 Class<?>[] parameterTypes = new Class<?>[]{long[].class, long[].class}; 228 testSubstitution("arraysEqualsLong", ArrayEqualsNode.class, Arrays.class, "equals", parameterTypes, false, args1, args2); 229 } 230 231 @SuppressWarnings("all") 232 public static boolean arraysEqualsLong(long[] a, long[] b) { 233 return Arrays.equals(a, b); 234 } 235 236 @Test 237 public void testEqualsNodeGVN() { 238 test("testEqualsNodeGVNSnippet", true); 239 } 240 241 public static int[] intArrayCompare = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9}; 242 public static int[] intArray; 243 244 public static boolean testEqualsNodeGVNSnippet(boolean b) { 245 int[] newIntArray = new int[]{0, 2, 3, 4, 5, 6, 7, 8, 9}; 246 intArray = newIntArray; 247 248 if (b) { 249 newIntArray[0] = 1; 250 return Arrays.equals(newIntArray, intArrayCompare); 251 } else { 252 newIntArray[0] = 1; 253 return Arrays.equals(newIntArray, intArrayCompare); 254 } 255 } 256 257 @Test 258 public void testConstants() { 259 testGraph("testConstantsSnippet"); 260 } 261 262 public static final int[] constantArray1 = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9}; 263 public static final int[] constantArray2 = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9}; 264 265 public static boolean testConstantsSnippet() { 266 constantArray2[0] = 10; 267 try { 268 return Arrays.equals(constantArray1, constantArray2); 269 } finally { 270 constantArray2[0] = 1; 271 } 272 } 273 274 @Test 275 public void testCanonicalLength() { 276 StructuredGraph graph = parseEager("testCanonicalLengthSnippet", AllowAssumptions.NO); 277 HighTierContext context = new HighTierContext(getProviders(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); 278 new InliningPhase(new CanonicalizerPhase()).apply(graph, context); 279 new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); 280 281 Assert.assertTrue(graph.getNodes(ReturnNode.TYPE).first().result().asJavaConstant().asLong() == 0); 282 } 283 284 public static final int[] constantArray3 = new int[]{1, 2, 3}; 285 286 public static boolean testCanonicalLengthSnippet() { 287 return Arrays.equals(constantArray1, constantArray3); 288 } 289 290 @Test 291 public void testCanonicalEqual() { 292 StructuredGraph graph = parseEager("testCanonicalEqualSnippet", AllowAssumptions.NO); 293 HighTierContext context = new HighTierContext(getProviders(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); 294 new InliningPhase(new CanonicalizerPhase()).apply(graph, context); 295 new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); 296 297 Assert.assertTrue(graph.getNodes(ReturnNode.TYPE).first().result().asJavaConstant().asLong() == 1); 298 } 299 300 public static boolean testCanonicalEqualSnippet() { 301 return Arrays.equals(constantArray1, constantArray1); 302 } 303 304 @Test 305 public void testVirtualEqual() { 306 StructuredGraph graph = parseEager("testVirtualEqualSnippet", AllowAssumptions.NO); 307 HighTierContext context = new HighTierContext(getProviders(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); 308 new InliningPhase(new CanonicalizerPhase()).apply(graph, context); 309 new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); 310 new PartialEscapePhase(false, new CanonicalizerPhase(), graph.getOptions()).apply(graph, context); 311 new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); 312 313 Assert.assertTrue(graph.getNodes(ReturnNode.TYPE).first().result().asJavaConstant().asLong() == 1); 314 } 315 316 public static boolean testVirtualEqualSnippet() { 317 int[] array1 = new int[]{1, 2, 3, 4}; 318 int[] array2 = new int[]{1, 2, 3, 4}; 319 return Arrays.equals(array1, array2); 320 } 321 322 @Test 323 public void testVirtualNotEqual() { 324 StructuredGraph graph = parseEager("testVirtualNotEqualSnippet", AllowAssumptions.NO); 325 HighTierContext context = getDefaultHighTierContext(); 326 new InliningPhase(new CanonicalizerPhase()).apply(graph, context); 327 new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); 328 new PartialEscapePhase(false, new CanonicalizerPhase(), graph.getOptions()).apply(graph, context); 329 new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); 330 331 Assert.assertTrue(graph.getNodes(ReturnNode.TYPE).first().result().asJavaConstant().asLong() == 0); 332 } 333 334 public static boolean testVirtualNotEqualSnippet(int x) { 335 int[] array1 = new int[]{1, 2, 100, x}; 336 int[] array2 = new int[]{1, 2, 3, 4}; 337 return Arrays.equals(array1, array2); 338 } 339 }