/* * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package org.graalvm.compiler.replacements.test; import java.util.HashMap; import org.junit.Assert; import org.junit.Test; import org.graalvm.compiler.core.test.GraalCompilerTest; /** * Tests the implementation of {@code NEW}. */ public class NewInstanceTest extends GraalCompilerTest { @Override protected void assertDeepEquals(Object expected, Object actual) { Assert.assertTrue(expected != null); Assert.assertTrue(actual != null); super.assertDeepEquals(expected.getClass(), actual.getClass()); if (expected instanceof Object[]) { Assert.assertTrue(actual instanceof Object[]); Object[] eArr = (Object[]) expected; Object[] aArr = (Object[]) actual; Assert.assertTrue(eArr.length == aArr.length); for (int i = 0; i < eArr.length; i++) { assertDeepEquals(eArr[i], aArr[i]); } } else if (expected.getClass() != Object.class) { try { expected.getClass().getDeclaredMethod("equals", Object.class); super.assertDeepEquals(expected, actual); } catch (Exception e) { } } } @Test public void test1() { test("newObject"); } @Test public void test2() { test("newObjectTwice"); } public static Object newObject() { return new Object(); } @Test public void test3() { test("newObjectLoop", 100); } @Test public void test4() { test("newBigObject"); } @Test public void test5() { test("newSomeObject"); } @Test public void test6() { test("newEmptyString"); } @Test public void test7() { test("newString", "value"); } @Test public void test8() { test("newHashMap", 31); } @Test public void test9() { test("newRegression", true); } public static Object[] newObjectTwice() { Object[] res = {new Object(), new Object()}; return res; } public static Object[] newObjectLoop(int n) { Object[] res = new Object[n]; for (int i = 0; i < n; i++) { res[i] = new Object(); } return res; } public static BigObject newBigObject() { return new BigObject(); } public static SomeObject newSomeObject() { return new SomeObject(); } public static String newEmptyString() { return new String(); } public static String newString(String value) { return new String(value); } public static HashMap<?, ?> newHashMap(int initialCapacity) { return new HashMap<>(initialCapacity); } static class SomeObject { String name = "o1"; HashMap<String, Object> map = new HashMap<>(); SomeObject() { map.put(name, this.getClass()); } @Override public boolean equals(Object obj) { if (obj instanceof SomeObject) { SomeObject so = (SomeObject) obj; return so.name.equals(name) && so.map.equals(map); } return false; } @Override public int hashCode() { return name.hashCode(); } } static class BigObject { Object f01; Object f02; Object f03; Object f04; Object f05; Object f06; Object f07; Object f08; Object f09; Object f10; Object f12; Object f13; Object f14; Object f15; Object f16; Object f17; Object f18; Object f19; Object f20; Object f21; Object f22; Object f23; Object f24; Object f25; Object f26; Object f27; Object f28; Object f29; Object f30; Object f31; Object f32; Object f33; Object f34; Object f35; Object f36; Object f37; Object f38; Object f39; Object f40; Object f41; Object f42; Object f43; Object f44; Object f45; } /** * Tests that an earlier bug does not occur. The issue was that the loading of the TLAB 'top' * and 'end' values was being GVN'ed from each branch of the 'if' statement. This meant that the * allocated B object in the true branch overwrote the allocated array. The cause is that * RegisterNode was a floating node and the reads from it were UnsafeLoads which are also * floating. The fix was to make RegisterNode a fixed node (which it should have been in the * first place). */ public static Object newRegression(boolean condition) { Object result; if (condition) { Object[] arr = {0, 1, 2, 3, 4, 5}; result = new B(); for (int i = 0; i < arr.length; ++i) { // If the bug exists, the values of arr will now be deadbeef values // and the virtual dispatch will cause a segfault. This can result in // either a VM crash or a spurious NullPointerException. if (arr[i].equals(Integer.valueOf(i))) { return false; } } } else { result = new B(); } return result; } static class B { long f1 = 0xdeadbeefdeadbe01L; long f2 = 0xdeadbeefdeadbe02L; long f3 = 0xdeadbeefdeadbe03L; long f4 = 0xdeadbeefdeadbe04L; long f5 = 0xdeadbeefdeadbe05L; } }