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