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