/*
 * 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 NEW.
/** * 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).
/** * 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; } }