001/*
002 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.
008 *
009 * This code is distributed in the hope that it will be useful, but WITHOUT
010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
011 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
012 * version 2 for more details (a copy is included in the LICENSE file that
013 * accompanied this code).
014 *
015 * You should have received a copy of the GNU General Public License version
016 * 2 along with this work; if not, write to the Free Software Foundation,
017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
018 *
019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
020 * or visit www.oracle.com if you need additional information or have any
021 * questions.
022 */
023package com.oracle.graal.replacements.test;
024
025import java.util.*;
026
027import org.junit.*;
028
029import com.oracle.graal.compiler.test.*;
030
031/**
032 * Tests the implementation of {@code NEW}.
033 */
034public class NewInstanceTest extends GraalCompilerTest {
035
036    @Override
037    protected void assertDeepEquals(Object expected, Object actual) {
038        Assert.assertTrue(expected != null);
039        Assert.assertTrue(actual != null);
040        super.assertDeepEquals(expected.getClass(), actual.getClass());
041
042        if (expected instanceof Object[]) {
043            Assert.assertTrue(actual instanceof Object[]);
044            Object[] eArr = (Object[]) expected;
045            Object[] aArr = (Object[]) actual;
046            Assert.assertTrue(eArr.length == aArr.length);
047            for (int i = 0; i < eArr.length; i++) {
048                assertDeepEquals(eArr[i], aArr[i]);
049            }
050        } else if (expected.getClass() != Object.class) {
051            try {
052                expected.getClass().getDeclaredMethod("equals", Object.class);
053                super.assertDeepEquals(expected, actual);
054            } catch (Exception e) {
055            }
056        }
057    }
058
059    @Test
060    public void test1() {
061        test("newObject");
062    }
063
064    @Test
065    public void test2() {
066        test("newObjectTwice");
067    }
068
069    public static Object newObject() {
070        return new Object();
071    }
072
073    @Test
074    public void test3() {
075        test("newObjectLoop", 100);
076    }
077
078    @Test
079    public void test4() {
080        test("newBigObject");
081    }
082
083    @Test
084    public void test5() {
085        test("newSomeObject");
086    }
087
088    @Test
089    public void test6() {
090        test("newEmptyString");
091    }
092
093    @Test
094    public void test7() {
095        test("newString", "value");
096    }
097
098    @Test
099    public void test8() {
100        test("newHashMap", 31);
101    }
102
103    @Test
104    public void test9() {
105        test("newRegression", true);
106    }
107
108    public static Object[] newObjectTwice() {
109        Object[] res = {new Object(), new Object()};
110        return res;
111    }
112
113    public static Object[] newObjectLoop(int n) {
114        Object[] res = new Object[n];
115        for (int i = 0; i < n; i++) {
116            res[i] = new Object();
117        }
118        return res;
119    }
120
121    public static BigObject newBigObject() {
122        return new BigObject();
123    }
124
125    public static SomeObject newSomeObject() {
126        return new SomeObject();
127    }
128
129    public static String newEmptyString() {
130        return new String();
131    }
132
133    public static String newString(String value) {
134        return new String(value);
135    }
136
137    public static HashMap<?, ?> newHashMap(int initialCapacity) {
138        return new HashMap<>(initialCapacity);
139    }
140
141    static class SomeObject {
142
143        String name = "o1";
144        HashMap<String, Object> map = new HashMap<>();
145
146        public SomeObject() {
147            map.put(name, this.getClass());
148        }
149
150        @Override
151        public boolean equals(Object obj) {
152            if (obj instanceof SomeObject) {
153                SomeObject so = (SomeObject) obj;
154                return so.name.equals(name) && so.map.equals(map);
155            }
156            return false;
157        }
158
159        @Override
160        public int hashCode() {
161            return name.hashCode();
162        }
163    }
164
165    static class BigObject {
166
167        Object f01;
168        Object f02;
169        Object f03;
170        Object f04;
171        Object f05;
172        Object f06;
173        Object f07;
174        Object f08;
175        Object f09;
176        Object f10;
177        Object f12;
178        Object f13;
179        Object f14;
180        Object f15;
181        Object f16;
182        Object f17;
183        Object f18;
184        Object f19;
185        Object f20;
186        Object f21;
187        Object f22;
188        Object f23;
189        Object f24;
190        Object f25;
191        Object f26;
192        Object f27;
193        Object f28;
194        Object f29;
195        Object f30;
196        Object f31;
197        Object f32;
198        Object f33;
199        Object f34;
200        Object f35;
201        Object f36;
202        Object f37;
203        Object f38;
204        Object f39;
205        Object f40;
206        Object f41;
207        Object f42;
208        Object f43;
209        Object f44;
210        Object f45;
211    }
212
213    /**
214     * Tests that an earlier bug does not occur. The issue was that the loading of the TLAB 'top'
215     * and 'end' values was being GVN'ed from each branch of the 'if' statement. This meant that the
216     * allocated B object in the true branch overwrote the allocated array. The cause is that
217     * RegisterNode was a floating node and the reads from it were UnsafeLoads which are also
218     * floating. The fix was to make RegisterNode a fixed node (which it should have been in the
219     * first place).
220     */
221    public static Object newRegression(boolean condition) {
222        Object result;
223        if (condition) {
224            Object[] arr = {0, 1, 2, 3, 4, 5};
225            result = new B();
226            for (int i = 0; i < arr.length; ++i) {
227                // If the bug exists, the values of arr will now be deadbeef values
228                // and the virtual dispatch will cause a segfault. This can result in
229                // either a VM crash or a spurious NullPointerException.
230                if (arr[i].equals(Integer.valueOf(i))) {
231                    return false;
232                }
233            }
234        } else {
235            result = new B();
236        }
237        return result;
238    }
239
240    static class B {
241
242        long f1 = 0xdeadbeefdeadbe01L;
243        long f2 = 0xdeadbeefdeadbe02L;
244        long f3 = 0xdeadbeefdeadbe03L;
245        long f4 = 0xdeadbeefdeadbe04L;
246        long f5 = 0xdeadbeefdeadbe05L;
247    }
248}