1 /*
   2  * Copyright (c) 2019, 2020, 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.invoke.*;
  27 import java.lang.reflect.Method;
  28 
  29 import jdk.test.lib.Asserts;
  30 
  31 /*
  32  * @test
  33  * @summary Test correct handling of nullable value types.
  34  * @library /testlibrary /test/lib /compiler/whitebox /
  35  * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
  36  * @compile TestNullableValueTypes.java
  37  * @run driver ClassFileInstaller sun.hotspot.WhiteBox jdk.test.lib.Platform
  38  * @run main/othervm/timeout=300 -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
  39  *                               -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI
  40  *                               compiler.valhalla.valuetypes.ValueTypeTest
  41  *                               compiler.valhalla.valuetypes.TestNullableValueTypes
  42  */
  43 public class TestNullableValueTypes extends ValueTypeTest {
  44     // Extra VM parameters for some test scenarios. See ValueTypeTest.getVMParameters()
  45     @Override
  46     public String[] getExtraVMParameters(int scenario) {
  47         switch (scenario) {
  48         case 1: return new String[] {"-XX:-UseOptoBiasInlining"};
  49         case 2: return new String[] {"-XX:-UseBiasedLocking"};
  50         case 3: return new String[] {"-XX:-MonomorphicArrayCheck", "-XX:-UseBiasedLocking", "-XX:ValueArrayElemMaxFlatSize=-1"};
  51         case 4: return new String[] {"-XX:-MonomorphicArrayCheck"};
  52         }
  53         return null;
  54     }
  55 
  56     public static void main(String[] args) throws Throwable {
  57         TestNullableValueTypes test = new TestNullableValueTypes();
  58         test.run(args, MyValue1.class, MyValue2.class, MyValue2Inline.class, Test17Value.class, Test21Value.class);
  59     }
  60 
  61     static {
  62         try {
  63             Class<?> clazz = TestNullableValueTypes.class;
  64             MethodHandles.Lookup lookup = MethodHandles.lookup();
  65 
  66             MethodType test18_mt = MethodType.methodType(void.class, MyValue1.class.asNullableType());
  67             test18_mh1 = lookup.findStatic(clazz, "test18_target1", test18_mt);
  68             test18_mh2 = lookup.findStatic(clazz, "test18_target2", test18_mt);
  69 
  70             MethodType test19_mt = MethodType.methodType(void.class, MyValue1.class.asNullableType());
  71             test19_mh1 = lookup.findStatic(clazz, "test19_target1", test19_mt);
  72             test19_mh2 = lookup.findStatic(clazz, "test19_target2", test19_mt);
  73         } catch (NoSuchMethodException | IllegalAccessException e) {
  74             e.printStackTrace();
  75             throw new RuntimeException("Method handle lookup failed");
  76         }
  77     }
  78 
  79     private static final MyValue1 testValue1 = MyValue1.createWithFieldsInline(rI, rL);
  80     private static final MyValue1[] testValue1Array = new MyValue1[] {testValue1,
  81                                                                       testValue1,
  82                                                                       testValue1};
  83 
  84     MyValue1? nullField;
  85     MyValue1 valueField1 = testValue1;
  86 
  87     @Test
  88     public long test1(MyValue1? vt) {
  89         long result = 0;
  90         try {
  91             result = vt.hash();
  92             throw new RuntimeException("NullPointerException expected");
  93         } catch (NullPointerException e) {
  94             // Expected
  95         }
  96         return result;
  97     }
  98 
  99     @DontCompile
 100     public void test1_verifier(boolean warmup) throws Throwable {
 101         long result = test1(null);
 102         Asserts.assertEquals(result, 0L);
 103     }
 104 
 105     @Test
 106     public long test2(MyValue1? vt) {
 107         long result = 0;
 108         try {
 109             result = vt.hashInterpreted();
 110             throw new RuntimeException("NullPointerException expected");
 111         } catch (NullPointerException e) {
 112             // Expected
 113         }
 114         return result;
 115     }
 116 
 117     @DontCompile
 118     public void test2_verifier(boolean warmup) {
 119         long result = test2(nullField);
 120         Asserts.assertEquals(result, 0L);
 121     }
 122 
 123     @Test
 124     public long test3() {
 125         long result = 0;
 126         try {
 127             if ((Object)nullField != null) {
 128                 throw new RuntimeException("nullField should be null");
 129             }
 130             result = nullField.hash();
 131             throw new RuntimeException("NullPointerException expected");
 132         } catch (NullPointerException e) {
 133             // Expected
 134         }
 135         return result;
 136     }
 137 
 138     @DontCompile
 139     public void test3_verifier(boolean warmup) {
 140         long result = test3();
 141         Asserts.assertEquals(result, 0L);
 142     }
 143 
 144     @Test
 145     public void test4() {
 146         try {
 147             valueField1 = (MyValue1) nullField;
 148             throw new RuntimeException("NullPointerException expected");
 149         } catch (NullPointerException e) {
 150             // Expected
 151         }
 152     }
 153 
 154     @DontCompile
 155     public void test4_verifier(boolean warmup) {
 156         test4();
 157     }
 158 
 159     @Test
 160     public MyValue1? test5(MyValue1? vt) {
 161         try {
 162             Object o = vt;
 163             vt = (MyValue1)o;
 164             throw new RuntimeException("NullPointerException expected");
 165         } catch (NullPointerException e) {
 166             // Expected
 167         }
 168 
 169         // Should not throw
 170         vt = test5_dontinline(vt);
 171         vt = test5_inline(vt);
 172         return vt;
 173     }
 174 
 175     @DontCompile
 176     public void test5_verifier(boolean warmup) {
 177         MyValue1? vt = test5(nullField);
 178         Asserts.assertEquals((Object)vt, null);
 179     }
 180 
 181     @DontInline
 182     public MyValue1? test5_dontinline(MyValue1? vt) {
 183         return vt;
 184     }
 185 
 186     @ForceInline
 187     public MyValue1? test5_inline(MyValue1? vt) {
 188         return vt;
 189     }
 190 
 191     @Test
 192     public MyValue1 test6(Object obj) {
 193         MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
 194         try {
 195             vt = (MyValue1)obj;
 196             throw new RuntimeException("NullPointerException expected");
 197         } catch (NullPointerException e) {
 198             // Expected
 199         }
 200         return vt;
 201     }
 202 
 203     @DontCompile
 204     public void test6_verifier(boolean warmup) {
 205         MyValue1 vt = test6(null);
 206         Asserts.assertEquals(vt.hash(), testValue1.hash());
 207     }
 208 
 209     @ForceInline
 210     public MyValue1? getNullInline() {
 211         return null;
 212     }
 213 
 214     @DontInline
 215     public MyValue1? getNullDontInline() {
 216         return null;
 217     }
 218 
 219     @Test
 220     public void test7() throws Throwable {
 221         nullField = getNullInline();     // Should not throw
 222         nullField = getNullDontInline(); // Should not throw
 223         try {
 224             valueField1 = (MyValue1) getNullInline();
 225             throw new RuntimeException("NullPointerException expected");
 226         } catch (NullPointerException e) {
 227             // Expected
 228         }
 229         try {
 230             valueField1 = (MyValue1) getNullDontInline();
 231             throw new RuntimeException("NullPointerException expected");
 232         } catch (NullPointerException e) {
 233             // Expected
 234         }
 235     }
 236 
 237     @DontCompile
 238     public void test7_verifier(boolean warmup) throws Throwable {
 239         test7();
 240     }
 241 
 242     @Test
 243     public void test8() throws Throwable {
 244         try {
 245             valueField1 = (MyValue1) nullField;
 246             throw new RuntimeException("NullPointerException expected");
 247         } catch (NullPointerException e) {
 248             // Expected
 249         }
 250     }
 251 
 252     @DontCompile
 253     public void test8_verifier(boolean warmup) throws Throwable {
 254         test8();
 255     }
 256 
 257     // merge of 2 values, one being null
 258     @Test
 259     public void test9(boolean flag1) {
 260         MyValue1 v;
 261         if (flag1) {
 262             v = valueField1;
 263         } else {
 264             v = (MyValue1) nullField;
 265         }
 266         valueField1 = v;
 267     }
 268 
 269     @DontCompile
 270     public void test9_verifier(boolean warmup) {
 271         test9(true);
 272         try {
 273             test9(false);
 274             throw new RuntimeException("NullPointerException expected");
 275         } catch (NullPointerException e) {
 276             // Expected
 277         }
 278     }
 279 
 280     // null constant
 281     @Test
 282     public void test10(boolean flag) throws Throwable {
 283         MyValue1? val = flag ? valueField1 : null;
 284         valueField1 = (MyValue1) val;
 285     }
 286 
 287     @DontCompile
 288     public void test10_verifier(boolean warmup) throws Throwable {
 289         test10(true);
 290         try {
 291             test10(false);
 292             throw new RuntimeException("NullPointerException expected");
 293         } catch (NullPointerException e) {
 294             // Expected
 295         }
 296     }
 297 
 298     // null constant
 299     @Test
 300     public void test11(boolean flag) throws Throwable {
 301         MyValue1? val = flag ? null : valueField1;
 302         valueField1 = (MyValue1) val;
 303     }
 304 
 305     @DontCompile
 306     public void test11_verifier(boolean warmup) throws Throwable {
 307         test11(false);
 308         try {
 309             test11(true);
 310             throw new RuntimeException("NullPointerException expected");
 311         } catch (NullPointerException e) {
 312             // Expected
 313         }
 314     }
 315 
 316     // null return
 317     int test12_cnt;
 318 
 319     @DontInline
 320     public MyValue1? test12_helper() {
 321         test12_cnt++;
 322         return nullField;
 323     }
 324 
 325     @Test
 326     public void test12() {
 327         valueField1 = (MyValue1) test12_helper();
 328     }
 329 
 330     @DontCompile
 331     public void test12_verifier(boolean warmup) {
 332         try {
 333             test12_cnt = 0;
 334             test12();
 335             throw new RuntimeException("NullPointerException expected");
 336         } catch (NullPointerException e) {
 337             // Expected
 338         }
 339         if (test12_cnt != 1) {
 340             throw new RuntimeException("call executed twice");
 341         }
 342     }
 343 
 344     // null return at virtual call
 345     class A {
 346         public MyValue1? test13_helper() {
 347             return nullField;
 348         }
 349     }
 350 
 351     class B extends A {
 352         public MyValue1 test13_helper() {
 353             return (MyValue1) nullField;
 354         }
 355     }
 356 
 357     class C extends A {
 358         public MyValue1? test13_helper() {
 359             return nullField;
 360         }
 361     }
 362 
 363     class D extends C {
 364         public MyValue1 test13_helper() {
 365             return (MyValue1) nullField;
 366         }
 367     }
 368 
 369     @Test
 370     public void test13(A a) {
 371         valueField1 = (MyValue1) a.test13_helper();
 372     }
 373 
 374     @DontCompile
 375     public void test13_verifier(boolean warmup) {
 376         A a = new A();
 377         A b = new B();
 378         A c = new C();
 379         A d = new D();
 380         try {
 381             test13(a);
 382             throw new RuntimeException("NullPointerException expected");
 383         } catch (NullPointerException e) {
 384             // Expected
 385         }
 386         try {
 387             test13(b);
 388             throw new RuntimeException("NullPointerException expected");
 389         } catch (NullPointerException e) {
 390             // Expected
 391         }
 392         try {
 393             test13(c);
 394             throw new RuntimeException("NullPointerException expected");
 395         } catch (NullPointerException e) {
 396             // Expected
 397         }
 398         try {
 399             test13(d);
 400             throw new RuntimeException("NullPointerException expected");
 401         } catch (NullPointerException e) {
 402             // Expected
 403         }
 404     }
 405 
 406     // Test writing null to a (flattened) value type array
 407     @ForceInline
 408     public void test14_inline(Object[] oa, Object o, int index) {
 409         oa[index] = o;
 410     }
 411 
 412     @Test()
 413     public void test14(MyValue1[] va, int index) {
 414         test14_inline(va, nullField, index);
 415     }
 416 
 417     @DontCompile
 418     public void test14_verifier(boolean warmup) {
 419         int index = Math.abs(rI) % 3;
 420         try {
 421             test14(testValue1Array, index);
 422             throw new RuntimeException("No NPE thrown");
 423         } catch (NullPointerException e) {
 424             // Expected
 425         }
 426         Asserts.assertEQ(testValue1Array[index].hash(), testValue1.hash());
 427     }
 428 
 429     @DontInline
 430     MyValue1? getNullField1() {
 431         return nullField;
 432     }
 433 
 434     @DontInline
 435     MyValue1 getNullField2() {
 436         return (MyValue1) nullField;
 437     }
 438 
 439     @Test()
 440     public void test15() {
 441         nullField = getNullField1(); // should not throw
 442         try {
 443             valueField1 = (MyValue1) getNullField1();
 444             throw new RuntimeException("NullPointerException expected");
 445         } catch (NullPointerException e) {
 446             // Expected
 447         }
 448         try {
 449             valueField1 = getNullField2();
 450             throw new RuntimeException("NullPointerException expected");
 451         } catch (NullPointerException e) {
 452             // Expected
 453         }
 454     }
 455 
 456     @DontCompile
 457     public void test15_verifier(boolean warmup) {
 458         test15();
 459     }
 460 
 461     @DontInline
 462     public boolean test16_dontinline(MyValue1? vt) {
 463         return (Object)vt == null;
 464     }
 465 
 466     // Test c2c call passing null for a value type
 467     @Test
 468     @Warmup(10000) // Warmup to make sure 'test17_dontinline' is compiled
 469     public boolean test16(Object arg) throws Exception {
 470         Method test16method = getClass().getMethod("test16_dontinline", MyValue1.class.asNullableType());
 471         return (boolean)test16method.invoke(this, arg);
 472     }
 473 
 474     @DontCompile
 475     public void test16_verifier(boolean warmup) throws Exception {
 476         boolean res = test16(null);
 477         Asserts.assertTrue(res);
 478     }
 479 
 480     // Test scalarization of default value type with non-flattenable field
 481     final inline class Test17Value {
 482         public final MyValue1? valueField;
 483 
 484         @ForceInline
 485         public Test17Value(MyValue1? valueField) {
 486             this.valueField = valueField;
 487         }
 488     }
 489 
 490     @Test()
 491     public Test17Value test17(boolean b) {
 492         Test17Value vt1 = Test17Value.default;
 493         if ((Object)vt1.valueField != null) {
 494             throw new RuntimeException("Should be null");
 495         }
 496         Test17Value vt2 = new Test17Value(testValue1);
 497         return b ? vt1 : vt2;
 498     }
 499 
 500     @DontCompile
 501     public void test17_verifier(boolean warmup) {
 502         test17(true);
 503         test17(false);
 504     }
 505 
 506     static final MethodHandle test18_mh1;
 507     static final MethodHandle test18_mh2;
 508 
 509     static MyValue1? nullValue;
 510 
 511     @DontInline
 512     static void test18_target1(MyValue1? vt) {
 513         nullValue = vt;
 514     }
 515 
 516     @ForceInline
 517     static void test18_target2(MyValue1? vt) {
 518         nullValue = vt;
 519     }
 520 
 521     // Test passing null for a value type
 522     @Test
 523     @Warmup(11000) // Make sure lambda forms get compiled
 524     public void test18() throws Throwable {
 525         test18_mh1.invokeExact(nullValue);
 526         test18_mh2.invokeExact(nullValue);
 527     }
 528 
 529     @DontCompile
 530     public void test18_verifier(boolean warmup) {
 531         try {
 532             test18();
 533         } catch (Throwable t) {
 534             throw new RuntimeException("test18 failed", t);
 535         }
 536     }
 537 
 538     static MethodHandle test19_mh1;
 539     static MethodHandle test19_mh2;
 540 
 541     @DontInline
 542     static void test19_target1(MyValue1? vt) {
 543         nullValue = vt;
 544     }
 545 
 546     @ForceInline
 547     static void test19_target2(MyValue1? vt) {
 548         nullValue = vt;
 549     }
 550 
 551     // Same as test12 but with non-final mh
 552     @Test
 553     @Warmup(11000) // Make sure lambda forms get compiled
 554     public void test19() throws Throwable {
 555         test19_mh1.invokeExact(nullValue);
 556         test19_mh2.invokeExact(nullValue);
 557     }
 558 
 559     @DontCompile
 560     public void test19_verifier(boolean warmup) {
 561         try {
 562             test19();
 563         } catch (Throwable t) {
 564             throw new RuntimeException("test19 failed", t);
 565         }
 566     }
 567 
 568     // Same as test12/13 but with constant null
 569     @Test
 570     @Warmup(11000) // Make sure lambda forms get compiled
 571     public void test20(MethodHandle mh) throws Throwable {
 572         mh.invoke(null);
 573     }
 574 
 575     @DontCompile
 576     public void test20_verifier(boolean warmup) {
 577         try {
 578             test20(test18_mh1);
 579             test20(test18_mh2);
 580             test20(test19_mh1);
 581             test20(test19_mh2);
 582         } catch (Throwable t) {
 583             throw new RuntimeException("test20 failed", t);
 584         }
 585     }
 586 
 587     // Test writing null to a flattenable/non-flattenable value type field in a value type
 588     final inline class Test21Value {
 589         final MyValue1? valueField1;
 590         final MyValue1 valueField2;
 591         final MyValue1? alwaysNull = null;
 592 
 593         @ForceInline
 594         public Test21Value(MyValue1? valueField1, MyValue1 valueField2) {
 595             this.valueField1 = testValue1;
 596             this.valueField2 = testValue1;
 597         }
 598 
 599         @ForceInline
 600         public Test21Value test1() {
 601             return new Test21Value(alwaysNull, this.valueField2); // Should not throw NPE
 602         }
 603 
 604         @ForceInline
 605         public Test21Value test2() {
 606             return new Test21Value(this.valueField1, (MyValue1) alwaysNull); // Should throw NPE
 607         }
 608     }
 609 
 610     @Test
 611     public Test21Value test21(Test21Value vt) {
 612         vt = vt.test1();
 613         try {
 614             vt = vt.test2();
 615             throw new RuntimeException("NullPointerException expected");
 616         } catch (NullPointerException e) {
 617             // Expected
 618         }
 619         return vt;
 620     }
 621 
 622     @DontCompile
 623     public void test21_verifier(boolean warmup) {
 624         test21(Test21Value.default);
 625     }
 626 
 627     @DontInline
 628     public MyValue1 test22_helper() {
 629         return (MyValue1) nullField;
 630     }
 631 
 632     @Test
 633     public void test22() {
 634         valueField1 = test22_helper();
 635     }
 636 
 637     @DontCompile
 638     public void test22_verifier(boolean warmup) {
 639         try {
 640             test22();
 641             throw new RuntimeException("NullPointerException expected");
 642         } catch (NullPointerException e) {
 643             // Expected
 644         }
 645     }
 646 
 647     @Test
 648     public void test23(MyValue1[] arr, MyValue1? b) {
 649         arr[0] = (MyValue1) b;
 650     }
 651 
 652     @DontCompile
 653     public void test23_verifier(boolean warmup) {
 654         MyValue1[] arr = new MyValue1[2];
 655         MyValue1? b = null;
 656         try {
 657             test23(arr, b);
 658             throw new RuntimeException("NullPointerException expected");
 659         } catch (NullPointerException e) {
 660             // Expected
 661         }
 662     }
 663 
 664     static MyValue1? nullBox;
 665 
 666     @Test
 667     public MyValue1 test24() {
 668         return (MyValue1) nullBox;
 669     }
 670 
 671     @DontCompile
 672     public void test24_verifier(boolean warmup) {
 673         try {
 674             test24();
 675             throw new RuntimeException("NullPointerException expected");
 676         } catch (NullPointerException e) {
 677             // Expected
 678         }
 679     }
 680 
 681     @DontInline
 682     public void test25_callee(MyValue1 val) { }
 683 
 684     // Test that when checkcasting from null-ok to null-free and back to null-ok we
 685     // keep track of the information that the value can never be null.
 686     @Test(failOn = ALLOC + STORE)
 687     public int test25(boolean b, MyValue1? vt1, MyValue1 vt2) {
 688         vt1 = (MyValue1)vt1;
 689         Object obj = b ? vt1 : vt2; // We should not allocate here
 690         test25_callee((MyValue1) vt1);
 691         return ((MyValue1)obj).x;
 692     }
 693 
 694     @DontCompile
 695     public void test25_verifier(boolean warmup) {
 696         int res = test25(true, testValue1, testValue1);
 697         Asserts.assertEquals(res, testValue1.x);
 698         res = test25(false, testValue1, testValue1);
 699         Asserts.assertEquals(res, testValue1.x);
 700     }
 701 
 702     // Test that chains of casts are folded and don't trigger an allocation
 703     @Test(failOn = ALLOC + STORE)
 704     public MyValue3 test26(MyValue3 vt) {
 705         return ((MyValue3)((Object)((MyValue3?)(MyValue3)((MyValue3?)((Object)vt)))));
 706     }
 707 
 708     @DontCompile
 709     public void test26_verifier(boolean warmup) {
 710         MyValue3 vt = MyValue3.create();
 711         MyValue3 result = test26(vt);
 712         Asserts.assertEquals(result, vt);
 713     }
 714 
 715     @Test(failOn = ALLOC + STORE)
 716     public MyValue3? test27(MyValue3? vt) {
 717         return ((MyValue3?)((Object)((MyValue3)(MyValue3?)((MyValue3)((Object)vt)))));
 718     }
 719 
 720     @DontCompile
 721     public void test27_verifier(boolean warmup) {
 722         MyValue3 vt = MyValue3.create();
 723         MyValue3 result = (MyValue3) test27(vt);
 724         Asserts.assertEquals(result, vt);
 725     }
 726 
 727     // Some more casting tests
 728     @Test()
 729     public MyValue1? test28(MyValue1 vt, MyValue1? vtBox, int i) {
 730         MyValue1? result = null;
 731         if (i == 0) {
 732             result = (MyValue1?)vt;
 733             result = null;
 734         } else if (i == 1) {
 735             result = (MyValue1?)vt;
 736         } else if (i == 2) {
 737             result = vtBox;
 738         }
 739         return result;
 740     }
 741 
 742     @DontCompile
 743     public void test28_verifier(boolean warmup) {
 744         MyValue1? result = test28(testValue1, null, 0);
 745         Asserts.assertEquals(result, null);
 746         result = test28(testValue1, testValue1, 1);
 747         Asserts.assertEquals(result, testValue1);
 748         result = test28(testValue1, null, 2);
 749         Asserts.assertEquals(result, null);
 750         result = test28(testValue1, testValue1, 2);
 751         Asserts.assertEquals(result, testValue1);
 752     }
 753 
 754     @Test()
 755     public long test29(MyValue1 vt, MyValue1? vtBox) {
 756         long result = 0;
 757         for (int i = 0; i < 100; ++i) {
 758             MyValue1? box;
 759             if (i == 0) {
 760                 box = (MyValue1?)vt;
 761                 box = null;
 762             } else if (i < 99) {
 763                 box = (MyValue1?)vt;
 764             } else {
 765                 box = vtBox;
 766             }
 767             if (box != null) {
 768                 result += box.hash();
 769             }
 770         }
 771         return result;
 772     }
 773 
 774     @DontCompile
 775     public void test29_verifier(boolean warmup) {
 776         long result = test29(testValue1, null);
 777         Asserts.assertEquals(result, testValue1.hash()*98);
 778         result = test29(testValue1, testValue1);
 779         Asserts.assertEquals(result, testValue1.hash()*99);
 780     }
 781 
 782     // Test null check of value type receiver with incremental inlining
 783     public long test30_callee(MyValue1? vt) {
 784         long result = 0;
 785         try {
 786             result = vt.hashInterpreted();
 787             throw new RuntimeException("NullPointerException expected");
 788         } catch (NullPointerException e) {
 789             // Expected
 790         }
 791         return result;
 792     }
 793 
 794     @Test
 795     public long test30() {
 796         return test30_callee(nullField);
 797     }
 798 
 799     @DontCompile
 800     public void test30_verifier(boolean warmup) {
 801         long result = test30();
 802         Asserts.assertEquals(result, 0L);
 803     }
 804 
 805     // Test casting null to unloaded value type
 806     final inline class Test31Value {
 807         private final int i = 0;
 808     }
 809 
 810     @Test
 811     public void test31(Object o) {
 812         try {
 813             o = (Test31Value)o;
 814             throw new RuntimeException("NullPointerException expected");
 815         } catch (NullPointerException e) {
 816             // Expected
 817         }
 818     }
 819 
 820     @DontCompile
 821     public void test31_verifier(boolean warmup) {
 822         test31(null);
 823     }
 824 
 825     private static final MyValue1? constNullField = null;
 826 
 827     @Test
 828     public MyValue1? test32() {
 829         return constNullField;
 830     }
 831 
 832     @DontCompile
 833     public void test32_verifier(boolean warmup) {
 834         MyValue1? result = test32();
 835         Asserts.assertEquals(result, null);
 836     }
 837 
 838     static inline class Test33Value1 {
 839         int x = 0;
 840     }
 841 
 842     static inline class Test33Value2 {
 843         Test33Value1? vt;
 844 
 845         public Test33Value2() {
 846             vt = new Test33Value1();
 847         }
 848     }
 849 
 850     public static final Test33Value2 test33Val = new Test33Value2();
 851 
 852     @Test
 853     public Test33Value2 test33() {
 854         return test33Val;
 855     }
 856 
 857     @DontCompile
 858     public void test33_verifier(boolean warmup) {
 859         Test33Value2 result = test33();
 860         Asserts.assertEquals(result, test33Val);
 861     }
 862 
 863     // Verify that static nullable inline-type fields are not
 864     // treated as never-null by C2 when initialized at compile time.
 865     private static MyValue1? test34Val;
 866 
 867     @Test
 868     public void test34(MyValue1 vt) {
 869         if (test34Val == null) {
 870             test34Val = vt;
 871         }
 872     }
 873 
 874     @DontCompile
 875     public void test34_verifier(boolean warmup) {
 876         test34(testValue1);
 877         if (!warmup) {
 878             test34Val = null;
 879             test34(testValue1);
 880             Asserts.assertEquals(test34Val, testValue1);
 881         }
 882     }
 883 
 884     // Same as test17 but with non-allocated value at withfield
 885     @Test()
 886     public Test17Value test35(boolean b) {
 887         Test17Value vt1 = Test17Value.default;
 888         if ((Object)vt1.valueField != null) {
 889             throw new RuntimeException("Should be null");
 890         }
 891         MyValue1 vt3 = MyValue1.createWithFieldsInline(rI, rL);
 892         Test17Value vt2 = new Test17Value(vt3);
 893         return b ? vt1 : vt2;
 894     }
 895 
 896     @DontCompile
 897     public void test35_verifier(boolean warmup) {
 898         test35(true);
 899         test35(false);
 900     }
 901 }