1 /*
   2  * Copyright (c) 2019, 2024, 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.inlinetypes;
  25 
  26 import compiler.lib.ir_framework.*;
  27 import jdk.test.lib.Asserts;
  28 
  29 import jdk.internal.value.ValueClass;
  30 import jdk.internal.vm.annotation.ImplicitlyConstructible;
  31 import jdk.internal.vm.annotation.LooselyConsistentValue;
  32 import jdk.internal.vm.annotation.NullRestricted;
  33 
  34 import static compiler.valhalla.inlinetypes.InlineTypes.rI;
  35 
  36 /*
  37  * @test
  38  * @key randomness
  39  * @summary Test the handling of fields of unloaded value classes.
  40  * @library /test/lib /
  41  * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
  42  * @enablePreview
  43  * @modules java.base/jdk.internal.value
  44  *          java.base/jdk.internal.vm.annotation
  45  * @compile hack/GetUnresolvedInlineFieldWrongSignature.java
  46  * @compile TestUnloadedInlineTypeField.java
  47  * @run main/othervm/timeout=300 compiler.valhalla.inlinetypes.TestUnloadedInlineTypeField
  48  */
  49 
  50 public class TestUnloadedInlineTypeField {
  51     // Only prevent loading of classes when testing with C1. Load classes
  52     // early when executing with C2 to prevent uncommon traps. It's still
  53     // beneficial to execute this test with C2 because it also checks handling
  54     // of type mismatches.
  55 
  56     public static void main(String[] args) {
  57         final Scenario[] scenarios = {
  58                 new Scenario(0),
  59                 new Scenario(1, "-XX:InlineFieldMaxFlatSize=0"),
  60                 new Scenario(2, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:+PatchALot"),
  61                 new Scenario(3, "-XX:InlineFieldMaxFlatSize=0",
  62                                 "-XX:+IgnoreUnrecognizedVMOptions", "-XX:+PatchALot")
  63         };
  64         InlineTypes.getFramework()
  65                    .addScenarios(scenarios)
  66                    .addFlags("--enable-preview",
  67                              // Prevent IR Test Framework from loading classes
  68                              "-DIgnoreCompilerControls=true",
  69                              // Some tests trigger frequent re-compilation. Don't mark them as non-compilable.
  70                              "-XX:PerMethodRecompilationCutoff=-1", "-XX:PerBytecodeRecompilationCutoff=-1")
  71                    .start();
  72     }
  73 
  74     // Test case 1:
  75     // The value class field class has been loaded, but the holder class has not been loaded.
  76     //
  77     //     aload_0
  78     //     getfield  MyValue1Holder.v:LMyValue1;
  79     //               ^ not loaded      ^ already loaded
  80     //
  81     // MyValue1 has already been loaded, because it's in the preload attribute of
  82     // TestUnloadedInlineTypeField, due to TestUnloadedInlineTypeField.test1_precondition().
  83     @ImplicitlyConstructible
  84     @LooselyConsistentValue
  85     static value class MyValue1 {
  86         int foo;
  87 
  88         MyValue1() {
  89             foo = rI;
  90         }
  91     }
  92 
  93     static class MyValue1Holder {
  94         @NullRestricted
  95         MyValue1 v;
  96 
  97         public MyValue1Holder() {
  98             v = new MyValue1();
  99         }
 100     }
 101 
 102     static MyValue1 test1_precondition() {
 103         return new MyValue1();
 104     }
 105 
 106     @Test
 107     public int test1(Object holder) {
 108         if (holder != null) {
 109             // Don't use MyValue1Holder in the signature, it might trigger class loading
 110             return ((MyValue1Holder)holder).v.foo;
 111         } else {
 112             return 0;
 113         }
 114     }
 115 
 116     @Run(test = "test1")
 117     public void test1_verifier(RunInfo info) {
 118         if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
 119             test1(null);
 120         } else {
 121             MyValue1Holder holder = new MyValue1Holder();
 122             Asserts.assertEQ(test1(holder), rI);
 123         }
 124     }
 125 
 126     // Test case 2:
 127     // Both the value class field class, and the holder class have not been loaded.
 128     //
 129     //     aload_0
 130     //     getfield  MyValue2Holder.v:LMyValue2;
 131     //               ^ not loaded     ^ not loaded
 132     //
 133     // MyValue2 has not been loaded, because it is not explicitly referenced by
 134     // TestUnloadedInlineTypeField.
 135     @ImplicitlyConstructible
 136     @LooselyConsistentValue
 137     static value class MyValue2 {
 138         int foo;
 139 
 140         public MyValue2(int n) {
 141             foo = n;
 142         }
 143     }
 144 
 145     static class MyValue2Holder {
 146         @NullRestricted
 147         MyValue2 v;
 148 
 149         public MyValue2Holder() {
 150             v = new MyValue2(rI);
 151         }
 152     }
 153 
 154     @Test
 155     public int test2(Object holder) {
 156         if (holder != null) {
 157             // Don't use MyValue2Holder in the signature, it might trigger class loading
 158             return ((MyValue2Holder)holder).v.foo;
 159         } else {
 160             return 0;
 161         }
 162     }
 163 
 164     @Run(test = "test2")
 165     public void test2_verifier(RunInfo info) {
 166         if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
 167             test2(null);
 168         } else {
 169             MyValue2Holder holder = new MyValue2Holder();
 170             Asserts.assertEQ(test2(holder), rI);
 171         }
 172     }
 173 
 174     // Test case 4:
 175     // Same as case 1, except we use putfield instead of getfield.
 176     @ImplicitlyConstructible
 177     @LooselyConsistentValue
 178     static value class MyValue4 {
 179         int foo;
 180 
 181         MyValue4(int n) {
 182             foo = n;
 183         }
 184     }
 185 
 186     static class MyValue4Holder {
 187         @NullRestricted
 188         MyValue4 v;
 189 
 190         public MyValue4Holder() {
 191             v = new MyValue4(0);
 192         }
 193     }
 194 
 195     @Test
 196     public void test4(Object holder, MyValue4 v) {
 197         if (holder != null) {
 198             // Don't use MyValue4Holder in the signature, it might trigger class loading
 199             ((MyValue4Holder)holder).v = v;
 200         }
 201     }
 202 
 203     @Run(test = "test4")
 204     public void test4_verifier(RunInfo info) {
 205         MyValue4 v = new MyValue4(rI);
 206         if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
 207             test4(null, v);
 208         } else {
 209             MyValue4Holder holder = new MyValue4Holder();
 210             test4(holder, v);
 211             Asserts.assertEQ(holder.v.foo, rI);
 212         }
 213     }
 214 
 215     // Test case 5:
 216     // Same as case 2, except we use putfield instead of getfield.
 217     @ImplicitlyConstructible
 218     @LooselyConsistentValue
 219     static value class MyValue5 {
 220         int foo;
 221 
 222         MyValue5(int n) {
 223             foo = n;
 224         }
 225     }
 226 
 227     static class MyValue5Holder {
 228         @NullRestricted
 229         MyValue5 v;
 230 
 231         public MyValue5Holder() {
 232             v = new MyValue5(0);
 233         }
 234 
 235         public Object make(int n) {
 236             return new MyValue5(n);
 237         }
 238     }
 239 
 240     @Test
 241     public void test5(Object holder, Object o) {
 242         if (holder != null) {
 243             // Don't use MyValue5 and MyValue5Holder in the signature, it might trigger class loading
 244             MyValue5 v = (MyValue5)o;
 245             ((MyValue5Holder)holder).v = v;
 246         }
 247     }
 248 
 249     @Run(test = "test5")
 250     public void test5_verifier(RunInfo info) {
 251         if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
 252             test5(null, null);
 253         } else {
 254             MyValue5Holder holder = new MyValue5Holder();
 255             Object v = holder.make(rI);
 256             test5(holder, v);
 257             Asserts.assertEQ(holder.v.foo, rI);
 258         }
 259     }
 260 
 261 
 262     // Test case 6: (same as test1, except we use getstatic instead of getfield)
 263     // The value class field class has been loaded, but the holder class has not been loaded.
 264     //
 265     //     getstatic  MyValue6Holder.v:LMyValue1;
 266     //                ^ not loaded       ^ already loaded
 267     //
 268     // MyValue6 has already been loaded, because it's in the preload attribute of
 269     // TestUnloadedInlineTypeField, due to TestUnloadedInlineTypeField.test1_precondition().
 270     @ImplicitlyConstructible
 271     @LooselyConsistentValue
 272     static value class MyValue6 {
 273         int foo;
 274 
 275         MyValue6() {
 276             foo = rI;
 277         }
 278     }
 279 
 280     static class MyValue6Holder {
 281         @NullRestricted
 282         static MyValue6 v = new MyValue6();
 283     }
 284 
 285     static MyValue6 test6_precondition() {
 286         return new MyValue6();
 287     }
 288 
 289     @Test
 290     public int test6(int n) {
 291         if (n == 0) {
 292             return 0;
 293         } else {
 294             return MyValue6Holder.v.foo + n;
 295         }
 296     }
 297 
 298     @Run(test = "test6")
 299     public void test6_verifier(RunInfo info) {
 300         if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
 301             test6(0);
 302         } else {
 303             Asserts.assertEQ(test6(rI), 2*rI);
 304         }
 305     }
 306 
 307 
 308     // Test case 7:  (same as test2, except we use getstatic instead of getfield)
 309     // Both the value class field class, and the holder class have not been loaded.
 310     //
 311     //     getstatic  MyValue7Holder.v:LMyValue7;
 312     //                ^ not loaded       ^ not loaded
 313     //
 314     // MyValue7 has not been loaded, because it is not explicitly referenced by
 315     // TestUnloadedInlineTypeField.
 316     @ImplicitlyConstructible
 317     @LooselyConsistentValue
 318     static value class MyValue7 {
 319         int foo;
 320 
 321         MyValue7(int n) {
 322             foo = n;
 323         }
 324     }
 325 
 326     static class MyValue7Holder {
 327         @NullRestricted
 328         static MyValue7 v = new MyValue7(rI);
 329     }
 330 
 331     @Test
 332     public int test7(int n) {
 333         if (n == 0) {
 334             return 0;
 335         } else {
 336             return MyValue7Holder.v.foo + n;
 337         }
 338     }
 339 
 340     @Run(test = "test7")
 341     public void test7_verifier(RunInfo info) {
 342         if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
 343             test7(0);
 344         } else {
 345             Asserts.assertEQ(test7(rI), 2*rI);
 346         }
 347     }
 348 
 349     // Test case 8:
 350     // Same as case 1, except holder is allocated in test method (-> no holder null check required)
 351     @ImplicitlyConstructible
 352     @LooselyConsistentValue
 353     static value class MyValue8 {
 354         int foo;
 355 
 356         MyValue8() {
 357             foo = rI;
 358         }
 359     }
 360 
 361     static class MyValue8Holder {
 362         @NullRestricted
 363         MyValue8 v;
 364 
 365         public MyValue8Holder() {
 366             v = new MyValue8();
 367         }
 368     }
 369 
 370     static MyValue8 test8_precondition() {
 371         return new MyValue8();
 372     }
 373 
 374     @Test
 375     public int test8(boolean warmup) {
 376         if (!warmup) {
 377             MyValue8Holder holder = new MyValue8Holder();
 378             return holder.v.foo;
 379         } else {
 380             return 0;
 381         }
 382     }
 383 
 384     @Run(test = "test8")
 385     public void test8_verifier(RunInfo info) {
 386         if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
 387             test8(true);
 388         } else {
 389             Asserts.assertEQ(test8(false), rI);
 390         }
 391     }
 392 
 393     // Test case 9:
 394     // Same as case 2, except holder is allocated in test method (-> no holder null check required)
 395     @ImplicitlyConstructible
 396     @LooselyConsistentValue
 397     static value class MyValue9 {
 398         int foo;
 399 
 400         public MyValue9(int n) {
 401             foo = n;
 402         }
 403     }
 404 
 405     static class MyValue9Holder {
 406         @NullRestricted
 407         MyValue9 v;
 408 
 409         public MyValue9Holder() {
 410             v = new MyValue9(rI);
 411         }
 412     }
 413 
 414     @Test
 415     public int test9(boolean warmup) {
 416         if (!warmup) {
 417             MyValue9Holder holder = new MyValue9Holder();
 418             return holder.v.foo;
 419         } else {
 420             return 0;
 421         }
 422     }
 423 
 424     @Run(test = "test9")
 425     public void test9_verifier(RunInfo info) {
 426         if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
 427             test9(true);
 428         } else {
 429             Asserts.assertEQ(test9(false), rI);
 430         }
 431     }
 432 
 433     // Test case 11:
 434     // Same as case 4, except holder is allocated in test method (-> no holder null check required)
 435     @ImplicitlyConstructible
 436     @LooselyConsistentValue
 437     static value class MyValue11 {
 438         int foo;
 439 
 440         MyValue11(int n) {
 441             foo = n;
 442         }
 443     }
 444 
 445     static class MyValue11Holder {
 446         @NullRestricted
 447         MyValue11 v;
 448 
 449         public MyValue11Holder() {
 450             v = new MyValue11(0);
 451         }
 452     }
 453 
 454     @Test
 455     public Object test11(boolean warmup, MyValue11 v) {
 456         if (!warmup) {
 457             MyValue11Holder holder = new MyValue11Holder();
 458             holder.v = v;
 459             return holder;
 460         } else {
 461             return null;
 462         }
 463     }
 464 
 465     @Run(test = "test11")
 466     public void test11_verifier(RunInfo info) {
 467         MyValue11 v = new MyValue11(rI);
 468         if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
 469             test11(true, v);
 470         } else {
 471             MyValue11Holder holder = (MyValue11Holder)test11(false, v);
 472             Asserts.assertEQ(holder.v.foo, rI);
 473         }
 474     }
 475 
 476     // Test case 12:
 477     // Same as case 5, except holder is allocated in test method (-> no holder null check required)
 478     @ImplicitlyConstructible
 479     @LooselyConsistentValue
 480     static value class MyValue12 {
 481         int foo;
 482 
 483         MyValue12(int n) {
 484             foo = n;
 485         }
 486     }
 487 
 488     static class MyValue12Holder {
 489         @NullRestricted
 490         MyValue12 v;
 491 
 492         public MyValue12Holder() {
 493             v = new MyValue12(0);
 494         }
 495     }
 496 
 497     @Test
 498     public Object test12(boolean warmup, Object o) {
 499         if (!warmup) {
 500             // Don't use MyValue12 in the signature, it might trigger class loading
 501             MyValue12Holder holder = new MyValue12Holder();
 502             holder.v = (MyValue12)o;
 503             return holder;
 504         } else {
 505             return null;
 506         }
 507     }
 508 
 509     @Run(test = "test12")
 510     public void test12_verifier(RunInfo info) {
 511         if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
 512             test12(true, null);
 513         } else {
 514             MyValue12 v = new MyValue12(rI);
 515             MyValue12Holder holder = (MyValue12Holder)test12(false, v);
 516             Asserts.assertEQ(holder.v.foo, rI);
 517         }
 518     }
 519 
 520     // Test case 13:
 521     // Same as case 10, except MyValue13 is allocated in test method
 522     @ImplicitlyConstructible
 523     @LooselyConsistentValue
 524     static value class MyValue13 {
 525         int foo;
 526 
 527         public MyValue13() {
 528             foo = rI;
 529         }
 530     }
 531 
 532     static class MyValue13Holder {
 533         @NullRestricted
 534         MyValue13 v;
 535 
 536         public MyValue13Holder() {
 537             v = new MyValue13();
 538         }
 539     }
 540 
 541     static MyValue13 test13_precondition() {
 542         return new MyValue13();
 543     }
 544 
 545     @Test
 546     public void test13(Object holder) {
 547         // Don't use MyValue13Holder in the signature, it might trigger class loading
 548         GetUnresolvedInlineFieldWrongSignature.test13(holder);
 549     }
 550 
 551     @Run(test = "test13")
 552     public void test13_verifier(RunInfo info) {
 553         if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
 554             test13(null);
 555         } else {
 556             // Make sure klass is resolved
 557             for (int i = 0; i < 10; ++i) {
 558                 test13(new MyValue13Holder());
 559             }
 560         }
 561     }
 562 
 563     // Test case 15:
 564     // Same as case 13, except MyValue15 is unloaded
 565     @ImplicitlyConstructible
 566     @LooselyConsistentValue
 567     static value class MyValue15 {
 568         int foo;
 569 
 570         public MyValue15() {
 571             foo = rI;
 572         }
 573     }
 574 
 575     static class MyValue15Holder {
 576         @NullRestricted
 577         MyValue15 v;
 578 
 579         public MyValue15Holder() {
 580             v = new MyValue15();
 581         }
 582     }
 583 
 584     @Test
 585     public void test15(Object holder) {
 586         // Don't use MyValue15Holder in the signature, it might trigger class loading
 587         GetUnresolvedInlineFieldWrongSignature.test15(holder);
 588     }
 589 
 590     @Run(test = "test15")
 591     public void test15_verifier(RunInfo info) {
 592         if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
 593             test15(null);
 594         } else {
 595             // Make sure klass is resolved
 596             for (int i = 0; i < 10; ++i) {
 597                 test15(new MyValue15Holder());
 598             }
 599         }
 600     }
 601 
 602     // Test case 16:
 603     // aconst_init with type which is not a value class
 604     static class MyValue16 {
 605         int foo;
 606 
 607         public MyValue16() {
 608             foo = rI;
 609         }
 610     }
 611 
 612     static MyValue16 test16_precondition() {
 613         return new MyValue16();
 614     }
 615 
 616     @Test
 617     public Object test16(boolean warmup) {
 618         return GetUnresolvedInlineFieldWrongSignature.test16(warmup);
 619     }
 620 
 621     @Run(test = "test16")
 622     public void test16_verifier(RunInfo info) {
 623         if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
 624             test16(true);
 625         } else {
 626             // Make sure klass is resolved
 627             for (int i = 0; i < 10; ++i) {
 628                 test16(false);
 629             }
 630         }
 631     }
 632 
 633     // Test case 17:
 634     // Same as test16 but with unloaded type at aconst_init
 635     static class MyValue17 {
 636         int foo;
 637 
 638         public MyValue17() {
 639             foo = rI;
 640         }
 641     }
 642 
 643     @Test
 644     public Object test17(boolean warmup) {
 645         return GetUnresolvedInlineFieldWrongSignature.test17(warmup);
 646     }
 647 
 648     @Run(test = "test17")
 649     public void test17_verifier(RunInfo info) {
 650         if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
 651             test17(true);
 652         } else {
 653             // Make sure klass is resolved
 654             for (int i = 0; i < 10; ++i) {
 655                 test17(false);
 656             }
 657         }
 658     }
 659 
 660     // Test case 18:
 661     // Same as test7 but with the holder being loaded
 662     @ImplicitlyConstructible
 663     @LooselyConsistentValue
 664     static value class MyValue18 {
 665         int foo;
 666 
 667         MyValue18(int n) {
 668             foo = n;
 669         }
 670     }
 671 
 672     static class MyValue18Holder {
 673         @NullRestricted
 674         static MyValue18 v = new MyValue18(rI);
 675     }
 676 
 677     @Test
 678     public int test18(int n) {
 679         if (n == 0) {
 680             return 0;
 681         } else {
 682             return MyValue18Holder.v.foo + n;
 683         }
 684     }
 685 
 686     @Run(test = "test18")
 687     public void test18_verifier(RunInfo info) {
 688         // Make sure MyValue18Holder is loaded
 689         MyValue18Holder holder = new MyValue18Holder();
 690         if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
 691             test18(0);
 692         } else {
 693             Asserts.assertEQ(test18(rI), 2*rI);
 694         }
 695     }
 696 
 697     // Test case 19:
 698     // Same as test18 but uninitialized (null) static value class field
 699     @ImplicitlyConstructible
 700     @LooselyConsistentValue
 701     static value class MyValue19 {
 702         int foo;
 703 
 704         MyValue19(int n) {
 705             foo = n;
 706         }
 707     }
 708 
 709     static class MyValue19Holder {
 710         @NullRestricted
 711         static MyValue19 v;
 712     }
 713 
 714     @Test
 715     public int test19(int n) {
 716         if (n == 0) {
 717             return 0;
 718         } else {
 719             return MyValue19Holder.v.foo + n;
 720         }
 721     }
 722 
 723     @Run(test = "test19")
 724     public void test19_verifier(RunInfo info) {
 725         // Make sure MyValue19Holder is loaded
 726         MyValue19Holder holder = new MyValue19Holder();
 727         if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
 728             test19(0);
 729         } else {
 730             Asserts.assertEQ(test19(rI), rI);
 731         }
 732     }
 733 
 734     // Test case 20:
 735     // Value class with object field of unloaded type.
 736     static class MyObject20 {
 737         int x = 42;
 738     }
 739 
 740     @ImplicitlyConstructible
 741     @LooselyConsistentValue
 742     static value class MyValue20 {
 743         MyObject20 obj;
 744 
 745         MyValue20() {
 746             this.obj = null;
 747         }
 748     }
 749 
 750     @Test
 751     public MyValue20 test20() {
 752         return new MyValue20();
 753     }
 754 
 755     @Run(test = "test20")
 756     public void test20_verifier() {
 757         MyValue20 vt = test20();
 758         Asserts.assertEQ(vt.obj, null);
 759     }
 760 
 761     @ImplicitlyConstructible
 762     @LooselyConsistentValue
 763     static value class Test21ClassA {
 764         @NullRestricted
 765         static Test21ClassB b;
 766         @NullRestricted
 767         static Test21ClassC c;
 768     }
 769 
 770     @ImplicitlyConstructible
 771     @LooselyConsistentValue
 772     static value class Test21ClassB {
 773         static int x = Test21ClassA.c.x;
 774     }
 775 
 776     @ImplicitlyConstructible
 777     @LooselyConsistentValue
 778     static value class Test21ClassC {
 779         int x = 42;
 780     }
 781 
 782     // Test access to static value class field with unloaded type
 783     @Test
 784     public Object test21() {
 785         return new Test21ClassA();
 786     }
 787 
 788     @Run(test = "test21")
 789     public void test21_verifier() {
 790         Object ret = test21();
 791         Asserts.assertEQ(Test21ClassA.b.x, 42);
 792         Asserts.assertEQ(Test21ClassA.c.x, 42);
 793     }
 794 
 795     static boolean test22FailInit = true;
 796 
 797     @ImplicitlyConstructible
 798     @LooselyConsistentValue
 799     static value class Test22ClassA {
 800         int x = 0;
 801         @NullRestricted
 802         static Test22ClassB b;
 803     }
 804 
 805     @ImplicitlyConstructible
 806     @LooselyConsistentValue
 807     static value class Test22ClassB {
 808         int x = 0;
 809         static {
 810             if (test22FailInit) {
 811                 throw new RuntimeException("Init failed");
 812             }
 813         }
 814     }
 815 
 816     // Test that load from static field of uninitialized value class throws an exception
 817     @Test
 818     public Object test22() {
 819         return Test22ClassA.b;
 820     }
 821 
 822     @Run(test = "test22")
 823     public void test22_verifier() {
 824         // Trigger initialization error in Test22ClassB
 825         try {
 826             Test22ClassB b = new Test22ClassB();
 827             throw new RuntimeException("Should have thrown error during initialization");
 828         } catch (ExceptionInInitializerError | NoClassDefFoundError e) {
 829             // Expected
 830         }
 831         try {
 832             test22();
 833             throw new RuntimeException("Should have thrown NoClassDefFoundError");
 834         } catch (NoClassDefFoundError e) {
 835             // Expected
 836         }
 837     }
 838 
 839     static boolean test23FailInit = true;
 840 
 841     @ImplicitlyConstructible
 842     @LooselyConsistentValue
 843     static value class Test23ClassA {
 844         int x = 0;
 845         @NullRestricted
 846         static Test23ClassB b;
 847     }
 848 
 849     @ImplicitlyConstructible
 850     @LooselyConsistentValue
 851     static value class Test23ClassB {
 852         static {
 853             if (test23FailInit) {
 854                 throw new RuntimeException("Init failed");
 855             }
 856         }
 857     }
 858 
 859     // Same as test22 but with empty ClassB
 860     @Test
 861     public Object test23() {
 862         return Test23ClassA.b;
 863     }
 864 
 865     @Run(test = "test23")
 866     public void test23_verifier() {
 867         // Trigger initialization error in Test23ClassB
 868         try {
 869             Test23ClassB b = new Test23ClassB();
 870             throw new RuntimeException("Should have thrown error during initialization");
 871         } catch (ExceptionInInitializerError | NoClassDefFoundError e) {
 872             // Expected
 873         }
 874         try {
 875             test23();
 876             throw new RuntimeException("Should have thrown NoClassDefFoundError");
 877         } catch (NoClassDefFoundError e) {
 878             // Expected
 879         }
 880     }
 881 
 882     static boolean test24FailInit = true;
 883 
 884     @ImplicitlyConstructible
 885     @LooselyConsistentValue
 886     static value class Test24ClassA {
 887         @NullRestricted
 888         Test24ClassB b = new Test24ClassB();
 889     }
 890 
 891     @ImplicitlyConstructible
 892     @LooselyConsistentValue
 893     static value class Test24ClassB {
 894         int x = 0;
 895         static {
 896             if (test24FailInit) {
 897                 throw new RuntimeException("Init failed");
 898             }
 899         }
 900     }
 901 
 902     // Test that access to non-static field of uninitialized value class throws an exception
 903     @Test
 904     public Object test24() {
 905         return (new Test24ClassA()).b.x;
 906     }
 907 
 908     @Run(test = "test24")
 909     public void test24_verifier() {
 910         // Trigger initialization error in Test24ClassB
 911         try {
 912             Test24ClassB b = new Test24ClassB();
 913             throw new RuntimeException("Should have thrown error during initialization");
 914         } catch (ExceptionInInitializerError | NoClassDefFoundError e) {
 915             // Expected
 916         }
 917         try {
 918             test24();
 919             throw new RuntimeException("Should have thrown NoClassDefFoundError");
 920         } catch (NoClassDefFoundError e) {
 921             // Expected
 922         }
 923     }
 924 
 925     static boolean test25FailInit = true;
 926 
 927     @ImplicitlyConstructible
 928     @LooselyConsistentValue
 929     static value class Test25ClassA {
 930         @NullRestricted
 931         Test25ClassB b = new Test25ClassB();
 932     }
 933 
 934     @ImplicitlyConstructible
 935     @LooselyConsistentValue
 936     static value class Test25ClassB {
 937         int x = 24;
 938         static {
 939             if (test25FailInit) {
 940                 throw new RuntimeException("Init failed");
 941             }
 942         }
 943     }
 944 
 945     // Same as test24 but with field access outside of test method
 946     @Test
 947     public Test25ClassB test25() {
 948         return (new Test25ClassA()).b;
 949     }
 950 
 951     @Run(test = "test25")
 952     public void test25_verifier() {
 953         // Trigger initialization error in Test25ClassB
 954         try {
 955             Test25ClassB b = new Test25ClassB();
 956             throw new RuntimeException("Should have thrown error during initialization");
 957         } catch (ExceptionInInitializerError | NoClassDefFoundError e) {
 958             // Expected
 959         }
 960         try {
 961             Test25ClassB res = test25();
 962             Asserts.assertEQ(res.x, 0);
 963             throw new RuntimeException("Should have thrown NoClassDefFoundError");
 964         } catch (NoClassDefFoundError e) {
 965             // Expected
 966         }
 967     }
 968 
 969     static boolean test26FailInit = true;
 970 
 971     @ImplicitlyConstructible
 972     @LooselyConsistentValue
 973     static value class Test26ClassA {
 974         @NullRestricted
 975         Test26ClassB b = new Test26ClassB();
 976     }
 977 
 978     @ImplicitlyConstructible
 979     @LooselyConsistentValue
 980     static value class Test26ClassB {
 981         static {
 982             if (test26FailInit) {
 983                 throw new RuntimeException("Init failed");
 984             }
 985         }
 986     }
 987 
 988     // Same as test25 but with empty ClassB
 989     @Test
 990     public Object test26() {
 991         return (new Test26ClassA()).b;
 992     }
 993 
 994     @Run(test = "test26")
 995     public void test26_verifier() {
 996         // Trigger initialization error in Test26ClassB
 997         try {
 998             Test26ClassB b = new Test26ClassB();
 999             throw new RuntimeException("Should have thrown error during initialization");
1000         } catch (ExceptionInInitializerError | NoClassDefFoundError e) {
1001             // Expected
1002         }
1003         try {
1004             test26();
1005             throw new RuntimeException("Should have thrown NoClassDefFoundError");
1006         } catch (NoClassDefFoundError e) {
1007             // Expected
1008         }
1009     }
1010 
1011     @ImplicitlyConstructible
1012     @LooselyConsistentValue
1013     static value class MyValue27 {
1014         int foo = 42;
1015     }
1016 
1017     static class MyValue27Holder {
1018         @NullRestricted
1019         MyValue27 v;
1020     }
1021 
1022     // Make sure MyValue27Holder is loaded but MyValue27 is not
1023     Class test27Class = MyValue27Holder.class;
1024 
1025     // Test unloaded value class field load from loaded holder
1026     @Test
1027     public static int test27() {
1028         MyValue27Holder holder = new MyValue27Holder();
1029         return holder.v.foo;
1030     }
1031 
1032     @Run(test = "test27")
1033     public void test27_verifier() {
1034         Asserts.assertEQ(test27(), 42);
1035     }
1036 
1037     @ImplicitlyConstructible
1038     @LooselyConsistentValue
1039     static value class MyValue28 {
1040         @NullRestricted
1041         static MyValue28 field1;
1042     }
1043 
1044     // Test null store to null restricted field with unloaded holder
1045     @Test
1046     public static void test28() {
1047         MyValue28.field1 = null;
1048     }
1049 
1050     @Run(test = "test28")
1051     @Warmup(0) // Make sure that MyValue28 is not loaded
1052     public void test28_verifier() {
1053         try {
1054             test28();
1055             throw new RuntimeException("No exception thrown");
1056         } catch (NullPointerException e) {
1057             // Expected
1058         }
1059     }
1060 }