1 /*
  2  * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
  3  * Copyright (c) 2017, 2023, Red Hat, Inc. All rights reserved.
  4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  5  *
  6  * This code is free software; you can redistribute it and/or modify it
  7  * under the terms of the GNU General Public License version 2 only, as
  8  * published by the Free Software Foundation.
  9  *
 10  * This code is distributed in the hope that it will be useful, but WITHOUT
 11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 13  * version 2 for more details (a copy is included in the LICENSE file that
 14  * accompanied this code).
 15  *
 16  * You should have received a copy of the GNU General Public License version
 17  * 2 along with this work; if not, write to the Free Software Foundation,
 18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 19  *
 20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 21  * or visit www.oracle.com if you need additional information or have any
 22  * questions.
 23  */
 24 
 25 /**
 26  * @test
 27  * @bug 8182997 8214898
 28  * @library /test/lib
 29  * @summary Test the handling of arrays of unloaded value classes.
 30  * @enablePreview
 31  * @modules java.base/jdk.internal.value
 32  *          java.base/jdk.internal.vm.annotation
 33  * @run main/othervm -Xcomp
 34  *                   -XX:CompileCommand=compileonly,TestUnloadedInlineTypeArray::test*
 35  *                   TestUnloadedInlineTypeArray
 36  * @run main/othervm -Xcomp -XX:-UseArrayFlattening
 37  *                   -XX:CompileCommand=compileonly,TestUnloadedInlineTypeArray::test*
 38  *                   TestUnloadedInlineTypeArray
 39  * @run main/othervm -Xcomp
 40  *                   TestUnloadedInlineTypeArray
 41  * @run main/othervm -Xcomp -XX:-UseArrayFlattening
 42  *                   TestUnloadedInlineTypeArray
 43  * @run main/othervm -Xcomp -XX:-TieredCompilation
 44  *                   -XX:CompileCommand=compileonly,TestUnloadedInlineTypeArray::test*
 45  *                   TestUnloadedInlineTypeArray
 46  * @run main/othervm -Xcomp -XX:-TieredCompilation -XX:-UseArrayFlattening
 47  *                   -XX:CompileCommand=compileonly,TestUnloadedInlineTypeArray::test*
 48  *                   TestUnloadedInlineTypeArray
 49  * @run main/othervm -Xcomp -XX:-TieredCompilation
 50  *                   TestUnloadedInlineTypeArray
 51  * @run main/othervm -Xcomp -XX:-TieredCompilation -XX:-UseArrayFlattening
 52  *                   TestUnloadedInlineTypeArray
 53  */
 54 
 55 import jdk.test.lib.Asserts;
 56 
 57 import jdk.internal.value.ValueClass;
 58 import jdk.internal.vm.annotation.LooselyConsistentValue;
 59 
 60 @LooselyConsistentValue
 61 value class MyValue1 {
 62     int foo;
 63 
 64     private MyValue1() {
 65         foo = 0x42;
 66     }
 67 }
 68 
 69 @LooselyConsistentValue
 70 value class MyValue2 {
 71     int foo;
 72 
 73     public MyValue2(int n) {
 74         foo = n;
 75     }
 76 }
 77 
 78 @LooselyConsistentValue
 79 value class MyValue3 {
 80     int foo;
 81 
 82     public MyValue3(int n) {
 83         foo = n;
 84     }
 85 }
 86 
 87 @LooselyConsistentValue
 88 value class MyValue4 {
 89     int foo;
 90 
 91     public MyValue4(int n) {
 92         foo = n;
 93     }
 94 }
 95 
 96 @LooselyConsistentValue
 97 value class MyValue5 {
 98     int foo;
 99 
100     public MyValue5(int n) {
101         foo = n;
102     }
103 }
104 
105 @LooselyConsistentValue
106 value class MyValue6 {
107     int foo;
108 
109     public MyValue6(int n) {
110         foo = n;
111     }
112 
113     public MyValue6(MyValue6 v, MyValue6[] dummy) {
114         foo = v.foo + 1;
115     }
116 }
117 
118 @LooselyConsistentValue
119 value class MyValue7 {
120     int foo;
121 
122     public MyValue7(int n) {
123         foo = n;
124     }
125 }
126 
127 @LooselyConsistentValue
128 value class MyValue8 {
129     int foo = 123;
130     static {
131         TestUnloadedInlineTypeArray.MyValue8_inited = true;
132     }
133 }
134 
135 @LooselyConsistentValue
136 value class MyValue9 {
137     int foo = 123;
138     static {
139         TestUnloadedInlineTypeArray.MyValue9_inited = true;
140     }
141 }
142 
143 @LooselyConsistentValue
144 value class MyValue10 {
145     int foo = 42;
146 }
147 
148 @LooselyConsistentValue
149 value class MyValue11 {
150     int foo = 42;
151 }
152 
153 public class TestUnloadedInlineTypeArray {
154     static boolean MyValue8_inited = false;
155     static boolean MyValue9_inited = false;
156 
157     static MyValue1[] target1() {
158         return (MyValue1[])ValueClass.newNullableAtomicArray(MyValue1.class, 10);
159     }
160 
161     static void test1() {
162         target1();
163     }
164 
165     static MyValue1[] target1Nullable() {
166         return new MyValue1[10];
167     }
168 
169     static void test1Nullable() {
170         target1Nullable();
171     }
172 
173     static int test2(MyValue2[] arr) {
174         if (arr != null) {
175             return arr[1].foo;
176         } else {
177             return 1234;
178         }
179     }
180 
181     static void verifyTest2() {
182         int n = 50000;
183 
184         int m = 9999;
185         for (int i = 0; i < n; i++) {
186             m = test2(null);
187         }
188         Asserts.assertEQ(m, 1234);
189 
190         MyValue2[] arr = (MyValue2[])ValueClass.newNullableAtomicArray(MyValue2.class, 2);
191         arr[1] = new MyValue2(5678);
192         m = 9999;
193         for (int i = 0; i < n; i++) {
194             m = test2(arr);
195         }
196         Asserts.assertEQ(m, 5678);
197     }
198 
199     static int test2Nullable(MyValue2[] arr) {
200         if (arr != null) {
201             return arr[1].foo;
202         } else {
203             return 1234;
204         }
205     }
206 
207     static void verifyTest2Nullable() {
208         int n = 50000;
209 
210         int m = 9999;
211         for (int i = 0; i < n; i++) {
212             m = test2Nullable(null);
213         }
214         Asserts.assertEQ(m, 1234);
215 
216         MyValue2[] arr = new MyValue2[2];
217         arr[1] = new MyValue2(5678);
218         m = 9999;
219         for (int i = 0; i < n; i++) {
220             m = test2Nullable(arr);
221         }
222         Asserts.assertEQ(m, 5678);
223     }
224 
225     static void test3(MyValue3[] arr) {
226         if (arr != null) {
227             arr[1] = new MyValue3(2345);
228         }
229     }
230 
231     static void verifyTest3() {
232         int n = 50000;
233 
234         for (int i = 0; i < n; i++) {
235             test3(null);
236         }
237 
238         MyValue3[] arr = (MyValue3[])ValueClass.newNullableAtomicArray(MyValue3.class, 2);
239         for (int i = 0; i < n; i++) {
240             test3(arr);
241         }
242         Asserts.assertEQ(arr[1].foo, 2345);
243     }
244 
245     static void test3Nullable(MyValue3[] arr) {
246         if (arr != null) {
247             arr[0] = null;
248             arr[1] = new MyValue3(2345);
249         }
250     }
251 
252     static void verifyTest3Nullable() {
253         int n = 50000;
254 
255         for (int i = 0; i < n; i++) {
256             test3Nullable(null);
257         }
258 
259         MyValue3[] arr = new MyValue3[2];
260         for (int i = 0; i < n; i++) {
261             test3Nullable(arr);
262         }
263         Asserts.assertEQ(arr[0], null);
264         Asserts.assertEQ(arr[1].foo, 2345);
265     }
266 
267     static MyValue4[] test4(boolean b) {
268         // range check elimination
269         if (b) {
270             MyValue4[] arr = (MyValue4[])ValueClass.newNullableAtomicArray(MyValue4.class, 10);
271             arr[1] = new MyValue4(2345);
272             return arr;
273         } else {
274             return null;
275         }
276     }
277 
278     static void verifyTest4() {
279         int n = 50000;
280 
281         for (int i = 0; i < n; i++) {
282             test4(false);
283         }
284 
285         MyValue4[] arr = null;
286         for (int i = 0; i < n; i++) {
287             arr = test4(true);
288         }
289         Asserts.assertEQ(arr[1].foo, 2345);
290     }
291 
292     static MyValue4[] test4Nullable(boolean b) {
293         // range check elimination
294         if (b) {
295             MyValue4[] arr = new MyValue4[10];
296             arr[0] = null;
297             arr[1] = new MyValue4(2345);
298             return arr;
299         } else {
300             return null;
301         }
302     }
303 
304     static void verifyTest4Nullable() {
305         int n = 50000;
306 
307         for (int i = 0; i < n; i++) {
308             test4Nullable(false);
309         }
310 
311         MyValue4[] arr = null;
312         for (int i = 0; i < n; i++) {
313             arr = test4Nullable(true);
314         }
315         Asserts.assertEQ(arr[0], null);
316         Asserts.assertEQ(arr[1].foo, 2345);
317         arr[3] = null;
318     }
319 
320     static Object[] test5(int n) {
321         if (n == 0) {
322             return null;
323         } else if (n == 1) {
324             MyValue5[] arr = (MyValue5[])ValueClass.newNullableAtomicArray(MyValue5.class, 10);
325             arr[1] = new MyValue5(12345);
326             return arr;
327         } else {
328             MyValue5[] arr = new MyValue5[10];
329             arr[1] = new MyValue5(22345);
330             return arr;
331         }
332     }
333 
334     static void verifyTest5() {
335         int n = 50000;
336 
337         for (int i = 0; i < n; i++) {
338             test5(0);
339         }
340 
341         {
342             MyValue5[] arr = null;
343             for (int i = 0; i < n; i++) {
344                 arr = (MyValue5[])test5(1);
345             }
346             Asserts.assertEQ(arr[1].foo, 12345);
347         }
348         {
349             MyValue5[] arr = null;
350             for (int i = 0; i < n; i++) {
351                 arr = (MyValue5[])test5(2);
352             }
353             Asserts.assertEQ(arr[1].foo, 22345);
354         }
355     }
356 
357     static Object test6() {
358         return new MyValue6(new MyValue6(123), null);
359     }
360 
361     static void verifyTest6() {
362         Object n = test6();
363         Asserts.assertEQ(n.toString(), "MyValue6@" + Integer.toHexString(n.hashCode()));
364     }
365 
366     static int test7(MyValue7[][] arr) {
367         if (arr != null) {
368             return arr[0][1].foo;
369         } else {
370             return 1234;
371         }
372     }
373 
374     static void verifyTest7() {
375         int n = 50000;
376 
377         int m = 9999;
378         for (int i = 0; i < n; i++) {
379             m = test7(null);
380         }
381         Asserts.assertEQ(m, 1234);
382 
383         MyValue7[][] arr = { (MyValue7[])ValueClass.newNullableAtomicArray(MyValue7.class, 2),
384                              (MyValue7[])ValueClass.newNullableAtomicArray(MyValue7.class, 2) };
385         Object[] oa = arr[1];
386         Asserts.assertEQ(oa[0], null);
387 
388         arr[0][1] = new MyValue7(5678);
389         m = 9999;
390         for (int i = 0; i < n; i++) {
391             m = test7(arr);
392         }
393         Asserts.assertEQ(m, 5678);
394     }
395 
396     static int test7Nullable(MyValue7[][] arr) {
397         if (arr != null) {
398             arr[0][0] = null;
399             return arr[0][1].foo;
400         } else {
401             return 1234;
402         }
403     }
404 
405     static void verifyTest7Nullable() {
406         int n = 50000;
407 
408         int m = 9999;
409         for (int i = 0; i < n; i++) {
410             m = test7Nullable(null);
411         }
412         Asserts.assertEQ(m, 1234);
413 
414         MyValue7[][] arr = new MyValue7[2][2];
415         Object[] oa = arr[1];
416         Asserts.assertEQ(oa[0], null);
417 
418         arr[0][1] = new MyValue7(5678);
419         m = 9999;
420         for (int i = 0; i < n; i++) {
421             m = test7Nullable(arr);
422         }
423         Asserts.assertEQ(m, 5678);
424         Asserts.assertEQ(arr[0][0], null);
425     }
426 
427     static void test8() {
428         MyValue8 a[] = new MyValue8[0];
429         Asserts.assertEQ(MyValue8_inited, false);
430 
431         MyValue8 b[] = (MyValue8[])ValueClass.newNullableAtomicArray(MyValue8.class, 0);
432         Asserts.assertEQ(MyValue8_inited, true);
433     }
434 
435     static void test9() {
436         MyValue9 a[][] = new MyValue9[10][0];
437         Asserts.assertEQ(MyValue9_inited, false);
438 
439         a[0] = (MyValue9[])ValueClass.newNullableAtomicArray(MyValue9.class, 0);
440         Asserts.assertEQ(MyValue9_inited, true);
441     }
442 
443     static void test10(MyValue10 dummy) {
444         MyValue10[][] a = { (MyValue10[])ValueClass.newNullRestrictedNonAtomicArray(MyValue10.class, 1, new MyValue10()) };
445         if (a[0][0].equals(null)) throw new RuntimeException("test10 failed");
446         Asserts.assertNE(a[0][0], null);
447     }
448 
449     static void test11(MyValue10 dummy) {
450         MyValue11[][] a = new MyValue11[1][1];
451         Asserts.assertEQ(a[0][0], null);
452     }
453 
454     static public void main(String[] args) {
455         test1();
456         test1Nullable();
457         verifyTest2();
458         verifyTest2Nullable();
459         verifyTest3();
460         verifyTest3Nullable();
461         verifyTest4();
462         verifyTest4Nullable();
463         verifyTest5();
464         verifyTest6();
465         verifyTest7();
466         verifyTest7Nullable();
467         test8();
468         test9();
469         test10(null);
470         test11(null);
471     }
472 }