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 }