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 }