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