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 /*
25 * @test
26 * @bug 8372700
27 * @summary Check stable flat array field folding
28 * @library /test/lib /
29 * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
30 * @build jdk.test.whitebox.WhiteBox
31 * @enablePreview
32 * @modules java.base/jdk.internal.value
33 * java.base/jdk.internal.vm.annotation
34 * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
35 * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI compiler.c2.irTests.stable.StableFlatArrayTest
36 */
37
38 package compiler.c2.irTests.stable;
39
40 import compiler.lib.ir_framework.*;
41 import compiler.valhalla.inlinetypes.*;
42 import jdk.internal.value.ValueClass;
43 import jdk.internal.vm.annotation.Stable;
44 import jdk.test.lib.Asserts;
45
46 public class StableFlatArrayTest {
47 public static void main(String[] args) {
48 TestFramework tf = new TestFramework();
49 tf.addTestClassesToBootClassPath();
50 tf.addFlags(
51 "--enable-preview",
52 "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"
53 )
54 .start();
55 }
56
57 static final Integer[] NULL_RESTRICTED_NON_ATOMIC_ARRAY = (Integer[]) ValueClass.newNullRestrictedNonAtomicArray(Integer.class, 1, 42);
58 static final Integer[] NULL_RESTRICTED_ATOMIC_ARRAY = (Integer[]) ValueClass.newNullRestrictedAtomicArray(Integer.class, 1, 43);
59 static final Integer[] NULLABLE_ATOMIC_ARRAY = (Integer[]) ValueClass.newNullableAtomicArray(Integer.class, 1);
60 static {
61 NULLABLE_ATOMIC_ARRAY[0] = 44;
62 }
63
64 static final int NULL_RESTRICTED_NON_ATOMIC_CASE = 1;
65 static final int NULL_RESTRICTED_ATOMIC_CASE = 2;
66 static final int NULLABLE_ATOMIC_CASE = 3;
67
68 static class Carrier {
69 @Stable
70 Integer[] field;
71
72 @ForceInline
73 public Carrier(int initLevel) {
74 switch (initLevel) {
75 case NULL_RESTRICTED_NON_ATOMIC_CASE:
76 field = NULL_RESTRICTED_NON_ATOMIC_ARRAY;
77 break;
78 case NULL_RESTRICTED_ATOMIC_CASE:
79 field = NULL_RESTRICTED_ATOMIC_ARRAY;
80 break;
81 case NULLABLE_ATOMIC_CASE:
82 field = NULLABLE_ATOMIC_ARRAY;
83 break;
84 default:
85 throw new IllegalStateException("Unknown level");
86 }
87 }
88 }
89
90 static final Carrier NULL_RESTRICTED_NON_ATOMIC_CARRIER = new Carrier(NULL_RESTRICTED_NON_ATOMIC_CASE);
91 static final Carrier NULL_RESTRICTED_ATOMIC_CARRIER = new Carrier(NULL_RESTRICTED_ATOMIC_CASE);
92 static final Carrier NULLABLE_ATOMIC_CARRIER = new Carrier(NULLABLE_ATOMIC_CASE);
93
94 @Test
95 @IR(failOn = {IRNode.LOAD, IRNode.MEMBAR})
96 static int testNullRestrictedNonAtomic() {
97 Integer[] is = NULL_RESTRICTED_NON_ATOMIC_CARRIER.field;
98 if (is != null) {
99 Integer i = is[0];
100 if (i != null) {
101 return i;
102 }
103 }
104 return 0;
105 }
106
107 @Run(test = "testNullRestrictedNonAtomic")
108 public void testNullRestrictedNonAtomic_verifier() {
109 int result = testNullRestrictedNonAtomic();
110 Asserts.assertEquals(result, 42);
111 }
112
113 @Test
114 @IR(failOn = {IRNode.LOAD, IRNode.MEMBAR})
115 static int testNullRestrictedAtomic() {
116 Integer[] is = NULL_RESTRICTED_ATOMIC_CARRIER.field;
117 if (is != null) {
118 Integer i = is[0];
119 if (i != null) {
120 return i;
121 }
122 }
123 return 0;
124 }
125
126 @Run(test = "testNullRestrictedAtomic")
127 public void testNullRestrictedAtomic_verifier() {
128 int result = testNullRestrictedAtomic();
129 Asserts.assertEquals(result, 43);
130 }
131
132 @Test
133 @IR(failOn = {IRNode.LOAD, IRNode.MEMBAR})
134 static int testNullableAtomic() {
135 Integer[] is = NULLABLE_ATOMIC_CARRIER.field;
136 if (is != null) {
137 Integer i = is[0];
138 if (i != null) {
139 return i;
140 }
141 }
142 return 0;
143 }
144
145 @Run(test = "testNullableAtomic")
146 public void testNullableAtomic_verifier() {
147 int result = testNullableAtomic();
148 Asserts.assertEquals(result, 44);
149 }
150 }