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