1 /*
   2  * Copyright (c) 2011, 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.HashMap;
  26 
  27 import org.junit.Assert;
  28 import org.junit.Test;
  29 
  30 import org.graalvm.compiler.core.test.GraalCompilerTest;
  31 
  32 /**
  33  * Tests the implementation of {@code NEW}.
  34  */
  35 public class NewInstanceTest extends GraalCompilerTest {
  36 
  37     @Override
  38     protected void assertDeepEquals(Object expected, Object actual) {
  39         Assert.assertTrue(expected != null);
  40         Assert.assertTrue(actual != null);
  41         super.assertDeepEquals(expected.getClass(), actual.getClass());
  42 
  43         if (expected instanceof Object[]) {
  44             Assert.assertTrue(actual instanceof Object[]);
  45             Object[] eArr = (Object[]) expected;
  46             Object[] aArr = (Object[]) actual;
  47             Assert.assertTrue(eArr.length == aArr.length);
  48             for (int i = 0; i < eArr.length; i++) {
  49                 assertDeepEquals(eArr[i], aArr[i]);
  50             }
  51         } else if (expected.getClass() != Object.class) {
  52             try {
  53                 expected.getClass().getDeclaredMethod("equals", Object.class);
  54                 super.assertDeepEquals(expected, actual);
  55             } catch (Exception e) {
  56             }
  57         }
  58     }
  59 
  60     @Test
  61     public void test1() {
  62         test("newObject");
  63     }
  64 
  65     @Test
  66     public void test2() {
  67         test("newObjectTwice");
  68     }
  69 
  70     public static Object newObject() {
  71         return new Object();
  72     }
  73 
  74     @Test
  75     public void test3() {
  76         test("newObjectLoop", 100);
  77     }
  78 
  79     @Test
  80     public void test4() {
  81         test("newBigObject");
  82     }
  83 
  84     @Test
  85     public void test5() {
  86         test("newSomeObject");
  87     }
  88 
  89     @Test
  90     public void test6() {
  91         test("newEmptyString");
  92     }
  93 
  94     @Test
  95     public void test7() {
  96         test("newString", "value");
  97     }
  98 
  99     @Test
 100     public void test8() {
 101         test("newHashMap", 31);
 102     }
 103 
 104     @Test
 105     public void test9() {
 106         test("newRegression", true);
 107     }
 108 
 109     public static Object[] newObjectTwice() {
 110         Object[] res = {new Object(), new Object()};
 111         return res;
 112     }
 113 
 114     public static Object[] newObjectLoop(int n) {
 115         Object[] res = new Object[n];
 116         for (int i = 0; i < n; i++) {
 117             res[i] = new Object();
 118         }
 119         return res;
 120     }
 121 
 122     public static BigObject newBigObject() {
 123         return new BigObject();
 124     }
 125 
 126     public static SomeObject newSomeObject() {
 127         return new SomeObject();
 128     }
 129 
 130     public static String newEmptyString() {
 131         return new String();
 132     }
 133 
 134     public static String newString(String value) {
 135         return new String(value);
 136     }
 137 
 138     public static HashMap<?, ?> newHashMap(int initialCapacity) {
 139         return new HashMap<>(initialCapacity);
 140     }
 141 
 142     static class SomeObject {
 143 
 144         String name = "o1";
 145         HashMap<String, Object> map = new HashMap<>();
 146 
 147         SomeObject() {
 148             map.put(name, this.getClass());
 149         }
 150 
 151         @Override
 152         public boolean equals(Object obj) {
 153             if (obj instanceof SomeObject) {
 154                 SomeObject so = (SomeObject) obj;
 155                 return so.name.equals(name) && so.map.equals(map);
 156             }
 157             return false;
 158         }
 159 
 160         @Override
 161         public int hashCode() {
 162             return name.hashCode();
 163         }
 164     }
 165 
 166     static class BigObject {
 167 
 168         Object f01;
 169         Object f02;
 170         Object f03;
 171         Object f04;
 172         Object f05;
 173         Object f06;
 174         Object f07;
 175         Object f08;
 176         Object f09;
 177         Object f10;
 178         Object f12;
 179         Object f13;
 180         Object f14;
 181         Object f15;
 182         Object f16;
 183         Object f17;
 184         Object f18;
 185         Object f19;
 186         Object f20;
 187         Object f21;
 188         Object f22;
 189         Object f23;
 190         Object f24;
 191         Object f25;
 192         Object f26;
 193         Object f27;
 194         Object f28;
 195         Object f29;
 196         Object f30;
 197         Object f31;
 198         Object f32;
 199         Object f33;
 200         Object f34;
 201         Object f35;
 202         Object f36;
 203         Object f37;
 204         Object f38;
 205         Object f39;
 206         Object f40;
 207         Object f41;
 208         Object f42;
 209         Object f43;
 210         Object f44;
 211         Object f45;
 212     }
 213 
 214     /**
 215      * Tests that an earlier bug does not occur. The issue was that the loading of the TLAB 'top'
 216      * and 'end' values was being GVN'ed from each branch of the 'if' statement. This meant that the
 217      * allocated B object in the true branch overwrote the allocated array. The cause is that
 218      * RegisterNode was a floating node and the reads from it were UnsafeLoads which are also
 219      * floating. The fix was to make RegisterNode a fixed node (which it should have been in the
 220      * first place).
 221      */
 222     public static Object newRegression(boolean condition) {
 223         Object result;
 224         if (condition) {
 225             Object[] arr = {0, 1, 2, 3, 4, 5};
 226             result = new B();
 227             for (int i = 0; i < arr.length; ++i) {
 228                 // If the bug exists, the values of arr will now be deadbeef values
 229                 // and the virtual dispatch will cause a segfault. This can result in
 230                 // either a VM crash or a spurious NullPointerException.
 231                 if (arr[i].equals(Integer.valueOf(i))) {
 232                     return false;
 233                 }
 234             }
 235         } else {
 236             result = new B();
 237         }
 238         return result;
 239     }
 240 
 241     static class B {
 242 
 243         long f1 = 0xdeadbeefdeadbe01L;
 244         long f2 = 0xdeadbeefdeadbe02L;
 245         long f3 = 0xdeadbeefdeadbe03L;
 246         long f4 = 0xdeadbeefdeadbe04L;
 247         long f5 = 0xdeadbeefdeadbe05L;
 248     }
 249 }