1 /*
  2  * Copyright (c) 2023, 2024, 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:FlatArrayElementMaxSize=0
 37  *                   -XX:CompileCommand=compileonly,TestUnloadedInlineTypeArray::test*
 38  *                   TestUnloadedInlineTypeArray
 39  * @run main/othervm -Xcomp
 40  *                   TestUnloadedInlineTypeArray
 41  * @run main/othervm -Xcomp -XX:FlatArrayElementMaxSize=0
 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:FlatArrayElementMaxSize=0
 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:FlatArrayElementMaxSize=0
 52  *                   TestUnloadedInlineTypeArray
 53  */
 54 
 55 import jdk.test.lib.Asserts;
 56 
 57 import jdk.internal.value.ValueClass;
 58 import jdk.internal.vm.annotation.ImplicitlyConstructible;
 59 import jdk.internal.vm.annotation.LooselyConsistentValue;
 60 import jdk.internal.vm.annotation.NullRestricted;
 61 
 62 @ImplicitlyConstructible
 63 @LooselyConsistentValue
 64 value class MyValue1 {
 65     int foo;
 66 
 67     private MyValue1() {
 68         foo = 0x42;
 69     }
 70 }
 71 
 72 @ImplicitlyConstructible
 73 @LooselyConsistentValue
 74 value class MyValue2 {
 75     int foo;
 76 
 77     public MyValue2(int n) {
 78         foo = n;
 79     }
 80 }
 81 
 82 @ImplicitlyConstructible
 83 @LooselyConsistentValue
 84 value class MyValue3 {
 85     int foo;
 86 
 87     public MyValue3(int n) {
 88         foo = n;
 89     }
 90 }
 91 
 92 @ImplicitlyConstructible
 93 @LooselyConsistentValue
 94 value class MyValue4 {
 95     int foo;
 96 
 97     public MyValue4(int n) {
 98         foo = n;
 99     }
100 }
101 
102 @ImplicitlyConstructible
103 @LooselyConsistentValue
104 value class MyValue5 {
105     int foo;
106 
107     public MyValue5(int n) {
108         foo = n;
109     }
110 }
111 
112 @ImplicitlyConstructible
113 @LooselyConsistentValue
114 value class MyValue6 {
115     int foo;
116 
117     public MyValue6(int n) {
118         foo = n;
119     }
120 
121     public MyValue6(MyValue6 v, MyValue6[] dummy) {
122         foo = v.foo + 1;
123     }
124 }
125 
126 @ImplicitlyConstructible
127 @LooselyConsistentValue
128 value class MyValue7 {
129     int foo;
130 
131     public MyValue7(int n) {
132         foo = n;
133     }
134 }
135 
136 @ImplicitlyConstructible
137 @LooselyConsistentValue
138 value class MyValue8 {
139     int foo = 123;
140     static {
141         TestUnloadedInlineTypeArray.MyValue8_inited = true;
142     }
143 }
144 
145 @ImplicitlyConstructible
146 @LooselyConsistentValue
147 value class MyValue9 {
148     int foo = 123;
149     static {
150         TestUnloadedInlineTypeArray.MyValue9_inited = true;
151     }
152 }
153 
154 @ImplicitlyConstructible
155 @LooselyConsistentValue
156 value class MyValue10 {
157     int foo = 42;
158 }
159 
160 @ImplicitlyConstructible
161 @LooselyConsistentValue
162 value class MyValue11 {
163     int foo = 42;
164 }
165 
166 public class TestUnloadedInlineTypeArray {
167     static boolean MyValue8_inited = false;
168     static boolean MyValue9_inited = false;
169 
170     static MyValue1[] target1() {
171         return (MyValue1[])ValueClass.newNullRestrictedArray(MyValue1.class, 10);
172     }
173 
174     static void test1() {
175         target1();
176     }
177 
178     static MyValue1[] target1Nullable() {
179         return new MyValue1[10];
180     }
181 
182     static void test1Nullable() {
183         target1Nullable();
184     }
185 
186     static int test2(MyValue2[] arr) {
187         if (arr != null) {
188             return arr[1].foo;
189         } else {
190             return 1234;
191         }
192     }
193 
194     static void verifyTest2() {
195         int n = 50000;
196 
197         int m = 9999;
198         for (int i = 0; i < n; i++) {
199             m = test2(null);
200         }
201         Asserts.assertEQ(m, 1234);
202 
203         MyValue2[] arr = (MyValue2[])ValueClass.newNullRestrictedArray(MyValue2.class, 2);
204         arr[1] = new MyValue2(5678);
205         m = 9999;
206         for (int i = 0; i < n; i++) {
207             m = test2(arr);
208         }
209         Asserts.assertEQ(m, 5678);
210     }
211 
212     static int test2Nullable(MyValue2[] arr) {
213         if (arr != null) {
214             return arr[1].foo;
215         } else {
216             return 1234;
217         }
218     }
219 
220     static void verifyTest2Nullable() {
221         int n = 50000;
222 
223         int m = 9999;
224         for (int i = 0; i < n; i++) {
225             m = test2Nullable(null);
226         }
227         Asserts.assertEQ(m, 1234);
228 
229         MyValue2[] arr = new MyValue2[2];
230         arr[1] = new MyValue2(5678);
231         m = 9999;
232         for (int i = 0; i < n; i++) {
233             m = test2Nullable(arr);
234         }
235         Asserts.assertEQ(m, 5678);
236     }
237 
238     static void test3(MyValue3[] arr) {
239         if (arr != null) {
240             arr[1] = new MyValue3(2345);
241         }
242     }
243 
244     static void verifyTest3() {
245         int n = 50000;
246 
247         for (int i = 0; i < n; i++) {
248             test3(null);
249         }
250 
251         MyValue3[] arr = (MyValue3[])ValueClass.newNullRestrictedArray(MyValue3.class, 2);
252         for (int i = 0; i < n; i++) {
253             test3(arr);
254         }
255         Asserts.assertEQ(arr[1].foo, 2345);
256     }
257 
258     static void test3Nullable(MyValue3[] arr) {
259         if (arr != null) {
260             arr[0] = null;
261             arr[1] = new MyValue3(2345);
262         }
263     }
264 
265     static void verifyTest3Nullable() {
266         int n = 50000;
267 
268         for (int i = 0; i < n; i++) {
269             test3Nullable(null);
270         }
271 
272         MyValue3[] arr = new MyValue3[2];
273         for (int i = 0; i < n; i++) {
274             test3Nullable(arr);
275         }
276         Asserts.assertEQ(arr[0], null);
277         Asserts.assertEQ(arr[1].foo, 2345);
278     }
279 
280     static MyValue4[] test4(boolean b) {
281         // range check elimination
282         if (b) {
283             MyValue4[] arr = (MyValue4[])ValueClass.newNullRestrictedArray(MyValue4.class, 10);
284             arr[1] = new MyValue4(2345);
285             return arr;
286         } else {
287             return null;
288         }
289     }
290 
291     static void verifyTest4() {
292         int n = 50000;
293 
294         for (int i = 0; i < n; i++) {
295             test4(false);
296         }
297 
298         MyValue4[] arr = null;
299         for (int i = 0; i < n; i++) {
300             arr = test4(true);
301         }
302         Asserts.assertEQ(arr[1].foo, 2345);
303     }
304 
305     static MyValue4[] test4Nullable(boolean b) {
306         // range check elimination
307         if (b) {
308             MyValue4[] arr = new MyValue4[10];
309             arr[0] = null;
310             arr[1] = new MyValue4(2345);
311             return arr;
312         } else {
313             return null;
314         }
315     }
316 
317     static void verifyTest4Nullable() {
318         int n = 50000;
319 
320         for (int i = 0; i < n; i++) {
321             test4Nullable(false);
322         }
323 
324         MyValue4[] arr = null;
325         for (int i = 0; i < n; i++) {
326             arr = test4Nullable(true);
327         }
328         Asserts.assertEQ(arr[0], null);
329         Asserts.assertEQ(arr[1].foo, 2345);
330         arr[3] = null;
331     }
332 
333     static Object[] test5(int n) {
334         if (n == 0) {
335             return null;
336         } else if (n == 1) {
337             MyValue5[] arr = (MyValue5[])ValueClass.newNullRestrictedArray(MyValue5.class, 10);
338             arr[1] = new MyValue5(12345);
339             return arr;
340         } else {
341             MyValue5[] arr = new MyValue5[10];
342             arr[1] = new MyValue5(22345);
343             return arr;
344         }
345     }
346 
347     static void verifyTest5() {
348         int n = 50000;
349 
350         for (int i = 0; i < n; i++) {
351             test5(0);
352         }
353 
354         {
355             MyValue5[] arr = null;
356             for (int i = 0; i < n; i++) {
357                 arr = (MyValue5[])test5(1);
358             }
359             Asserts.assertEQ(arr[1].foo, 12345);
360         }
361         {
362             MyValue5[] arr = null;
363             for (int i = 0; i < n; i++) {
364                 arr = (MyValue5[])test5(2);
365             }
366             Asserts.assertEQ(arr[1].foo, 22345);
367         }
368     }
369 
370     static Object test6() {
371         return new MyValue6(new MyValue6(123), null);
372     }
373 
374     static void verifyTest6() {
375         Object n = test6();
376         Asserts.assertEQ(n.toString(), "MyValue6@" + Integer.toHexString(n.hashCode()));
377     }
378 
379     static int test7(MyValue7[][] arr) {
380         if (arr != null) {
381             return arr[0][1].foo;
382         } else {
383             return 1234;
384         }
385     }
386 
387     static void verifyTest7() {
388         int n = 50000;
389 
390         int m = 9999;
391         for (int i = 0; i < n; i++) {
392             m = test7(null);
393         }
394         Asserts.assertEQ(m, 1234);
395 
396         MyValue7[][] arr = { (MyValue7[])ValueClass.newNullRestrictedArray(MyValue7.class, 2),
397                              (MyValue7[])ValueClass.newNullRestrictedArray(MyValue7.class, 2) };
398         Object[] oa = arr[1];
399         Asserts.assertNE(oa[0], null);
400 
401         arr[0][1] = new MyValue7(5678);
402         m = 9999;
403         for (int i = 0; i < n; i++) {
404             m = test7(arr);
405         }
406         Asserts.assertEQ(m, 5678);
407     }
408 
409     static int test7Nullable(MyValue7[][] arr) {
410         if (arr != null) {
411             arr[0][0] = null;
412             return arr[0][1].foo;
413         } else {
414             return 1234;
415         }
416     }
417 
418     static void verifyTest7Nullable() {
419         int n = 50000;
420 
421         int m = 9999;
422         for (int i = 0; i < n; i++) {
423             m = test7Nullable(null);
424         }
425         Asserts.assertEQ(m, 1234);
426 
427         MyValue7[][] arr = new MyValue7[2][2];
428         Object[] oa = arr[1];
429         Asserts.assertEQ(oa[0], null);
430 
431         arr[0][1] = new MyValue7(5678);
432         m = 9999;
433         for (int i = 0; i < n; i++) {
434             m = test7Nullable(arr);
435         }
436         Asserts.assertEQ(m, 5678);
437         Asserts.assertEQ(arr[0][0], null);
438     }
439 
440     static void test8() {
441         MyValue8 a[] = new MyValue8[0];
442         Asserts.assertEQ(MyValue8_inited, false);
443 
444         MyValue8 b[] = (MyValue8[])ValueClass.newNullRestrictedArray(MyValue8.class, 0);
445         Asserts.assertEQ(MyValue8_inited, true);
446     }
447 
448     static void test9() {
449         MyValue9 a[][] = new MyValue9[10][0];
450         Asserts.assertEQ(MyValue9_inited, false);
451 
452         a[0] = (MyValue9[])ValueClass.newNullRestrictedArray(MyValue9.class, 0);
453         Asserts.assertEQ(MyValue9_inited, true);
454     }
455 
456     static void test10(MyValue10 dummy) {
457         MyValue10[][] a = { (MyValue10[])ValueClass.newNullRestrictedArray(MyValue10.class, 1) };
458         if (a[0][0].equals(null)) throw new RuntimeException("test10 failed");
459         Asserts.assertNE(a[0][0], null);
460     }
461 
462     static void test11(MyValue10 dummy) {
463         MyValue11[][] a = new MyValue11[1][1];
464         Asserts.assertEQ(a[0][0], null);
465     }
466 
467     static public void main(String[] args) {
468         test1();
469         test1Nullable();
470         verifyTest2();
471         verifyTest2Nullable();
472         verifyTest3();
473         verifyTest3Nullable();
474         verifyTest4();
475         verifyTest4Nullable();
476         verifyTest5();
477         verifyTest6();
478         verifyTest7();
479         verifyTest7Nullable();
480         test8();
481         test9();
482         test10(null);
483         test11(null);
484     }
485 }