1 /*
   2  * Copyright (c) 2024, 2026, 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 jdk.internal.vm.annotation.LooselyConsistentValue;
  27 import jdk.internal.vm.annotation.NullRestricted;
  28 
  29 import jdk.test.lib.Asserts;
  30 import jdk.test.lib.helpers.StrictInit;
  31 
  32 /*
  33  * @test id=noFlags
  34  * @key randomness
  35  * @summary Test support for null markers in flat fields.
  36  * @library /test/lib /
  37  * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
  38  * @enablePreview
  39  * @modules java.base/jdk.internal.value
  40  *          java.base/jdk.internal.vm.annotation
  41  * @compile TestFieldNullMarkers.java
  42  * @run driver jdk.test.lib.helpers.StrictProcessor
  43  *             compiler.valhalla.inlinetypes.TestFieldNullMarkers$StrictFieldHolder
  44  * @run main/timeout=300 compiler.valhalla.inlinetypes.TestFieldNullMarkers
  45  */
  46 
  47 /*
  48  * @test id=no-flattening
  49  * @key randomness
  50  * @summary Test support for null markers in flat fields.
  51  * @library /test/lib /
  52  * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
  53  * @enablePreview
  54  * @modules java.base/jdk.internal.value
  55  *          java.base/jdk.internal.vm.annotation
  56  * @compile TestFieldNullMarkers.java
  57  * @run driver jdk.test.lib.helpers.StrictProcessor
  58  *             compiler.valhalla.inlinetypes.TestFieldNullMarkers$StrictFieldHolder
  59  * @run main/othervm/timeout=300 -Xbatch
  60  *                               -XX:-UseNullableValueFlattening -XX:-UseAtomicValueFlattening -XX:-UseNonAtomicValueFlattening
  61  *                               compiler.valhalla.inlinetypes.TestFieldNullMarkers
  62  */
  63 
  64 /*
  65  * @test id=nAVF
  66  * @key randomness
  67  * @summary Test support for null markers in flat fields.
  68  * @library /test/lib /
  69  * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
  70  * @enablePreview
  71  * @modules java.base/jdk.internal.value
  72  *          java.base/jdk.internal.vm.annotation
  73  * @compile TestFieldNullMarkers.java
  74  * @run driver jdk.test.lib.helpers.StrictProcessor
  75  *             compiler.valhalla.inlinetypes.TestFieldNullMarkers$StrictFieldHolder
  76  * @run main/othervm/timeout=300 -Xbatch
  77  *                               -XX:-UseNullableValueFlattening -XX:-UseAtomicValueFlattening -XX:+UseNonAtomicValueFlattening
  78  *                               compiler.valhalla.inlinetypes.TestFieldNullMarkers
  79  */
  80 
  81 /*
  82  * @test id=AVF
  83  * @key randomness
  84  * @summary Test support for null markers in flat fields.
  85  * @library /test/lib /
  86  * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
  87  * @enablePreview
  88  * @modules java.base/jdk.internal.value
  89  *          java.base/jdk.internal.vm.annotation
  90  * @compile TestFieldNullMarkers.java
  91  * @run driver jdk.test.lib.helpers.StrictProcessor
  92  *             compiler.valhalla.inlinetypes.TestFieldNullMarkers$StrictFieldHolder
  93  * @run main/othervm/timeout=300 -Xbatch
  94  *                               -XX:-UseNullableValueFlattening -XX:+UseAtomicValueFlattening -XX:-UseNonAtomicValueFlattening
  95  *                               compiler.valhalla.inlinetypes.TestFieldNullMarkers
  96  */
  97 
  98 /*
  99  * @test id=AVF-nAVF
 100  * @key randomness
 101  * @summary Test support for null markers in flat fields.
 102  * @library /test/lib /
 103  * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
 104  * @enablePreview
 105  * @modules java.base/jdk.internal.value
 106  *          java.base/jdk.internal.vm.annotation
 107  * @compile TestFieldNullMarkers.java
 108  * @run driver jdk.test.lib.helpers.StrictProcessor
 109  *             compiler.valhalla.inlinetypes.TestFieldNullMarkers$StrictFieldHolder
 110  * @run main/othervm/timeout=300 -Xbatch
 111  *                               -XX:-UseNullableValueFlattening -XX:+UseAtomicValueFlattening -XX:+UseNonAtomicValueFlattening
 112  *                               compiler.valhalla.inlinetypes.TestFieldNullMarkers
 113  */
 114 
 115 /*
 116  * @test id=NVF
 117  * @key randomness
 118  * @summary Test support for null markers in flat fields.
 119  * @library /test/lib /
 120  * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
 121  * @enablePreview
 122  * @modules java.base/jdk.internal.value
 123  *          java.base/jdk.internal.vm.annotation
 124  * @compile TestFieldNullMarkers.java
 125  * @run driver jdk.test.lib.helpers.StrictProcessor
 126  *             compiler.valhalla.inlinetypes.TestFieldNullMarkers$StrictFieldHolder
 127  * @run main/othervm/timeout=300 -Xbatch
 128  *                               -XX:+UseNullableValueFlattening -XX:-UseAtomicValueFlattening -XX:-UseNonAtomicValueFlattening
 129  *                               compiler.valhalla.inlinetypes.TestFieldNullMarkers
 130  */
 131 
 132 /*
 133  * @test id=NVF-nAVF
 134  * @key randomness
 135  * @summary Test support for null markers in flat fields.
 136  * @library /test/lib /
 137  * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
 138  * @enablePreview
 139  * @modules java.base/jdk.internal.value
 140  *          java.base/jdk.internal.vm.annotation
 141  * @compile TestFieldNullMarkers.java
 142  * @run driver jdk.test.lib.helpers.StrictProcessor
 143  *             compiler.valhalla.inlinetypes.TestFieldNullMarkers$StrictFieldHolder
 144  * @run main/othervm/timeout=300 -Xbatch
 145  *                               -XX:+UseNullableValueFlattening -XX:-UseAtomicValueFlattening -XX:+UseNonAtomicValueFlattening
 146  *                               compiler.valhalla.inlinetypes.TestFieldNullMarkers
 147  */
 148 
 149 /*
 150  * @test id=NVF-AVF
 151  * @key randomness
 152  * @summary Test support for null markers in flat fields.
 153  * @library /test/lib /
 154  * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
 155  * @enablePreview
 156  * @modules java.base/jdk.internal.value
 157  *          java.base/jdk.internal.vm.annotation
 158  * @compile TestFieldNullMarkers.java
 159  * @run driver jdk.test.lib.helpers.StrictProcessor
 160  *             compiler.valhalla.inlinetypes.TestFieldNullMarkers$StrictFieldHolder
 161  * @run main/othervm/timeout=300 -Xbatch
 162  *                               -XX:+UseNullableValueFlattening -XX:+UseAtomicValueFlattening -XX:-UseNonAtomicValueFlattening
 163  *                               compiler.valhalla.inlinetypes.TestFieldNullMarkers
 164  */
 165 
 166 /*
 167  * @test id=all-flattening
 168  * @key randomness
 169  * @summary Test support for null markers in flat fields.
 170  * @library /test/lib /
 171  * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
 172  * @enablePreview
 173  * @modules java.base/jdk.internal.value
 174  *          java.base/jdk.internal.vm.annotation
 175  * @compile TestFieldNullMarkers.java
 176  * @run driver jdk.test.lib.helpers.StrictProcessor
 177  *             compiler.valhalla.inlinetypes.TestFieldNullMarkers$StrictFieldHolder
 178  * @run main/othervm/timeout=300 -Xbatch
 179  *                               -XX:+UseNullableValueFlattening -XX:+UseAtomicValueFlattening -XX:+UseNonAtomicValueFlattening
 180  *                               compiler.valhalla.inlinetypes.TestFieldNullMarkers
 181  */
 182 
 183 /*
 184  * @test id=all-flattening-di
 185  * @key randomness
 186  * @summary Test support for null markers in flat fields.
 187  * @library /test/lib /
 188  * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
 189  * @enablePreview
 190  * @modules java.base/jdk.internal.value
 191  *          java.base/jdk.internal.vm.annotation
 192  * @compile TestFieldNullMarkers.java
 193  * @run driver jdk.test.lib.helpers.StrictProcessor
 194  *             compiler.valhalla.inlinetypes.TestFieldNullMarkers$StrictFieldHolder
 195  * @run main/othervm/timeout=300 -Xbatch
 196  *                               -XX:+UseNullableValueFlattening -XX:+UseAtomicValueFlattening -XX:+UseNonAtomicValueFlattening
 197  *                               -XX:CompileCommand=dontinline,*::testHelper*
 198  *                               compiler.valhalla.inlinetypes.TestFieldNullMarkers
 199  */
 200 
 201 /*
 202  * @test id=all-flattening-pass-fields
 203  * @key randomness
 204  * @summary Test support for null markers in flat fields.
 205  * @library /test/lib /
 206  * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
 207  * @enablePreview
 208  * @modules java.base/jdk.internal.value
 209  *          java.base/jdk.internal.vm.annotation
 210  * @compile TestFieldNullMarkers.java
 211  * @run driver jdk.test.lib.helpers.StrictProcessor
 212  *             compiler.valhalla.inlinetypes.TestFieldNullMarkers$StrictFieldHolder
 213  * @run main/othervm/timeout=300 -Xbatch
 214  *                               -XX:+UseNullableValueFlattening -XX:+UseAtomicValueFlattening -XX:+UseNonAtomicValueFlattening
 215  *                               -XX:+InlineTypeReturnedAsFields -XX:+InlineTypePassFieldsAsArgs
 216  *                               compiler.valhalla.inlinetypes.TestFieldNullMarkers
 217  */
 218 
 219 /*
 220  * @test id=all-flattening-no-pass-fields
 221  * @key randomness
 222  * @summary Test support for null markers in flat fields.
 223  * @library /test/lib /
 224  * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
 225  * @enablePreview
 226  * @modules java.base/jdk.internal.value
 227  *          java.base/jdk.internal.vm.annotation
 228  * @compile TestFieldNullMarkers.java
 229  * @run driver jdk.test.lib.helpers.StrictProcessor
 230  *             compiler.valhalla.inlinetypes.TestFieldNullMarkers$StrictFieldHolder
 231  * @run main/othervm/timeout=300 -Xbatch
 232  *                               -XX:+UseNullableValueFlattening -XX:+UseAtomicValueFlattening -XX:+UseNonAtomicValueFlattening
 233  *                               -XX:-InlineTypeReturnedAsFields -XX:-InlineTypePassFieldsAsArgs
 234  *                               compiler.valhalla.inlinetypes.TestFieldNullMarkers
 235  */
 236 
 237 /*
 238  * @test id=all-flattening-return-fields
 239  * @key randomness
 240  * @summary Test support for null markers in flat fields.
 241  * @library /test/lib /
 242  * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
 243  * @enablePreview
 244  * @modules java.base/jdk.internal.value
 245  *          java.base/jdk.internal.vm.annotation
 246  * @compile TestFieldNullMarkers.java
 247  * @run driver jdk.test.lib.helpers.StrictProcessor
 248  *             compiler.valhalla.inlinetypes.TestFieldNullMarkers$StrictFieldHolder
 249  * @run main/othervm/timeout=300 -Xbatch
 250  *                               -XX:+UseNullableValueFlattening -XX:+UseAtomicValueFlattening -XX:+UseNonAtomicValueFlattening
 251  *                               -XX:+InlineTypeReturnedAsFields -XX:-InlineTypePassFieldsAsArgs
 252  *                               compiler.valhalla.inlinetypes.TestFieldNullMarkers
 253  */
 254 
 255 /*
 256  * @test id=all-flattening-pass-args
 257  * @key randomness
 258  * @summary Test support for null markers in flat fields.
 259  * @library /test/lib /
 260  * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
 261  * @enablePreview
 262  * @modules java.base/jdk.internal.value
 263  *          java.base/jdk.internal.vm.annotation
 264  * @compile TestFieldNullMarkers.java
 265  * @run driver jdk.test.lib.helpers.StrictProcessor
 266  *             compiler.valhalla.inlinetypes.TestFieldNullMarkers$StrictFieldHolder
 267  * @run main/othervm/timeout=300 -Xbatch
 268  *                               -XX:+UseNullableValueFlattening -XX:+UseAtomicValueFlattening -XX:+UseNonAtomicValueFlattening
 269  *                               -XX:-InlineTypeReturnedAsFields -XX:+InlineTypePassFieldsAsArgs
 270  *                               compiler.valhalla.inlinetypes.TestFieldNullMarkers
 271  */
 272 
 273 public class TestFieldNullMarkers {
 274 
 275     public TestFieldNullMarkers() {
 276         field12 = new MyValue8((byte)0);
 277         field13 = MyValue14.DEFAULT;
 278         field16 = MyValue14.DEFAULT;
 279         field17 = new MyValue15(null);
 280         field19 = new MyValue16(null, null);
 281         field20 = new MyValue17(null, (byte)0, (byte)0);
 282         emptyField1 = new MyValueEmpty();
 283         emptyField2 = new MyValueEmpty();
 284         super();
 285     }
 286 
 287     // Value class with two nullable flat fields
 288     @LooselyConsistentValue
 289     static value class MyValue1 {
 290         byte x;
 291         MyValue2 val1;
 292         MyValue2 val2;
 293 
 294         public MyValue1(byte x, MyValue2 val1, MyValue2 val2) {
 295             this.x = x;
 296             this.val1 = val1;
 297             this.val2 = val2;
 298         }
 299 
 300         public String toString() {
 301             return "x = " + x + ", val1 = [" + val1 + "], val2 = [" + val2 + "]";
 302         }
 303     }
 304 
 305     @LooselyConsistentValue
 306     static abstract value class MyAbstract1 {
 307         byte x;
 308 
 309         public MyAbstract1(byte x) {
 310             this.x = x;
 311         }
 312     }
 313 
 314     // Empty value class inheriting single field from abstract super class
 315     @LooselyConsistentValue
 316     static value class MyValue2 extends MyAbstract1 {
 317         public MyValue2(byte x) {
 318             super(x);
 319         }
 320 
 321         public String toString() {
 322             return "x = " + x;
 323         }
 324     }
 325 
 326     // Value class with a hole in the payload that will be used for the null marker
 327     @LooselyConsistentValue
 328     static value class MyValue3 {
 329         byte x;
 330         // Hole that will be used by the null marker
 331         int i;
 332 
 333         public MyValue3(byte x) {
 334             this.x = x;
 335             this.i = x;
 336         }
 337 
 338         public String toString() {
 339             return "x = " + x + ", i = " + i;
 340         }
 341     }
 342 
 343     // Value class with two nullable flat fields that have their null markers *not* at the end of the payload
 344     @LooselyConsistentValue
 345     static value class MyValue4 {
 346         MyValue3 val1;
 347         MyValue3 val2;
 348 
 349         public MyValue4(MyValue3 val1, MyValue3 val2) {
 350             this.val1 = val1;
 351             this.val2 = val2;
 352         }
 353 
 354         public String toString() {
 355             return "val1 = [" + val1 + "], val2 = [" + val2 + "]";
 356         }
 357     }
 358 
 359     @LooselyConsistentValue
 360     static value class MyValue5C {
 361         byte x;
 362 
 363         public MyValue5C(byte x) {
 364             this.x = x;
 365         }
 366     }
 367 
 368     @LooselyConsistentValue
 369     static value class MyValue5B {
 370         byte x;
 371         MyValue5C val;
 372 
 373         public MyValue5B(byte x, MyValue5C val) {
 374             this.x = x;
 375             this.val = val;
 376         }
 377     }
 378 
 379     @LooselyConsistentValue
 380     static value class MyValue5A {
 381         byte x;
 382         MyValue5B val;
 383 
 384         public MyValue5A(byte x, MyValue5B val) {
 385             this.x = x;
 386             this.val = val;
 387         }
 388     }
 389 
 390     // Value class with deep nesting of nullable flat fields
 391     @LooselyConsistentValue
 392     static value class MyValue5 {
 393         byte x;
 394         MyValue5A val;
 395 
 396         public MyValue5(byte x, MyValue5A val) {
 397             this.x = x;
 398             this.val = val;
 399         }
 400     }
 401 
 402     @LooselyConsistentValue
 403     static value class MyValueEmpty {
 404 
 405     }
 406 
 407     // Value class with flat field of empty value class
 408     @LooselyConsistentValue
 409     static value class MyValue6 {
 410         MyValueEmpty val;
 411 
 412         public MyValue6(MyValueEmpty val) {
 413             this.val = val;
 414         }
 415     }
 416 
 417     // Same as MyValue6 but one more level of nested flat fields
 418     @LooselyConsistentValue
 419     static value class MyValue7 {
 420         MyValue6 val;
 421 
 422         public MyValue7(MyValue6 val) {
 423             this.val = val;
 424         }
 425     }
 426 
 427     // Some more field types
 428 
 429     @LooselyConsistentValue
 430     static value class MyValue8 {
 431         byte b;
 432 
 433         public MyValue8(byte b) {
 434             this.b = b;
 435         }
 436     }
 437 
 438     @LooselyConsistentValue
 439     static value class MyValue9 {
 440         short s;
 441 
 442         public MyValue9(short s) {
 443             this.s = s;
 444         }
 445     }
 446 
 447     @LooselyConsistentValue
 448     static value class MyValue10 {
 449         int i;
 450 
 451         public MyValue10(int i) {
 452             this.i = i;
 453         }
 454     }
 455 
 456     @LooselyConsistentValue
 457     static value class MyValue11 {
 458         float f;
 459 
 460         public MyValue11(float f) {
 461             this.f = f;
 462         }
 463     }
 464 
 465     @LooselyConsistentValue
 466     static value class MyValue12 {
 467         char c;
 468 
 469         public MyValue12(char c) {
 470             this.c = c;
 471         }
 472     }
 473 
 474     @LooselyConsistentValue
 475     static value class MyValue13 {
 476         boolean b;
 477 
 478         public MyValue13(boolean b) {
 479             this.b = b;
 480         }
 481     }
 482 
 483     // Test value class with nullable and null-free fields
 484     @LooselyConsistentValue
 485     static value class MyValue14 {
 486         @NullRestricted
 487         MyValue8 nullfree;
 488         MyValue8 nullable;
 489 
 490         public MyValue14(MyValue8 nullfree, MyValue8 nullable) {
 491             this.nullfree = nullfree;
 492             this.nullable = nullable;
 493         }
 494 
 495         public static final MyValue14 DEFAULT = new MyValue14(new MyValue8((byte)0), null);
 496     }
 497 
 498     static class MyClass {
 499         int x;
 500 
 501         public MyClass(int x) {
 502             this.x = x;
 503         }
 504     }
 505 
 506     // Value class with oop field
 507     @LooselyConsistentValue
 508     static value class MyValue15 {
 509         MyClass obj;
 510 
 511         public MyValue15(MyClass obj) {
 512             this.obj = obj;
 513         }
 514     }
 515 
 516     // Value class with two oop fields
 517     @LooselyConsistentValue
 518     static value class MyValue16 {
 519         MyClass obj1;
 520         MyClass obj2;
 521 
 522         public MyValue16(MyClass obj1, MyClass obj2) {
 523             this.obj1 = obj1;
 524             this.obj2 = obj2;
 525         }
 526     }
 527 
 528     // Value class with oop field and primitive fields
 529     @LooselyConsistentValue
 530     static value class MyValue17 {
 531         byte b1;
 532         MyClass obj;
 533         byte b2;
 534 
 535         public MyValue17(MyClass obj, byte b1, byte b2) {
 536             this.obj = obj;
 537             this.b1 = b1;
 538             this.b2 = b2;
 539         }
 540     }
 541 
 542     MyValue1 field1; // Not flat
 543     MyValue4 field2; // Not flat
 544     MyValue5 field3; // Flat
 545     MyValue6 field4; // Flat
 546     MyValue7 field5; // Flat
 547     MyValue8 field6; // Flat
 548     MyValue9 field7; // Flat
 549     MyValue10 field8; // Flat
 550     MyValue11 field9; // Flat
 551     MyValue12 field10; // Flat
 552     MyValue13 field11; // Flat
 553 
 554     @NullRestricted
 555     volatile MyValue8 field12;
 556 
 557     @NullRestricted
 558     MyValue14 field13; // Null-free, flat
 559     volatile MyValue14 field14; // Nullable, atomic, flat
 560     MyValue14 field15;          // Nullable, (atomic), flat
 561     @NullRestricted
 562     volatile MyValue14 field16; // Null-free, atomic, flat
 563 
 564     @NullRestricted
 565     volatile MyValue15 field17;
 566     MyValue15 field18;
 567     @NullRestricted
 568     volatile MyValue16 field19;
 569     @NullRestricted
 570     volatile MyValue17 field20;
 571     MyValue17 field21;
 572 
 573     // Combinations of strict fields
 574     static class StrictFieldHolder {
 575         @StrictInit
 576         MyValue8 strictField1;
 577         @StrictInit
 578         final MyValue8 strictField2;
 579         @NullRestricted
 580         MyValue8 strictField3;
 581         @NullRestricted
 582         final MyValue8 strictField4;
 583         @StrictInit
 584         volatile MyValue8 strictField5;
 585         @NullRestricted
 586         volatile MyValue8 strictField6;
 587 
 588         @StrictInit
 589         TwoBytes strictField7;
 590         @StrictInit
 591         final TwoBytes strictField8;
 592         @NullRestricted
 593         TwoBytes strictField9;
 594         @NullRestricted
 595         final TwoBytes strictField10;
 596         @StrictInit
 597         volatile TwoBytes strictField11;
 598         @NullRestricted
 599         volatile TwoBytes strictField12;
 600 
 601         public StrictFieldHolder(MyValue8 val8, MyValue8 val8NullFree, TwoBytes twoBytes, TwoBytes twoBytesNullFree) {
 602             strictField1 = val8;
 603             strictField2 = val8;
 604             strictField3 = val8NullFree;
 605             strictField4 = val8NullFree;
 606             strictField5 = val8NullFree;
 607             strictField6 = val8NullFree;
 608 
 609             strictField7 = twoBytes;
 610             strictField8 = twoBytes;
 611             strictField9 = twoBytesNullFree;
 612             strictField10 = twoBytesNullFree;
 613             strictField11 = twoBytesNullFree;
 614             strictField12 = twoBytesNullFree;
 615             super();
 616         }
 617     }
 618 
 619     @NullRestricted
 620     MyValueEmpty emptyField1;
 621     @NullRestricted
 622     volatile MyValueEmpty emptyField2;
 623     MyValueEmpty emptyField3;
 624     volatile MyValueEmpty emptyField4;
 625 
 626     static final MyValue1 VAL1 = new MyValue1((byte)42, new MyValue2((byte)43), null);
 627     static final MyValue4 VAL4 = new MyValue4(new MyValue3((byte)42), null);
 628     static final MyValue5 VAL5 = new MyValue5((byte)42, new MyValue5A((byte)43, new MyValue5B((byte)44, new MyValue5C((byte)45))));
 629     static final MyValue6 VAL6 = new MyValue6(new MyValueEmpty());
 630     static final MyValue7 VAL7 = new MyValue7(new MyValue6(new MyValueEmpty()));
 631 
 632     // Using two bytes such that null-free fields will not be naturally atomic
 633     @LooselyConsistentValue
 634     static value class TwoBytes {
 635         byte b1;
 636         byte b2;
 637 
 638         public TwoBytes(byte b1, byte b2) {
 639             this.b1 = b1;
 640             this.b2 = b2;
 641         }
 642 
 643         public static final TwoBytes DEFAULT = new TwoBytes((byte)0, (byte)0);
 644     }
 645 
 646     static private final MyValue8 CANARY_VALUE = new MyValue8((byte)42);
 647 
 648     public static class Cage1 {
 649         MyValue8 canary1 = CANARY_VALUE;
 650 
 651         @NullRestricted
 652         volatile TwoBytes field;
 653 
 654         MyValue8 canary2 = CANARY_VALUE;
 655 
 656         public Cage1() {
 657             field = TwoBytes.DEFAULT;
 658             super();
 659         }
 660 
 661         public void verify(TwoBytes val) {
 662             Asserts.assertEQ(canary1, CANARY_VALUE);
 663             Asserts.assertEQ(field, val);
 664             Asserts.assertEQ(canary2, CANARY_VALUE);
 665         }
 666     }
 667 
 668     public static class Cage2 {
 669         @NullRestricted
 670         MyValue8 canary1;
 671 
 672         @NullRestricted
 673         volatile TwoBytes field;
 674 
 675         @NullRestricted
 676         MyValue8 canary2;
 677 
 678         public Cage2() {
 679             canary1 = CANARY_VALUE;
 680             field = TwoBytes.DEFAULT;
 681             canary2 = CANARY_VALUE;
 682             super();
 683         }
 684 
 685         public void verify(TwoBytes val) {
 686             Asserts.assertEQ(canary1, CANARY_VALUE);
 687             Asserts.assertEQ(field, val);
 688             Asserts.assertEQ(canary2, CANARY_VALUE);
 689         }
 690     }
 691 
 692     public static class Cage3 {
 693         @NullRestricted
 694         MyValue8 canary1;
 695 
 696         volatile TwoBytes field;
 697 
 698         @NullRestricted
 699         MyValue8 canary2;
 700 
 701         public Cage3() {
 702             canary1 = CANARY_VALUE;
 703             canary2 = CANARY_VALUE;
 704             super();
 705         }
 706 
 707         public void verify(TwoBytes val) {
 708             Asserts.assertEQ(canary1, CANARY_VALUE);
 709             Asserts.assertEQ(field, val);
 710             Asserts.assertEQ(canary2, CANARY_VALUE);
 711         }
 712     }
 713 
 714     public static class Cage4 {
 715         MyValue8 canary1 = CANARY_VALUE;
 716 
 717         volatile TwoBytes field;
 718 
 719         MyValue8 canary2 = CANARY_VALUE;
 720 
 721         public void verify(TwoBytes val) {
 722             Asserts.assertEQ(canary1, CANARY_VALUE);
 723             Asserts.assertEQ(field, val);
 724             Asserts.assertEQ(canary2, CANARY_VALUE);
 725         }
 726     }
 727 
 728     static final Cage1 canaryCage1 = new Cage1();
 729     static final Cage2 canaryCage2 = new Cage2();
 730     static final Cage3 canaryCage3 = new Cage3();
 731     static final Cage4 canaryCage4 = new Cage4();
 732 
 733     // Check that the canary values are not accidentally overwritten
 734     public void testOutOfBoundsAccess(int i) {
 735         TwoBytes val = new TwoBytes((byte)i, (byte)(i+1));
 736         canaryCage1.field = val;
 737         canaryCage1.verify(val);
 738 
 739         canaryCage2.field = val;
 740         canaryCage2.verify(val);
 741 
 742         canaryCage3.field = val;
 743         canaryCage3.verify(val);
 744 
 745         canaryCage3.field = null;
 746         canaryCage3.verify(null);
 747 
 748         canaryCage4.field = val;
 749         canaryCage4.verify(val);
 750 
 751         canaryCage4.field = null;
 752         canaryCage4.verify(null);
 753     }
 754 
 755     // Test that the calling convention is keeping track of the null marker
 756     public MyValue1 testHelper1(MyValue1 val) {
 757         return val;
 758     }
 759 
 760     public void testSet1(MyValue1 val) {
 761         field1 = testHelper1(val);
 762     }
 763 
 764     public MyValue1 testGet1() {
 765         return field1;
 766     }
 767 
 768     public void testDeopt1(byte x, MyValue1 neverNull, MyValue1 alwaysNull, boolean deopt) {
 769         MyValue2 val2 = new MyValue2(x);
 770         MyValue1 val1 = new MyValue1(x, val2, val2);
 771         if (deopt) {
 772             Asserts.assertEQ(val1.x, x);
 773             Asserts.assertEQ(val1.val1, val2);
 774             Asserts.assertEQ(val1.val2, val2);
 775             Asserts.assertEQ(neverNull.x, x);
 776             Asserts.assertEQ(neverNull.val1, val2);
 777             Asserts.assertEQ(neverNull.val2, val2);
 778             Asserts.assertEQ(alwaysNull.x, x);
 779             Asserts.assertEQ(alwaysNull.val1, null);
 780             Asserts.assertEQ(alwaysNull.val2, null);
 781         }
 782     }
 783 
 784     public void testOSR() {
 785         // Trigger OSR
 786         for (int i = 0; i < 100_000; ++i) {
 787             field1 = null;
 788             Asserts.assertEQ(field1, null);
 789             MyValue2 val2 = new MyValue2((byte)i);
 790             MyValue1 val = new MyValue1((byte)i, val2, null);
 791             field1 = val;
 792             Asserts.assertEQ(field1.x, (byte)i);
 793             Asserts.assertEQ(field1.val1, val2);
 794             Asserts.assertEQ(field1.val2, null);
 795         }
 796     }
 797 
 798     public boolean testACmp(MyValue2 val2) {
 799         return field1.val1 == val2;
 800     }
 801 
 802     // Test that the calling convention is keeping track of the null marker
 803     public MyValue4 testHelper2(MyValue4 val) {
 804         return val;
 805     }
 806 
 807     public void testSet2(MyValue4 val) {
 808         field2 = testHelper2(val);
 809     }
 810 
 811     public MyValue4 testGet2() {
 812         return field2;
 813     }
 814 
 815     public void testDeopt2(byte x, MyValue4 neverNull, MyValue4 alwaysNull, boolean deopt) {
 816         MyValue3 val3 = new MyValue3(x);
 817         MyValue4 val4 = new MyValue4(val3, null);
 818         if (deopt) {
 819             Asserts.assertEQ(val4.val1, val3);
 820             Asserts.assertEQ(val4.val2, null);
 821             Asserts.assertEQ(neverNull.val1, val3);
 822             Asserts.assertEQ(neverNull.val2, val3);
 823             Asserts.assertEQ(alwaysNull.val1, null);
 824             Asserts.assertEQ(alwaysNull.val2, null);
 825         }
 826     }
 827 
 828     // Test that the calling convention is keeping track of the null marker
 829     public MyValue5 testHelper3(MyValue5 val) {
 830         return val;
 831     }
 832 
 833     public void testSet3(MyValue5 val) {
 834         field3 = testHelper3(val);
 835     }
 836 
 837     public MyValue5 testGet3() {
 838         return field3;
 839     }
 840 
 841     public void testDeopt3(byte x, MyValue5 val6, MyValue5 val7, MyValue5 val8, MyValue5 val9, boolean deopt) {
 842         MyValue5 val1 = new MyValue5(x, new MyValue5A(x, new MyValue5B(x, new MyValue5C(x))));
 843         MyValue5 val2 = new MyValue5(x, new MyValue5A(x, new MyValue5B(x, null)));
 844         MyValue5 val3 = new MyValue5(x, new MyValue5A(x, null));
 845         MyValue5 val4 = new MyValue5(x, null);
 846         MyValue5 val5 = null;
 847         if (deopt) {
 848             Asserts.assertEQ(val1.x, x);
 849             Asserts.assertEQ(val1.val.x, x);
 850             Asserts.assertEQ(val1.val.val.x, x);
 851             Asserts.assertEQ(val1.val.val.val.x, x);
 852             Asserts.assertEQ(val2.x, x);
 853             Asserts.assertEQ(val2.val.x, x);
 854             Asserts.assertEQ(val2.val.val.x, x);
 855             Asserts.assertEQ(val2.val.val.val, null);
 856             Asserts.assertEQ(val3.x, x);
 857             Asserts.assertEQ(val3.val.x, x);
 858             Asserts.assertEQ(val3.val.val, null);
 859             Asserts.assertEQ(val4.x, x);
 860             Asserts.assertEQ(val4.val, null);
 861             Asserts.assertEQ(val5, null);
 862 
 863             Asserts.assertEQ(val6.x, x);
 864             Asserts.assertEQ(val6.val.x, x);
 865             Asserts.assertEQ(val6.val.val.x, x);
 866             Asserts.assertEQ(val6.val.val.val.x, x);
 867             Asserts.assertEQ(val7.x, x);
 868             Asserts.assertEQ(val7.val.x, x);
 869             Asserts.assertEQ(val7.val.val.x, x);
 870             Asserts.assertEQ(val7.val.val.val, null);
 871             Asserts.assertEQ(val8.x, x);
 872             Asserts.assertEQ(val8.val.x, x);
 873             Asserts.assertEQ(val8.val.val, null);
 874             Asserts.assertEQ(val9.x, x);
 875             Asserts.assertEQ(val9.val, null);
 876         }
 877     }
 878 
 879     // Test that the calling convention is keeping track of the null marker
 880     public MyValue6 testHelper4(MyValue6 val) {
 881         return val;
 882     }
 883 
 884     public void testSet4(MyValue6 val) {
 885         field4 = testHelper4(val);
 886     }
 887 
 888     public MyValue6 testGet4() {
 889         return field4;
 890     }
 891 
 892     public void testDeopt4(MyValue6 val4, MyValue6 val5, MyValue6 val6, boolean deopt) {
 893         MyValue6 val1 = new MyValue6(new MyValueEmpty());
 894         MyValue6 val2 = new MyValue6(null);
 895         MyValue6 val3 = null;
 896         if (deopt) {
 897             Asserts.assertEQ(val1.val, new MyValueEmpty());
 898             Asserts.assertEQ(val2.val, null);
 899             Asserts.assertEQ(val3, null);
 900 
 901             Asserts.assertEQ(val4.val, new MyValueEmpty());
 902             Asserts.assertEQ(val5.val, null);
 903             Asserts.assertEQ(val6, null);
 904         }
 905     }
 906 
 907     // Test that the calling convention is keeping track of the null marker
 908     public MyValue7 testHelper5(MyValue7 val) {
 909         return val;
 910     }
 911 
 912     public void testSet5(MyValue7 val) {
 913         field5 = testHelper5(val);
 914     }
 915 
 916     public MyValue7 testGet5() {
 917         return field5;
 918     }
 919 
 920     public void testDeopt5(MyValue7 val5, MyValue7 val6, MyValue7 val7, MyValue7 val8, boolean deopt) {
 921         MyValue7 val1 = new MyValue7(new MyValue6(new MyValueEmpty()));
 922         MyValue7 val2 = new MyValue7(new MyValue6(null));
 923         MyValue7 val3 = new MyValue7(null);
 924         MyValue7 val4 = null;
 925         if (deopt) {
 926             Asserts.assertEQ(val1.val, new MyValue6(new MyValueEmpty()));
 927             Asserts.assertEQ(val2.val, new MyValue6(null));
 928             Asserts.assertEQ(val3.val, null);
 929             Asserts.assertEQ(val4, null);
 930 
 931             Asserts.assertEQ(val5.val, new MyValue6(new MyValueEmpty()));
 932             Asserts.assertEQ(val6.val, new MyValue6(null));
 933             Asserts.assertEQ(val7.val, null);
 934             Asserts.assertEQ(val8, null);
 935         }
 936     }
 937 
 938     // Make sure that flat field accesses contain a (implicit) null check
 939     public static void testNPE1() {
 940         TestFieldNullMarkers t = null;
 941         try {
 942             MyValue8 v = t.field6;
 943             throw new RuntimeException("No NPE thrown!");
 944         } catch (NullPointerException e) {
 945             // Expected
 946         }
 947     }
 948 
 949     public static void testNPE2() {
 950         TestFieldNullMarkers t = null;
 951         try {
 952             t.field6 = null;
 953             throw new RuntimeException("No NPE thrown!");
 954         } catch (NullPointerException e) {
 955             // Expected
 956         }
 957     }
 958 
 959     public void checkFields(int i) {
 960         Asserts.assertEQ(field6.b, (byte)i);
 961         Asserts.assertEQ(field7.s, (short)i);
 962         Asserts.assertEQ(field8.i, i);
 963         Asserts.assertEQ(field9.f, (float)i);
 964         Asserts.assertEQ(field10.c, (char)i);
 965         Asserts.assertEQ(field11.b, (i % 2) == 0);
 966     }
 967 
 968     // Test that writing and reading a (signed) byte stays in bounds
 969     public void testBounds(int i) {
 970         MyValue8 val = new MyValue8((byte)i);
 971         field6 = val;
 972         int b = field6.b;
 973         if (b < -128 || b > 127) {
 974             throw new RuntimeException("Byte value out of bounds: " + b);
 975         }
 976     }
 977 
 978     static void produceGarbage() {
 979         for (int i = 0; i < 100; ++i) {
 980             Object[] arrays = new Object[1024];
 981             for (int j = 0; j < arrays.length; j++) {
 982                 arrays[j] = new int[1024];
 983             }
 984         }
 985         System.gc();
 986     }
 987 
 988     // Test that barriers are emitted when writing flat, atomic fields with oops
 989     public void testWriteOopFields1(MyValue15 val) {
 990         field17 = val;
 991         field18 = val;
 992     }
 993 
 994     public void testWriteOopFields2(MyValue16 val) {
 995         field19 = val;
 996     }
 997 
 998     public void testWriteOopFields3(MyValue17 val) {
 999         field20 = val;
1000         field21 = val;
1001     }
1002 
1003     public static class MyHolderClass9 {
1004         @NullRestricted
1005         TwoBytes field1;
1006 
1007         TwoBytes field2;
1008 
1009         @NullRestricted
1010         volatile TwoBytes field3;
1011 
1012         volatile TwoBytes field4;
1013 
1014         public MyHolderClass9() {
1015             field1 = TwoBytes.DEFAULT;
1016             field3 = TwoBytes.DEFAULT;
1017             super();
1018         }
1019     }
1020 
1021     static final MyHolderClass9 constantHolder = new MyHolderClass9();
1022 
1023     // Test loading a flat field from a constant container (should not be constant folded because fields are immutable)
1024     public void testLoadingFromConstantHolder(int i) {
1025         TwoBytes val = new TwoBytes((byte)i, (byte)(i + 1));
1026         constantHolder.field1 = val;
1027         Asserts.assertEQ(constantHolder.field1, val);
1028 
1029         constantHolder.field2 = val;
1030         Asserts.assertEQ(constantHolder.field2, val);
1031 
1032         constantHolder.field2 = null;
1033         Asserts.assertEQ(constantHolder.field2, null);
1034 
1035         constantHolder.field3 = val;
1036         Asserts.assertEQ(constantHolder.field3, val);
1037 
1038         constantHolder.field4 = val;
1039         Asserts.assertEQ(constantHolder.field4, val);
1040 
1041         constantHolder.field4 = null;
1042         Asserts.assertEQ(constantHolder.field4, null);
1043     }
1044 
1045     public void testStrictFields(StrictFieldHolder holder, MyValue8 val8, MyValue8 val8NullFree, TwoBytes twoBytes, TwoBytes twoBytesNullFree) {
1046         Asserts.assertEQ(holder.strictField1, val8);
1047         Asserts.assertEQ(holder.strictField2, val8);
1048         Asserts.assertEQ(holder.strictField3, val8NullFree);
1049         Asserts.assertEQ(holder.strictField4, val8NullFree);
1050         Asserts.assertEQ(holder.strictField5, val8NullFree);
1051         Asserts.assertEQ(holder.strictField6, val8NullFree);
1052 
1053         Asserts.assertEQ(holder.strictField7, twoBytes);
1054         Asserts.assertEQ(holder.strictField8, twoBytes);
1055         Asserts.assertEQ(holder.strictField9, twoBytesNullFree);
1056         Asserts.assertEQ(holder.strictField10, twoBytesNullFree);
1057         Asserts.assertEQ(holder.strictField11, twoBytesNullFree);
1058         Asserts.assertEQ(holder.strictField12, twoBytesNullFree);
1059     }
1060 
1061     public static void main(String[] args) {
1062         TestFieldNullMarkers t = new TestFieldNullMarkers();
1063         t.testOSR();
1064 
1065         final int LIMIT = 50_000;
1066         for (int i = -50_000; i < LIMIT; ++i) {
1067             t.field1 = null;
1068             Asserts.assertEQ(t.testGet1(), null);
1069 
1070             boolean useNull = (i % 2) == 0;
1071             MyValue2 val2 = useNull ? null : new MyValue2((byte)i);
1072             MyValue1 val = new MyValue1((byte)i, val2, val2);
1073             t.field1 = val;
1074             Asserts.assertEQ(t.testGet1().x, val.x);
1075             Asserts.assertEQ(t.testGet1().val1, val2);
1076             Asserts.assertEQ(t.testGet1().val2, val2);
1077 
1078             Asserts.assertTrue(t.testACmp(val2));
1079 
1080             t.testSet1(null);
1081             Asserts.assertEQ(t.field1, null);
1082 
1083             t.testSet1(val);
1084             Asserts.assertEQ(t.field1.x, val.x);
1085             Asserts.assertEQ(t.field1.val1, val2);
1086             Asserts.assertEQ(t.field1.val2, val2);
1087 
1088             t.testDeopt1((byte)i, null, null, false);
1089 
1090             t.field2 = null;
1091             Asserts.assertEQ(t.testGet2(), null);
1092 
1093             MyValue3 val3 = useNull ? null : new MyValue3((byte)i);
1094             MyValue4 val4 = new MyValue4(val3, val3);
1095             t.field2 = val4;
1096             Asserts.assertEQ(t.testGet2().val1, val3);
1097             Asserts.assertEQ(t.testGet2().val2, val3);
1098 
1099             t.testSet2(null);
1100             Asserts.assertEQ(t.testGet2(), null);
1101 
1102             t.testSet2(val4);
1103             Asserts.assertEQ(t.testGet2().val1, val3);
1104             Asserts.assertEQ(t.testGet2().val2, val3);
1105 
1106             t.testDeopt2((byte)i, null, null, false);
1107 
1108             t.field3 = null;
1109             Asserts.assertEQ(t.testGet3(), null);
1110 
1111             boolean useNull_1 = (i % 4) == 0;
1112             boolean useNull_2 = (i % 4) == 1;
1113             boolean useNull_3 = (i % 4) == 2;
1114             MyValue5C val5_3 = useNull_3 ? null : new MyValue5C((byte)i);
1115             MyValue5B val5_2 = useNull_2 ? null : new MyValue5B((byte)i, val5_3);
1116             MyValue5A val5_1 = useNull_1 ? null : new MyValue5A((byte)i, val5_2);
1117             MyValue5 val5 = new MyValue5((byte)i, val5_1);
1118             t.field3 = val5;
1119             Asserts.assertEQ(t.testGet3().x, val5.x);
1120             if (useNull_1) {
1121                 Asserts.assertEQ(t.testGet3().val, null);
1122             } else {
1123                 Asserts.assertEQ(t.testGet3().val.x, val5_1.x);
1124                 if (useNull_2) {
1125                     Asserts.assertEQ(t.testGet3().val.val, null);
1126                 } else {
1127                     Asserts.assertEQ(t.testGet3().val.val.x, val5_2.x);
1128                     if (useNull_3) {
1129                         Asserts.assertEQ(t.testGet3().val.val.val, null);
1130                     } else {
1131                         Asserts.assertEQ(t.testGet3().val.val.val.x, val5_3.x);
1132                     }
1133                 }
1134             }
1135 
1136             t.testSet3(null);
1137             Asserts.assertEQ(t.field3, null);
1138 
1139             t.testSet3(val5);
1140             Asserts.assertEQ(t.testGet3().x, val5.x);
1141             if (useNull_1) {
1142                 Asserts.assertEQ(t.testGet3().val, null);
1143             } else {
1144                 Asserts.assertEQ(t.testGet3().val.x, val5_1.x);
1145                 if (useNull_2) {
1146                     Asserts.assertEQ(t.testGet3().val.val, null);
1147                 } else {
1148                     Asserts.assertEQ(t.testGet3().val.val.x, val5_2.x);
1149                     if (useNull_3) {
1150                         Asserts.assertEQ(t.testGet3().val.val.val, null);
1151                     } else {
1152                         Asserts.assertEQ(t.testGet3().val.val.val.x, val5_3.x);
1153                     }
1154                 }
1155             }
1156             t.testDeopt3((byte)i, null, null, null, null, false);
1157 
1158             t.field4 = null;
1159             Asserts.assertEQ(t.testGet4(), null);
1160 
1161             MyValueEmpty empty = useNull ? null : new MyValueEmpty();
1162             MyValue6 val6 = new MyValue6(empty);
1163             t.field4 = val6;
1164             Asserts.assertEQ(t.testGet4().val, empty);
1165 
1166             t.testSet4(null);
1167             Asserts.assertEQ(t.testGet4(), null);
1168 
1169             t.testSet4(val6);
1170             Asserts.assertEQ(t.testGet4().val, empty);
1171 
1172             t.testDeopt4(null, null, null, false);
1173 
1174             t.field5 = null;
1175             Asserts.assertEQ(t.testGet5(), null);
1176 
1177             empty = ((i % 3) == 0) ? null : new MyValueEmpty();
1178             val6 = ((i % 3) == 1) ? null : new MyValue6(empty);
1179             MyValue7 val7 = new MyValue7(val6);
1180             t.field5 = val7;
1181             Asserts.assertEQ(t.testGet5().val, val6);
1182 
1183             t.testSet5(null);
1184             Asserts.assertEQ(t.testGet5(), null);
1185 
1186             t.testSet5(val7);
1187             Asserts.assertEQ(t.testGet5().val, val6);
1188 
1189             t.testDeopt5(null, null, null, null, false);
1190 
1191             // Check accesses with constant value
1192             t.field1 = VAL1;
1193             Asserts.assertEQ(t.field1.x, VAL1.x);
1194             Asserts.assertEQ(t.field1.val1, VAL1.val1);
1195             Asserts.assertEQ(t.field1.val2, VAL1.val2);
1196 
1197             t.field2 = VAL4;
1198             Asserts.assertEQ(t.field2.val1, VAL4.val1);
1199             Asserts.assertEQ(t.field2.val2, VAL4.val2);
1200 
1201             t.field3 = VAL5;
1202             Asserts.assertEQ(t.field3.x, VAL5.x);
1203             Asserts.assertEQ(t.field3.val.x, VAL5.val.x);
1204             Asserts.assertEQ(t.field3.val.val.x, VAL5.val.val.x);
1205             Asserts.assertEQ(t.field3.val.val.val.x, VAL5.val.val.val.x);
1206 
1207             t.field4 = VAL6;
1208             Asserts.assertEQ(t.field4.val, VAL6.val);
1209 
1210             t.field5 = VAL7;
1211             Asserts.assertEQ(t.field5.val, VAL7.val);
1212 
1213             // Some more values classes with different flavors of primitive fields
1214             t.field6 = null;
1215             Asserts.assertEQ(t.field6, null);
1216             t.field6 = new MyValue8((byte)i);
1217             Asserts.assertEQ(t.field6.b, (byte)i);
1218             t.field7 = null;
1219             Asserts.assertEQ(t.field7, null);
1220             t.field7 = new MyValue9((short)i);
1221             Asserts.assertEQ(t.field7.s, (short)i);
1222             t.field8 = null;
1223             Asserts.assertEQ(t.field8, null);
1224             t.field8 = new MyValue10(i);
1225             Asserts.assertEQ(t.field8.i, i);
1226             t.field9 = null;
1227             Asserts.assertEQ(t.field9, null);
1228             t.field9 = new MyValue11((float)i);
1229             Asserts.assertEQ(t.field9.f, (float)i);
1230             t.field10 = null;
1231             Asserts.assertEQ(t.field10, null);
1232             t.field10 = new MyValue12((char)i);
1233             Asserts.assertEQ(t.field10.c, (char)i);
1234             t.field11 = null;
1235             Asserts.assertEQ(t.field11, null);
1236             t.field11 = new MyValue13((i % 2) == 0);
1237             Asserts.assertEQ(t.field11.b, (i % 2) == 0);
1238 
1239             // Write the fields again and check that we don't overwrite other fields
1240             t.checkFields(i);
1241             t.field6 = new MyValue8((byte)i);
1242             t.checkFields(i);
1243             t.field7 = new MyValue9((short)i);
1244             t.checkFields(i);
1245             t.field8 = new MyValue10(i);
1246             t.checkFields(i);
1247             t.field9 = new MyValue11((float)i);
1248             t.checkFields(i);
1249             t.field10 = new MyValue12((char)i);
1250             t.checkFields(i);
1251             t.field11 = new MyValue13((i % 2) == 0);
1252             t.checkFields(i);
1253 
1254             testNPE1();
1255             testNPE2();
1256 
1257             t.testBounds(i);
1258 
1259             // Null-free, flat, atomic
1260             MyValue8 val8 = new MyValue8((byte)i);
1261             t.field12 = val8;
1262             Asserts.assertEQ(t.field12.b, (byte)i);
1263 
1264             try {
1265                 t.field12 = null;
1266                 throw new RuntimeException("No NPE thrown");
1267             } catch (NullPointerException npe) {
1268                 // Expected
1269             }
1270 
1271             // Null-free, flat with both nullable and null-free fields
1272             t.field13 = new MyValue14(val8, val8);
1273             Asserts.assertEQ(t.field13.nullfree, val8);
1274             Asserts.assertEQ(t.field13.nullable, val8);
1275 
1276             t.field13 = new MyValue14(val8, null);
1277             Asserts.assertEQ(t.field13.nullfree, val8);
1278             Asserts.assertEQ(t.field13.nullable, null);
1279 
1280             try {
1281                 t.field13 = new MyValue14(null, null);
1282                 throw new RuntimeException("No NPE thrown");
1283             } catch (NullPointerException npe) {
1284                 // Expected
1285             }
1286             try {
1287                 t.field13 = null;
1288                 throw new RuntimeException("No NPE thrown");
1289             } catch (NullPointerException npe) {
1290                 // Expected
1291             }
1292 
1293             // Nullable, atomic, flat with both nullable and null-free fields
1294             t.field14 = null;
1295             Asserts.assertEQ(t.field14, null);
1296 
1297             t.field14 = new MyValue14(val8, val8);
1298             Asserts.assertEQ(t.field14.nullfree, val8);
1299             Asserts.assertEQ(t.field14.nullable, val8);
1300 
1301             t.field14 = new MyValue14(val8, null);
1302             Asserts.assertEQ(t.field14.nullfree, val8);
1303             Asserts.assertEQ(t.field14.nullable, null);
1304 
1305             try {
1306                 t.field14 = new MyValue14(null, null);
1307                 throw new RuntimeException("No NPE thrown");
1308             } catch (NullPointerException npe) {
1309                 // Expected
1310             }
1311 
1312             // Nullable, (atomic), flat with both nullable and null-free fields
1313             t.field15 = null;
1314             Asserts.assertEQ(t.field15, null);
1315 
1316             t.field15 = new MyValue14(val8, val8);
1317             Asserts.assertEQ(t.field15.nullfree, val8);
1318             Asserts.assertEQ(t.field15.nullable, val8);
1319 
1320             t.field15 = new MyValue14(val8, null);
1321             Asserts.assertEQ(t.field15.nullfree, val8);
1322             Asserts.assertEQ(t.field15.nullable, null);
1323 
1324             try {
1325                 t.field15 = new MyValue14(null, null);
1326                 throw new RuntimeException("No NPE thrown");
1327             } catch (NullPointerException npe) {
1328                 // Expected
1329             }
1330 
1331             // Null-free, atomic, flat with both nullable and null-free fields
1332             t.field16 = new MyValue14(val8, val8);
1333             Asserts.assertEQ(t.field16.nullfree, val8);
1334             Asserts.assertEQ(t.field16.nullable, val8);
1335 
1336             t.field16 = new MyValue14(val8, null);
1337             Asserts.assertEQ(t.field16.nullfree, val8);
1338             Asserts.assertEQ(t.field16.nullable, null);
1339 
1340             try {
1341                 t.field16 = new MyValue14(null, null);
1342                 throw new RuntimeException("No NPE thrown");
1343             } catch (NullPointerException npe) {
1344                 // Expected
1345             }
1346             try {
1347                 t.field16 = null;
1348                 throw new RuntimeException("No NPE thrown");
1349             } catch (NullPointerException npe) {
1350                 // Expected
1351             }
1352 
1353             MyValue15 val15 = new MyValue15(new MyClass(i));
1354             t.testWriteOopFields1(val15);
1355             if (i > (LIMIT - 50)) {
1356                 // After warmup, produce some garbage to trigger GC
1357                 produceGarbage();
1358             }
1359             Asserts.assertEQ(t.field17.obj.x, i);
1360             Asserts.assertEQ(t.field18.obj.x, i);
1361 
1362             MyValue16 val16 = new MyValue16(new MyClass(i), new MyClass(i));
1363             t.testWriteOopFields2(val16);
1364             if (i > (LIMIT - 50)) {
1365                 // After warmup, produce some garbage to trigger GC
1366                 produceGarbage();
1367             }
1368             Asserts.assertEQ(t.field19.obj1.x, i);
1369             Asserts.assertEQ(t.field19.obj2.x, i);
1370 
1371             MyValue17 val17 = new MyValue17(new MyClass(i), (byte)i, (byte)i);
1372             t.testWriteOopFields3(val17);
1373             if (i > (LIMIT - 50)) {
1374                 // After warmup, produce some garbage to trigger GC
1375                 produceGarbage();
1376             }
1377             Asserts.assertEQ(t.field20.obj.x, i);
1378             Asserts.assertEQ(t.field20.b1, (byte)i);
1379             Asserts.assertEQ(t.field20.b2, (byte)i);
1380             Asserts.assertEQ(t.field21.obj.x, i);
1381             Asserts.assertEQ(t.field21.b1, (byte)i);
1382             Asserts.assertEQ(t.field21.b2, (byte)i);
1383 
1384             Asserts.assertEQ(t.emptyField1, new MyValueEmpty());
1385             Asserts.assertEQ(t.emptyField2, new MyValueEmpty());
1386 
1387             // Test empty fields
1388             t.emptyField3 = new MyValueEmpty();
1389             t.emptyField4 = new MyValueEmpty();
1390             Asserts.assertEQ(t.emptyField3, new MyValueEmpty());
1391             Asserts.assertEQ(t.emptyField4, new MyValueEmpty());
1392             t.emptyField3 = null;
1393             t.emptyField4 = null;
1394             Asserts.assertEQ(t.emptyField3, null);
1395             Asserts.assertEQ(t.emptyField4, null);
1396 
1397             t.testLoadingFromConstantHolder(i);
1398 
1399             // Verify that no out of bounds accesses happen
1400             t.testOutOfBoundsAccess(i);
1401 
1402             // Test strict fields
1403             TwoBytes twoBytes = new TwoBytes((byte)i, (byte)(i + 1));
1404             t.testStrictFields(new StrictFieldHolder(val8, val8, twoBytes, twoBytes), val8, val8, twoBytes, twoBytes);
1405             t.testStrictFields(new StrictFieldHolder(null, val8, null, twoBytes), null, val8, null, twoBytes);
1406         }
1407 
1408         // Trigger deoptimization to check that re-materialization takes the null marker into account
1409         byte x = (byte)42;
1410         t.testDeopt1(x, new MyValue1(x, new MyValue2(x), new MyValue2(x)), new MyValue1(x, null, null), true);
1411         t.testDeopt2(x, new MyValue4(new MyValue3(x), new MyValue3(x)), new MyValue4(null, null), true);
1412 
1413         MyValue5 val1 = new MyValue5(x, new MyValue5A(x, new MyValue5B(x, new MyValue5C(x))));
1414         MyValue5 val2 = new MyValue5(x, new MyValue5A(x, new MyValue5B(x, null)));
1415         MyValue5 val3 = new MyValue5(x, new MyValue5A(x, null));
1416         MyValue5 val4 = new MyValue5(x, null);
1417         t.testDeopt3(x, val1, val2, val3, val4, true);
1418 
1419         MyValue6 val5 = new MyValue6(new MyValueEmpty());
1420         MyValue6 val6 = new MyValue6(null);
1421         MyValue6 val7 = null;
1422         t.testDeopt4(val5, val6, val7, true);
1423 
1424         MyValue7 val8 = new MyValue7(new MyValue6(new MyValueEmpty()));
1425         MyValue7 val9 = new MyValue7(new MyValue6(null));
1426         MyValue7 val10 = new MyValue7(null);
1427         MyValue7 val11 = null;
1428         t.testDeopt5(val8, val9, val10, val11, false);
1429     }
1430 }
1431