1 /* 2 * Copyright (c) 2017, 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 package compiler.valhalla.valuetypes; 25 26 import java.lang.reflect.Array; 27 import java.lang.reflect.Field; 28 import java.util.Arrays; 29 import jdk.test.lib.Asserts; 30 import jdk.internal.misc.Unsafe; 31 32 /* 33 * @test 34 * @summary Test intrinsic support for value types 35 * @library /testlibrary /test/lib /compiler/whitebox / 36 * @modules java.base/jdk.internal.misc 37 * @requires os.simpleArch == "x64" 38 * @compile -XDemitQtypes -XDenableValueTypes -XDallowWithFieldOperator -XDallowFlattenabilityModifiers TestIntrinsics.java 39 * @run driver ClassFileInstaller sun.hotspot.WhiteBox jdk.test.lib.Platform 40 * @run main/othervm/timeout=120 -Xbootclasspath/a:. -ea -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions 41 * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI -XX:+EnableValhalla 42 * compiler.valhalla.valuetypes.ValueTypeTest 43 * compiler.valhalla.valuetypes.TestIntrinsics 44 */ 45 public class TestIntrinsics extends ValueTypeTest { 46 // Extra VM parameters for some test scenarios. See ValueTypeTest.getVMParameters() 47 @Override 48 public String[] getExtraVMParameters(int scenario) { 49 switch (scenario) { 50 case 3: return new String[] {"-XX:-MonomorphicArrayCheck", "-XX:+ValueArrayFlatten"}; 51 case 4: return new String[] {"-XX:-MonomorphicArrayCheck"}; 52 } 53 return null; 54 } 55 56 public static void main(String[] args) throws Throwable { 57 TestIntrinsics test = new TestIntrinsics(); 58 test.run(args, MyValue1.class, MyValue2.class, MyValue2Inline.class); 59 } 60 61 // Test correctness of the Class::isAssignableFrom intrinsic 62 @Test() 63 public boolean test1(Class<?> supercls, Class<?> subcls) { 64 return supercls.isAssignableFrom(subcls); 65 } 66 67 public void test1_verifier(boolean warmup) { 68 Asserts.assertTrue(test1(Object.class, MyValue1.class), "test1_1 failed"); 69 Asserts.assertTrue(test1(MyValue1.class, MyValue1.class), "test1_2 failed"); 70 Asserts.assertTrue(test1(Object.class, java.util.ArrayList.class), "test1_3 failed"); 71 Asserts.assertTrue(test1(java.util.ArrayList.class, java.util.ArrayList.class), "test1_4 failed"); 72 } 73 74 // Verify that Class::isAssignableFrom checks with statically known classes are folded 75 @Test(failOn = LOADK) 76 public boolean test2() { 77 boolean check1 = java.util.AbstractList.class.isAssignableFrom(java.util.ArrayList.class); 78 boolean check2 = MyValue1.class.isAssignableFrom(MyValue1.class); 79 boolean check3 = Object.class.isAssignableFrom(java.util.ArrayList.class); 80 boolean check4 = Object.class.isAssignableFrom(MyValue1.class); 81 boolean check5 = !MyValue1.class.isAssignableFrom(Object.class); 82 return check1 && check2 && check3 && check4 && check5; 83 } 84 85 public void test2_verifier(boolean warmup) { 86 Asserts.assertTrue(test2(), "test2 failed"); 87 } 88 89 // Test correctness of the Class::getSuperclass intrinsic 90 @Test() 91 public Class<?> test3(Class<?> cls) { 92 return cls.getSuperclass(); 93 } 94 95 public void test3_verifier(boolean warmup) { 96 Asserts.assertTrue(test3(Object.class) == null, "test3_1 failed"); 97 Asserts.assertTrue(test3(MyValue1.class) == Object.class, "test3_2 failed"); 98 Asserts.assertTrue(test3(Class.class) == Object.class, "test3_3 failed"); 99 } 100 101 // Verify that Class::getSuperclass checks with statically known classes are folded 102 @Test(failOn = LOADK) 103 public boolean test4() { 104 boolean check1 = Object.class.getSuperclass() == null; 105 boolean check2 = MyValue1.class.getSuperclass() == Object.class; 106 boolean check3 = Class.class.getSuperclass() == Object.class; 107 return check1 && check2 && check3; 108 } 109 110 public void test4_verifier(boolean warmup) { 111 Asserts.assertTrue(test4(), "test4 failed"); 112 } 113 114 // Disabled until 8206274 is fixed 115 /* 116 // Test toString() method 117 @Test(failOn = ALLOC + STORE + LOAD) 118 public String test5(MyValue1 v) { 119 return v.toString(); 120 } 121 122 @DontCompile 123 public void test5_verifier(boolean warmup) { 124 MyValue1 v = MyValue1.createDefaultInline(); 125 test5(v); 126 } 127 */ 128 129 // Test hashCode() method 130 @Test() 131 public int test6(MyValue1 v) { 132 return v.hashCode(); 133 } 134 135 @DontCompile 136 public void test6_verifier(boolean warmup) { 137 MyValue1 v = MyValue1.createWithFieldsInline(rI, rL); 138 int res = test6(v); 139 Asserts.assertEQ(res, v.hashCode()); 140 } 141 142 // Test default value type array creation via reflection 143 @Test() 144 public Object[] test7(Class<?> componentType, int len) { 145 Object[] va = (Object[])Array.newInstance(componentType, len); 146 return va; 147 } 148 149 @DontCompile 150 public void test7_verifier(boolean warmup) { 151 int len = Math.abs(rI) % 42; 152 long hash = MyValue1.createDefaultDontInline().hashPrimitive(); 153 Object[] va = test7(MyValue1.class, len); 154 for (int i = 0; i < len; ++i) { 155 Asserts.assertEQ(((MyValue1)va[i]).hashPrimitive(), hash); 156 } 157 } 158 159 // Class.isInstance 160 @Test() 161 public boolean test8(Class c, MyValue1 vt) { 162 return c.isInstance(vt); 163 } 164 165 @DontCompile 166 public void test8_verifier(boolean warmup) { 167 MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL); 168 boolean result = test8(MyValue1.class, vt); 169 Asserts.assertTrue(result); 170 } 171 172 @Test() 173 public boolean test9(Class c, MyValue1 vt) { 174 return c.isInstance(vt); 175 } 176 177 @DontCompile 178 public void test9_verifier(boolean warmup) { 179 MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL); 180 boolean result = test9(MyValue2.class, vt); 181 Asserts.assertFalse(result); 182 } 183 184 // Class.cast 185 @Test() 186 public Object test10(Class c, MyValue1 vt) { 187 return c.cast(vt); 188 } 189 190 @DontCompile 191 public void test10_verifier(boolean warmup) { 192 MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL); 193 Object result = test10(MyValue1.class, vt); 194 Asserts.assertEQ(((MyValue1)result).hash(), vt.hash()); 195 } 196 197 @Test() 198 public Object test11(Class c, MyValue1 vt) { 199 return c.cast(vt); 200 } 201 202 @DontCompile 203 public void test11_verifier(boolean warmup) { 204 MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL); 205 try { 206 test11(MyValue2.class, vt); 207 throw new RuntimeException("should have thrown"); 208 } catch(ClassCastException cce) { 209 } 210 } 211 212 @Test() 213 public Object test12(MyValue1 vt) { 214 return MyValue1.class.cast(vt); 215 } 216 217 @DontCompile 218 public void test12_verifier(boolean warmup) { 219 MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL); 220 Object result = test12(vt); 221 Asserts.assertEQ(((MyValue1)result).hash(), vt.hash()); 222 } 223 224 @Test() 225 public Object test13(MyValue1 vt) { 226 return MyValue2.class.cast(vt); 227 } 228 229 @DontCompile 230 public void test13_verifier(boolean warmup) { 231 MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL); 232 try { 233 test13(vt); 234 throw new RuntimeException("should have thrown"); 235 } catch(ClassCastException cce) { 236 } 237 } 238 239 // value type array creation via reflection 240 @Test() 241 public void test14(int len, long hash) { 242 Object[] va = (Object[])Array.newInstance(MyValue1.class, len); 243 for (int i = 0; i < len; ++i) { 244 Asserts.assertEQ(((MyValue1)va[i]).hashPrimitive(), hash); 245 } 246 } 247 248 @DontCompile 249 public void test14_verifier(boolean warmup) { 250 int len = Math.abs(rI) % 42; 251 long hash = MyValue1.createDefaultDontInline().hashPrimitive(); 252 test14(len, hash); 253 } 254 255 // Test hashCode() method 256 @Test() 257 public int test15(Object v) { 258 return v.hashCode(); 259 } 260 261 @DontCompile 262 public void test15_verifier(boolean warmup) { 263 MyValue1 v = MyValue1.createWithFieldsInline(rI, rL); 264 int res = test15(v); 265 Asserts.assertEQ(res, v.hashCode()); 266 } 267 268 @Test() 269 public int test16(Object v) { 270 return System.identityHashCode(v); 271 } 272 273 @DontCompile 274 public void test16_verifier(boolean warmup) { 275 MyValue1 v = MyValue1.createWithFieldsInline(rI, rL); 276 int res = test16(v); 277 Asserts.assertEQ(res, System.identityHashCode((Object)v)); 278 } 279 280 @Test() 281 public int test17(Object v) { 282 return System.identityHashCode(v); 283 } 284 285 @DontCompile 286 public void test17_verifier(boolean warmup) { 287 Integer v = new Integer(rI); 288 int res = test17(v); 289 Asserts.assertEQ(res, System.identityHashCode(v)); 290 } 291 292 @Test() 293 public int test18(Object v) { 294 return System.identityHashCode(v); 295 } 296 297 @DontCompile 298 public void test18_verifier(boolean warmup) { 299 Object v = null; 300 int res = test18(v); 301 Asserts.assertEQ(res, System.identityHashCode(v)); 302 } 303 304 // hashCode() and toString() with different value types 305 @Test() 306 public int test19(MyValue1 vt1, MyValue1 vt2, boolean b) { 307 MyValue1 res = b ? vt1 : vt2; 308 return res.hashCode(); 309 } 310 311 @DontCompile 312 public void test19_verifier(boolean warmup) { 313 MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL); 314 int res = test19(vt, vt, true); 315 Asserts.assertEQ(res, vt.hashCode()); 316 res = test19(vt, vt, false); 317 Asserts.assertEQ(res, vt.hashCode()); 318 } 319 320 @Test() 321 public String test20(MyValue1 vt1, MyValue1 vt2, boolean b) { 322 MyValue1 res = b ? vt1 : vt2; 323 return res.toString(); 324 } 325 326 @DontCompile 327 public void test20_verifier(boolean warmup) { 328 MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL); 329 String res = test20(vt, vt, true); 330 Asserts.assertEQ(res, vt.toString()); 331 res = test20(vt, vt, false); 332 Asserts.assertEQ(res, vt.toString()); 333 } 334 335 private static final Unsafe U = Unsafe.getUnsafe(); 336 private static final long X_OFFSET; 337 static { 338 try { 339 Field xField = MyValue1.class.getDeclaredField("x"); 340 X_OFFSET = U.objectFieldOffset(xField); 341 } catch (Exception e) { 342 throw new RuntimeException(e); 343 } 344 } 345 346 @Test() 347 public int test21(MyValue1 v) { 348 return U.getInt(v, X_OFFSET); 349 } 350 351 @DontCompile 352 public void test21_verifier(boolean warmup) { 353 MyValue1 v = MyValue1.createWithFieldsInline(rI, rL); 354 int res = test21(v); 355 Asserts.assertEQ(res, v.x); 356 } 357 358 @Test() 359 public void test22(MyValue1 v) { 360 U.putInt(v, X_OFFSET, 0); 361 } 362 363 @DontCompile 364 public void test22_verifier(boolean warmup) { 365 MyValue1 v = MyValue1.createWithFieldsInline(rI, rL); 366 test22(v); 367 } 368 369 @Test() 370 public int test23(MyValue1 v, long offset) { 371 return U.getInt(v, offset); 372 } 373 374 @DontCompile 375 public void test23_verifier(boolean warmup) { 376 MyValue1 v = MyValue1.createWithFieldsInline(rI, rL); 377 int res = test23(v, X_OFFSET); 378 Asserts.assertEQ(res, v.x); 379 } 380 381 MyValue1.val test24_vt = MyValue1.createWithFieldsInline(rI, rL); 382 383 @Test() 384 public int test24(long offset) { 385 return U.getInt(test24_vt, offset); 386 } 387 388 @DontCompile 389 public void test24_verifier(boolean warmup) { 390 int res = test24(X_OFFSET); 391 Asserts.assertEQ(res, test24_vt.x); 392 } 393 394 // Test copyOf intrinsic with allocated value type in it's debug information 395 // TODO Re-enable if value type arrays become covariant with object arrays 396 /* 397 value final class Test25Value { 398 final int x; 399 public Test25Value() { 400 this.x = 42; 401 } 402 } 403 404 final Test25Value[] test25Array = new Test25Value[10]; 405 406 @Test 407 public Test25Value[] test25(Test25Value element) { 408 Test25Value[] newArray = Arrays.copyOf(test25Array, test25Array.length + 1); 409 newArray[test25Array.length] = element; 410 return newArray; 411 } 412 413 @DontCompile 414 public void test25_verifier(boolean warmup) { 415 Test25Value vt = new Test25Value(); 416 test25(vt); 417 } 418 */ 419 420 @Test 421 public Object test26() { 422 Class<?>[] ca = new Class<?>[1]; 423 for (int i = 0; i < 1; ++i) { 424 // Folds during loop opts 425 ca[i] = MyValue1.class; 426 } 427 return Array.newInstance(ca[0], 1); 428 } 429 430 @DontCompile 431 public void test26_verifier(boolean warmup) { 432 Object[] res = (Object[])test26(); 433 Asserts.assertEQ(((MyValue1)res[0]).hashPrimitive(), MyValue1.createDefaultInline().hashPrimitive()); 434 } 435 436 // Load non-flattenable value type field with unsafe 437 MyValue1.box test27_vt = MyValue1.createWithFieldsInline(rI, rL); 438 private static final long TEST27_OFFSET; 439 static { 440 try { 441 Field field = TestIntrinsics.class.getDeclaredField("test27_vt"); 442 TEST27_OFFSET = U.objectFieldOffset(field); 443 } catch (Exception e) { 444 throw new RuntimeException(e); 445 } 446 } 447 448 @Test() 449 public MyValue1 test27() { 450 return (MyValue1)U.getObject(this, TEST27_OFFSET); 451 } 452 453 @DontCompile 454 public void test27_verifier(boolean warmup) { 455 MyValue1 res = test27(); 456 Asserts.assertEQ(res.hash(), test24_vt.hash()); 457 } 458 }