1 /*
  2  * Copyright (c) 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 /*
 30  * @test
 31  * @summary Test loads from a dead InlineTypeNode with top field values.
 32  * @bug 8384202
 33  * @requires vm.compiler2.enabled
 34  * @requires (vm.opt.PreloadClasses == null | vm.opt.PreloadClasses == "true")
 35  * @enablePreview
 36  * @modules java.base/jdk.internal.vm.annotation
 37  * @run main ${test.main.class}
 38  * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+IgnoreUnrecognizedVMOptions
 39  *                   -XX:+StressIGVN -XX:StressSeed=8 -XX:+AlwaysIncrementalInline
 40  *                   ${test.main.class}
 41  */
 42 public value class TestDeadInlineTypeFieldOffset {
 43     MyValue valueField1;
 44     @NullRestricted
 45     MyValue valueField2;
 46 
 47     TestDeadInlineTypeFieldOffset(MyValue valueField1, MyValue valueField2) {
 48         this.valueField1 = valueField1;
 49         this.valueField2 = valueField2;
 50     }
 51 
 52     TestDeadInlineTypeFieldOffset test1() {
 53         return new TestDeadInlineTypeFieldOffset(null, valueField2);
 54     }
 55 
 56     TestDeadInlineTypeFieldOffset test2() {
 57         return new TestDeadInlineTypeFieldOffset(valueField1, null);
 58     }
 59 
 60     @LooselyConsistentValue
 61     static value class NestedValue {
 62         int x;
 63         int y;
 64 
 65         NestedValue(int x, int y) {
 66             this.x = x;
 67             this.y = y;
 68         }
 69     }
 70 
 71     @LooselyConsistentValue
 72     static value class MyValue {
 73         NestedValue v1;
 74         @NullRestricted
 75         NestedValue v2;
 76 
 77         MyValue(NestedValue v1, NestedValue v2) {
 78             this.v1 = v1;
 79             this.v2 = v2;
 80         }
 81     }
 82 
 83     static TestDeadInlineTypeFieldOffset test(TestDeadInlineTypeFieldOffset vt) {
 84         vt = vt.test1();
 85         try {
 86             vt = vt.test2();
 87             throw new RuntimeException();
 88         } catch (NullPointerException e) {
 89             // Expected.
 90         }
 91         return vt;
 92     }
 93 
 94     public static void main(String[] args) {
 95         MyValue val = new MyValue(null, new NestedValue(5, 6));
 96         TestDeadInlineTypeFieldOffset vt = new TestDeadInlineTypeFieldOffset(null, val);
 97         for (int i = 0; i < 10_000; ++i) {
 98             vt = test(vt);
 99         }
100     }
101 }
102