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 }