1 /* 2 * Copyright (c) 2018, 2025, 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 package runtime.valhalla.inlinetypes; 25 26 import jdk.internal.value.ValueClass; 27 import jdk.internal.vm.annotation.LooselyConsistentValue; 28 import jdk.internal.vm.annotation.NullRestricted; 29 import jdk.internal.vm.annotation.Strict; 30 import java.lang.reflect.Array; 31 import java.util.Arrays; 32 import java.util.ArrayList; 33 import java.util.List; 34 35 import static jdk.test.lib.Asserts.*; 36 37 /* 38 * @test InlineTypeArray 39 * @summary Plain array test for Inline Types 40 * @modules java.base/jdk.internal.value 41 * java.base/jdk.internal.vm.annotation 42 * @library /test/lib 43 * @enablePreview 44 * @compile --source 25 InlineTypeArray.java Point.java Long8Inline.java Person.java 45 * @run main/othervm -XX:+UseArrayFlattening -XX:+UseFieldFlattening runtime.valhalla.inlinetypes.InlineTypeArray 46 * @run main/othervm -XX:-UseArrayFlattening runtime.valhalla.inlinetypes.InlineTypeArray 47 * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:ForceNonTearable=* runtime.valhalla.inlinetypes.InlineTypeArray 48 * @run main/othervm -XX:+UseArrayFlattening -XX:+UseFieldFlattening -XX:+UseNullableValueFlattening runtime.valhalla.inlinetypes.InlineTypeArray 49 */ 50 public class InlineTypeArray { 51 public static void main(String[] args) { 52 InlineTypeArray inlineTypeArray = new InlineTypeArray(); 53 inlineTypeArray.run(); 54 } 55 56 public void run() { 57 testClassForName(); 58 testSimplePointArray(); 59 testLong8Array(); 60 testMixedPersonArray(); 61 testMultiDimPointArray(); 62 testComposition(); 63 64 testSanityCheckcasts(); 65 testObjectArrayOfInlines(); 66 67 testReflectArray(); 68 testUtilArraysOnNullRestrictedNonAtomicArrays(); 69 testUtilArraysOnNullRestrictedAtomicArrays(); 70 testUtilArraysOnNullableAtomicArrays(); 71 72 testInlineArrayOom(); 73 } 74 75 void testClassForName() { 76 String arrayClsName = "[Lruntime.valhalla.inlinetypes.Point;"; 77 try { 78 Class<?> arrayCls = Class.forName(arrayClsName); 79 assertTrue(arrayCls.isArray(), "Expected an array class"); 80 81 arrayClsName = "[" + arrayClsName; 82 Class<?> mulArrayCls = Class.forName(arrayClsName); 83 assertTrue(mulArrayCls.isArray()); 84 assertTrue(mulArrayCls.getComponentType() == arrayCls); 85 } 86 catch (ClassNotFoundException cnfe) { 87 fail("Class.forName(" + arrayClsName + ") failed", cnfe); 88 } 89 } 90 91 void testSimplePointArray() { 92 Point[] defaultPoint = (Point[])ValueClass.newNullRestrictedNonAtomicArray(Point.class, 1, new Point(0, 0)); 93 Point p = defaultPoint[0]; 94 assertEquals(p.x, 0, "invalid default loaded from array"); 95 assertEquals(p.y, 0, "invalid default loaded from array"); 96 boolean gotNpe = false; 97 try { 98 defaultPoint[0] = (Point) getNull(); 99 } catch (NullPointerException npe) { 100 gotNpe = true; 101 } 102 assertTrue(gotNpe, "Expected NullPointerException"); 103 104 Point[] points = createSimplePointArray(); 105 System.gc(); // check that VTs survive GC 106 checkSimplePointArray(points); 107 assertTrue(points instanceof Point[], "Instance of"); 108 109 testSimplePointArrayCopy(); 110 111 // Locked/unlocked flat array type checks 112 points = createSimplePointArray(); 113 Point[] pointsCopy = (Point[])ValueClass.newNullRestrictedNonAtomicArray(Point.class, points.length, new Point(0, 0)); 114 synchronized (points) { 115 assertTrue(points instanceof Point[], "Instance of"); 116 checkSimplePointArray(points); 117 System.arraycopy(points, 0, pointsCopy, 0, points.length); 118 synchronized (pointsCopy) { 119 assertTrue(pointsCopy instanceof Point[], "Instance of"); 120 checkSimplePointArray(pointsCopy); 121 System.gc(); 122 } 123 System.gc(); 124 } 125 assertTrue(pointsCopy instanceof Point[], "Instance of"); 126 checkSimplePointArray(pointsCopy); 127 } 128 129 void testSimplePointArrayCopy() { 130 Point[] points = createSimplePointArray(); 131 Point[] pointsCopy = (Point[])ValueClass.newNullRestrictedNonAtomicArray(Point.class, points.length, new Point(0, 0)); 132 System.arraycopy(points, 0, pointsCopy, 0, points.length); 133 checkSimplePointArray(pointsCopy); 134 135 // Conjoint, overlap...left 136 System.arraycopy(points, 0, points, 1, 2); 137 checkArrayElementsEqual(points, new Point[] { pointsCopy[0], pointsCopy[0], pointsCopy[1], pointsCopy[3] }); 138 139 // Conjoint, overlap...right 140 points = createSimplePointArray(); 141 System.arraycopy(points, 2, points, 1, 2); 142 checkArrayElementsEqual(points, new Point[] { pointsCopy[0], pointsCopy[2], pointsCopy[3], pointsCopy[3] }); 143 } 144 145 static Point[] createSimplePointArray() { 146 Point[] ps = (Point[])ValueClass.newNullRestrictedNonAtomicArray(Point.class, 4, new Point(0, 0)); 147 assertEquals(ps.length, 4, "Length"); 148 ps.toString(); 149 ps[0] = new Point(1, 2); 150 ps[1] = new Point(3, 4); 151 ps[2] = new Point(5, 6); 152 ps[3] = new Point(7, 8); 153 boolean sawOob = false; 154 try { 155 ps[ps.length] = new Point(0, 0); 156 } catch (ArrayIndexOutOfBoundsException aioobe) { sawOob = true; } 157 assertTrue(sawOob, "Didn't see AIOOBE"); 158 return ps; 159 } 160 161 static void checkSimplePointArray(Point[] points) { 162 assertEquals(points[0].x, 1, "invalid 0 point x value"); 163 assertEquals(points[0].y, 2, "invalid 0 point y value"); 164 assertEquals(points[1].x, 3, "invalid 1 point x value"); 165 assertEquals(points[1].y, 4, "invalid 1 point y value"); 166 assertEquals(points[2].x, 5, "invalid 2 point x value"); 167 assertEquals(points[2].y, 6, "invalid 2 point y value"); 168 assertEquals(points[3].x, 7, "invalid 3 point x value"); 169 assertEquals(points[3].y, 8, "invalid 3 point y value"); 170 } 171 172 void testLong8Array() { 173 Long8Inline[] values = (Long8Inline[])ValueClass.newNullRestrictedNonAtomicArray(Long8Inline.class, 3, new Long8Inline()); 174 assertEquals(values.length, 3, "length"); 175 values.toString(); 176 Long8Inline value = values[1]; 177 long zl = 0; 178 Long8Inline.check(value, zl, zl, zl, zl, zl, zl, zl, zl); 179 values[1] = new Long8Inline(1, 2, 3, 4, 5, 6, 7, 8); 180 value = values[1]; 181 Long8Inline.check(value, 1, 2, 3, 4, 5, 6, 7, 8); 182 183 Long8Inline[] copy = (Long8Inline[])ValueClass.newNullRestrictedNonAtomicArray(Long8Inline.class, values.length, new Long8Inline()); 184 System.arraycopy(values, 0, copy, 0, values.length); 185 value = copy[1]; 186 Long8Inline.check(value, 1, 2, 3, 4, 5, 6, 7, 8); 187 } 188 189 void testMixedPersonArray() { 190 Person[] people = (Person[])ValueClass.newNullRestrictedNonAtomicArray(Person.class, 3, new Person(0, null, null)); 191 192 people[0] = new Person(1, "First", "Last"); 193 assertEquals(people[0].getId(), 1, "Invalid Id person"); 194 assertEquals(people[0].getFirstName(), "First", "Invalid First Name"); 195 assertEquals(people[0].getLastName(), "Last", "Invalid Last Name"); 196 197 people[1] = new Person(2, "Jane", "Wayne"); 198 people[2] = new Person(3, "Bob", "Dobalina"); 199 200 Person[] peopleCopy = (Person[])ValueClass.newNullRestrictedNonAtomicArray(Person.class, people.length, new Person(0, null, null)); 201 System.arraycopy(people, 0, peopleCopy, 0, people.length); 202 assertEquals(peopleCopy[2].getId(), 3, "Invalid Id"); 203 assertEquals(peopleCopy[2].getFirstName(), "Bob", "Invalid First Name"); 204 assertEquals(peopleCopy[2].getLastName(), "Dobalina", "Invalid Last Name"); 205 } 206 207 void testMultiDimPointArray() { 208 /* 209 Point[][][] multiPoints = new Point[2][3][4]; 210 assertEquals(multiPoints.length, 2, "1st dim length"); 211 assertEquals(multiPoints[0].length, 3, "2st dim length"); 212 assertEquals(multiPoints[0][0].length, 4, "3rd dim length"); 213 214 Point defaultPoint = multiPoints[1][2][3]; 215 assertEquals(defaultPoint.x, 0, "invalid point x value"); 216 assertEquals(defaultPoint.y, 0, "invalid point x value"); 217 */ 218 } 219 220 void testReflectArray() { 221 // Check the java.lang.reflect.Array.newInstance methods... 222 Class<?> cls = (Class<?>) Point[].class; 223 Point[][] array = (Point[][]) Array.newInstance(cls, 1); 224 assertEquals(array.length, 1, "Incorrect length"); 225 assertTrue(array[0] == null, "Expected NULL"); 226 227 Point[][][] array3 = (Point[][][]) Array.newInstance(cls, 1, 2); 228 assertEquals(array3.length, 1, "Incorrect length"); 229 assertEquals(array3[0].length, 2, "Incorrect length"); 230 assertTrue(array3[0][0] == null, "Expected NULL"); 231 232 // Now create ObjArrays of InlineArray... 233 Point[][] barray = (Point[][]) Array.newInstance(Point.class, 1, 2); 234 assertEquals(barray.length, 1, "Incorrect length"); 235 assertEquals(barray[0].length, 2, "Incorrect length"); 236 barray[0][1] = new Point(1, 2); 237 Point pb = barray[0][1]; 238 int x = pb.getX(); 239 assertEquals(x, 1, "Bad Point Value"); 240 } 241 242 @LooselyConsistentValue 243 static value class MyInt implements Comparable<MyInt> { 244 int value; 245 246 private MyInt() { this(0); } 247 private MyInt(int v) { value = v; } 248 public int getValue() { return value; } 249 public String toString() { return "MyInt: " + getValue(); } 250 public int compareTo(MyInt that) { return Integer.compare(this.getValue(), that.getValue()); } 251 public boolean equals(Object o) { 252 if (o instanceof MyInt) { 253 return this.getValue() == ((MyInt) o).getValue(); 254 } 255 return false; 256 } 257 258 public static MyInt create(int v) { 259 return new MyInt(v); 260 } 261 262 public static final MyInt MIN = MyInt.create(Integer.MIN_VALUE); 263 public static final MyInt ZERO = MyInt.create(0); 264 public static final MyInt MAX = MyInt.create(Integer.MAX_VALUE); 265 } 266 267 static MyInt staticMyInt; 268 static MyInt[] staticMyIntArray; 269 static MyInt[][] staticMyIntArrayArray; 270 271 static { 272 staticMyInt = MyInt.create(-1); 273 staticMyIntArray = (MyInt[])ValueClass.newNullRestrictedNonAtomicArray(MyInt.class, 1, new MyInt()); 274 staticMyIntArray[0] = staticMyInt; 275 staticMyIntArrayArray = new MyInt[][] { staticMyIntArray, staticMyIntArray }; 276 } 277 278 static value class MyShorts implements Comparable<MyShorts> { 279 short s0, s1; 280 281 private MyShorts() { this((short)0, (short)0); } 282 private MyShorts(short sa, short sb) { s0 = sa; s1 = sb; } 283 public short getS0() { return s0; } 284 public short getS1() { return s1; } 285 public String toString() { return "MyShorts: " + getS0() + " " + getS1(); } 286 public int compareTo(MyShorts that) { 287 int r = Short.compare(this.getS0(), that.getS0()); 288 return r != 0 ? r : Short.compare(this.getS1(), that.getS1()); 289 } 290 public boolean equals(Object o) { 291 if (o instanceof MyShorts) { 292 return this.getS0() == ((MyShorts) o).getS0() && this.getS1() == ((MyShorts) o).getS1(); 293 } 294 return false; 295 } 296 297 public static MyShorts create(short s0, short s1) { 298 return new MyShorts(s0, s1); 299 } 300 301 public static final MyShorts MIN = MyShorts.create(Short.MIN_VALUE, Short.MIN_VALUE); 302 public static final MyShorts ZERO = MyShorts.create((short)0, (short)0); 303 public static final MyShorts MAX = MyShorts.create(Short.MAX_VALUE, Short.MAX_VALUE); 304 } 305 306 static interface SomeSecondaryType { 307 default String hi() { return "Hi"; } 308 } 309 310 @LooselyConsistentValue 311 static value class MyOtherInt implements SomeSecondaryType { 312 final int value; 313 private MyOtherInt() { value = 0; } 314 } 315 316 void testSanityCheckcasts() { 317 MyInt[] myInts = (MyInt[])ValueClass.newNullRestrictedNonAtomicArray(MyInt.class, 1, new MyInt()); 318 assertTrue(myInts instanceof Object[]); 319 assertTrue(myInts instanceof Comparable[]); 320 assertTrue(myInts instanceof MyInt[]); 321 322 Class<?> cls = MyInt.class; 323 assertTrue(cls.isValue()); 324 Object arrObj = Array.newInstance(cls, 1); 325 assertTrue(arrObj instanceof Object[], "Not Object array"); 326 assertTrue(arrObj instanceof Comparable[], "Not Comparable array"); 327 assertTrue(arrObj instanceof MyInt[], "Not MyInt array"); 328 329 Object[] arr = (Object[]) arrObj; 330 assertTrue(arr instanceof Comparable[], "Not Comparable array"); 331 assertTrue(arr instanceof MyInt[], "Not MyInt array"); 332 Comparable[] comparables = (Comparable[])arr; 333 MyInt[] myIntArr = (MyInt[]) arr; 334 335 // multi-dim, check secondary array types are setup... 336 MyOtherInt[][] matrix = new MyOtherInt[1][1]; 337 assertTrue(matrix[0] instanceof MyOtherInt[]); 338 assertTrue(matrix[0] instanceof SomeSecondaryType[]); 339 assertTrue(matrix[0] instanceof MyOtherInt[]); 340 341 // Box types vs Inline... 342 MyInt[] myValueRefs = new MyInt[1]; 343 assertTrue(myValueRefs instanceof MyInt[]); 344 assertTrue(myValueRefs instanceof Object[]); 345 assertTrue(myValueRefs instanceof Comparable[]); 346 347 MyInt[][] myMdValueRefs = new MyInt[1][1]; 348 assertTrue(myMdValueRefs[0] instanceof MyInt[]); 349 assertTrue(myMdValueRefs[0] instanceof Object[]); 350 assertTrue(myMdValueRefs[0] instanceof Comparable[]); 351 352 // Did we break checkcast... 353 MyInt[] va1 = (MyInt[])null; 354 MyInt[] va2 = null; 355 MyInt[][] va3 = (MyInt[][])null; 356 MyInt[][][] va4 = (MyInt[][][])null; 357 } 358 359 360 void testUtilArraysOnNullRestrictedNonAtomicArrays() { 361 // Sanity check j.u.Arrays 362 363 // Testing Arrays.copyOf() 364 MyInt[] myInts = (MyInt[])ValueClass.newNullRestrictedNonAtomicArray(MyInt.class, 3, new MyInt()); 365 myInts[0] = MyInt.MAX; 366 myInts[1] = MyInt.MIN; 367 myInts[2] = MyInt.ZERO; 368 369 // Copy of same length, must work 370 MyInt[] copyMyInts = (MyInt[]) Arrays.copyOf(myInts, myInts.length); 371 MyInt[] expected = (MyInt[])ValueClass.newNullRestrictedNonAtomicArray(MyInt.class, 3, new MyInt()); 372 expected[0] = myInts[0]; 373 expected[1] = myInts[1]; 374 expected[2] = myInts[2]; 375 checkArrayElementsEqual(copyMyInts, expected); 376 377 // Copy of shorter length, must work 378 MyInt[] smallCopyMyInts = (MyInt[]) Arrays.copyOf(myInts, myInts.length - 1); 379 MyInt[] expected2 = (MyInt[])ValueClass.newNullRestrictedNonAtomicArray(MyInt.class, 2, new MyInt()); 380 expected2[0] = myInts[0]; 381 expected2[1] = myInts[1]; 382 checkArrayElementsEqual(smallCopyMyInts, expected2); 383 384 // Copy of bigger length, must fail for null-restricted arrays 385 IllegalArgumentException iae = null; 386 try { 387 MyInt[] bigCopyMyInts = (MyInt[]) Arrays.copyOf(myInts, myInts.length + 1); 388 } catch (IllegalArgumentException e) { 389 iae = e; 390 } 391 assertTrue(iae != null, "Exception not received"); 392 393 // Testing Arrays.copyOfRange() 394 MyInt[] fullRangeCopy = (MyInt[]) Arrays.copyOfRange(myInts, 0, myInts.length); 395 checkArrayElementsEqual(copyMyInts, expected); 396 397 MyInt[] beginningRangeCopy = (MyInt[]) Arrays.copyOfRange(myInts, 0, 2); 398 checkArrayElementsEqual(beginningRangeCopy, expected2); 399 400 401 MyInt[] endingRangeCopy = (MyInt[]) Arrays.copyOfRange(myInts, 1, myInts.length); 402 MyInt[] expected3 = (MyInt[])ValueClass.newNullRestrictedNonAtomicArray(MyInt.class, 2, new MyInt()); 403 expected3[0] = myInts[1]; 404 expected3[1] = myInts[2]; 405 checkArrayElementsEqual(endingRangeCopy, expected3); 406 407 // Range exceeding initial array's length, must fail for null-restricted arrays 408 iae = null; 409 try { 410 MyInt[] exceedingRangeCopy = (MyInt[]) Arrays.copyOfRange(myInts, 1, myInts.length + 1); 411 } catch (IllegalArgumentException e) { 412 iae = e; 413 } 414 assertTrue(iae != null, "Exception not received"); 415 416 // Range starting after the end of the original array, must fail for null-restricted arrays 417 iae = null; 418 try { 419 MyInt[] farRangeCopy = (MyInt[]) Arrays.copyOfRange(myInts, myInts.length, myInts.length + 1); 420 } catch (IllegalArgumentException e) { 421 iae = e; 422 } 423 assertTrue(iae != null, "Exception not received"); 424 425 Arrays.sort(copyMyInts); 426 expected = (MyInt[])ValueClass.newNullRestrictedNonAtomicArray(MyInt.class, 3, new MyInt()); 427 expected[0] = (MyInt) MyInt.MIN; 428 expected[1] = (MyInt) MyInt.ZERO; 429 expected[2] = (MyInt) MyInt.MAX; 430 checkArrayElementsEqual(copyMyInts, expected); 431 432 List myIntList = Arrays.asList(copyMyInts); 433 434 MyInt[] dest = (MyInt[])ValueClass.newNullRestrictedNonAtomicArray(MyInt.class, copyMyInts.length, new MyInt()); 435 checkArrayElementsEqual(copyMyInts, myIntList.toArray(dest)); 436 // This next line needs testMixedLayoutArrays to work 437 checkArrayElementsEqual(copyMyInts, myIntList.toArray()); 438 439 // Sanity check j.u.ArrayList 440 ArrayList<MyInt> aList = new ArrayList<MyInt>(Arrays.asList(copyMyInts)); 441 assertTrue(aList.indexOf(MyInt.MIN) == 0, "Bad Index"); 442 assertTrue(aList.indexOf(MyInt.ZERO) == 1, "Bad Index"); 443 assertTrue(aList.indexOf(MyInt.MAX) == 2, "Bad Index"); 444 445 aList.remove(2); 446 aList.add(MyInt.create(5)); 447 } 448 449 void testUtilArraysOnNullRestrictedAtomicArrays() { 450 // Sanity check j.u.Arrays 451 452 // Testing Arrays.copyOf() 453 MyShorts[] myShorts = (MyShorts[])ValueClass.newNullRestrictedAtomicArray(MyShorts.class, 3, new MyShorts()); 454 myShorts[0] = MyShorts.MAX; 455 myShorts[1] = MyShorts.MIN; 456 myShorts[2] = MyShorts.ZERO; 457 458 // Copy of same length, must work 459 MyShorts[] copyMyInts = (MyShorts[]) Arrays.copyOf(myShorts, myShorts.length); 460 MyShorts[] expected = (MyShorts[])ValueClass.newNullRestrictedAtomicArray(MyShorts.class, 3, new MyShorts()); 461 expected[0] = myShorts[0]; 462 expected[1] = myShorts[1]; 463 expected[2] = myShorts[2]; 464 checkArrayElementsEqual(copyMyInts, expected); 465 466 // Copy of shorter length, must work 467 MyShorts[] smallCopyMyInts = (MyShorts[]) Arrays.copyOf(myShorts, myShorts.length - 1); 468 MyShorts[] expected2 = (MyShorts[])ValueClass.newNullRestrictedAtomicArray(MyShorts.class, 2, new MyShorts()); 469 expected2[0] = myShorts[0]; 470 expected2[1] = myShorts[1]; 471 checkArrayElementsEqual(smallCopyMyInts, expected2); 472 473 // Copy of bigger length, must fail for null-restricted arrays 474 IllegalArgumentException iae = null; 475 try { 476 MyShorts[] bigCopyMyInts = (MyShorts[]) Arrays.copyOf(myShorts, myShorts.length + 1); 477 } catch (IllegalArgumentException e) { 478 iae = e; 479 } 480 assertTrue(iae != null, "Exception not received"); 481 482 // Testing Arrays.copyOfRange() 483 MyShorts[] fullRangeCopy = (MyShorts[]) Arrays.copyOfRange(myShorts, 0, myShorts.length); 484 checkArrayElementsEqual(copyMyInts, expected); 485 486 MyShorts[] beginningRangeCopy = (MyShorts[]) Arrays.copyOfRange(myShorts, 0, 2); 487 checkArrayElementsEqual(beginningRangeCopy, expected2); 488 489 490 MyShorts[] endingRangeCopy = (MyShorts[]) Arrays.copyOfRange(myShorts, 1, myShorts.length); 491 MyShorts[] expected3 = (MyShorts[])ValueClass.newNullRestrictedAtomicArray(MyShorts.class, 2, new MyShorts()); 492 expected3[0] = myShorts[1]; 493 expected3[1] = myShorts[2]; 494 checkArrayElementsEqual(endingRangeCopy, expected3); 495 496 // Range exceeding initial array's length, must fail for null-restricted arrays 497 iae = null; 498 try { 499 MyShorts[] exceedingRangeCopy = (MyShorts[]) Arrays.copyOfRange(myShorts, 1, myShorts.length + 1); 500 } catch (IllegalArgumentException e) { 501 iae = e; 502 } 503 assertTrue(iae != null, "Exception not received"); 504 505 // Range starting after the end of the original array, must fail for null-restricted arrays 506 iae = null; 507 try { 508 MyShorts[] farRangeCopy = (MyShorts[]) Arrays.copyOfRange(myShorts, myShorts.length, myShorts.length + 1); 509 } catch (IllegalArgumentException e) { 510 iae = e; 511 } 512 assertTrue(iae != null, "Exception not received"); 513 514 Arrays.sort(copyMyInts); 515 expected = (MyShorts[])ValueClass.newNullRestrictedAtomicArray(MyShorts.class, 3, new MyShorts()); 516 expected[0] = (MyShorts) MyShorts.MIN; 517 expected[1] = (MyShorts) MyShorts.ZERO; 518 expected[2] = (MyShorts) MyShorts.MAX; 519 checkArrayElementsEqual(copyMyInts, expected); 520 521 List myIntList = Arrays.asList(copyMyInts); 522 523 MyShorts[] dest = (MyShorts[])ValueClass.newNullRestrictedAtomicArray(MyShorts.class, copyMyInts.length, new MyShorts()); 524 checkArrayElementsEqual(copyMyInts, myIntList.toArray(dest)); 525 // This next line needs testMixedLayoutArrays to work 526 checkArrayElementsEqual(copyMyInts, myIntList.toArray()); 527 528 // Sanity check j.u.ArrayList 529 ArrayList<MyShorts> aList = new ArrayList<MyShorts>(Arrays.asList(copyMyInts)); 530 assertTrue(aList.indexOf(MyShorts.MIN) == 0, "Bad Index"); 531 assertTrue(aList.indexOf(MyShorts.ZERO) == 1, "Bad Index"); 532 assertTrue(aList.indexOf(MyShorts.MAX) == 2, "Bad Index"); 533 534 aList.remove(2); 535 aList.add(MyShorts.create((short)5, (short)7)); 536 } 537 538 void testUtilArraysOnNullableAtomicArrays() { 539 // Sanity check j.u.Arrays 540 541 // Testing Arrays.copyOf() 542 MyInt[] myInts = (MyInt[])ValueClass.newNullableAtomicArray(MyInt.class, 3); 543 myInts[0] = MyInt.MAX; 544 myInts[1] = MyInt.MIN; 545 myInts[2] = MyInt.ZERO; 546 547 // Copy of same length, must work 548 MyInt[] copyMyInts = (MyInt[]) Arrays.copyOf(myInts, myInts.length); 549 MyInt[] expected = (MyInt[])ValueClass.newNullableAtomicArray(MyInt.class, 3); 550 expected[0] = myInts[0]; 551 expected[1] = myInts[1]; 552 expected[2] = myInts[2]; 553 checkArrayElementsEqual(copyMyInts, expected); 554 555 // Copy of shorter length, must work 556 MyInt[] smallCopyMyInts = (MyInt[]) Arrays.copyOf(myInts, myInts.length - 1); 557 MyInt[] expected2 = (MyInt[])ValueClass.newNullableAtomicArray(MyInt.class, 2); 558 expected2[0] = myInts[0]; 559 expected2[1] = myInts[1]; 560 checkArrayElementsEqual(smallCopyMyInts, expected2); 561 562 // Copy of bigger length, must work for nullable arrays 563 MyInt[] bigCopyMyInts = (MyInt[]) Arrays.copyOf(myInts, myInts.length + 1); 564 MyInt[] expected2b = (MyInt[])ValueClass.newNullableAtomicArray(MyInt.class, 4); 565 expected2b[0] = myInts[0]; 566 expected2b[1] = myInts[1]; 567 expected2b[2] = myInts[2]; 568 expected2b[3] = null; 569 checkArrayElementsEqual(bigCopyMyInts, expected2b); 570 571 // Testing Arrays.copyOfRange() 572 MyInt[] fullRangeCopy = (MyInt[]) Arrays.copyOfRange(myInts, 0, myInts.length); 573 checkArrayElementsEqual(copyMyInts, expected); 574 575 MyInt[] beginningRangeCopy = (MyInt[]) Arrays.copyOfRange(myInts, 0, 2); 576 checkArrayElementsEqual(beginningRangeCopy, expected2); 577 578 MyInt[] endingRangeCopy = (MyInt[]) Arrays.copyOfRange(myInts, 1, myInts.length); 579 MyInt[] expected3 = (MyInt[])ValueClass.newNullableAtomicArray(MyInt.class, 2); 580 expected3[0] = myInts[1]; 581 expected3[1] = myInts[2]; 582 checkArrayElementsEqual(endingRangeCopy, expected3); 583 584 // Range exceeding initial array's length, must succeed for nullable arrays 585 MyInt[] exceedingRangeCopy = (MyInt[]) Arrays.copyOfRange(myInts, 1, myInts.length + 1); 586 MyInt[] expected3b = (MyInt[])ValueClass.newNullableAtomicArray(MyInt.class, 3); 587 expected3b[0] = myInts[1]; 588 expected3b[1] = myInts[2]; 589 expected3b[2] = null; 590 checkArrayElementsEqual(exceedingRangeCopy, expected3b); 591 592 // Range starting after the end of the original array, must suceed for nullable arrays 593 MyInt[] farRangeCopy = (MyInt[]) Arrays.copyOfRange(myInts, myInts.length, myInts.length + 1); 594 MyInt[] expected3c = (MyInt[])ValueClass.newNullableAtomicArray(MyInt.class, 1); 595 expected3c[0] = null; 596 checkArrayElementsEqual(farRangeCopy, expected3c); 597 598 Arrays.sort(copyMyInts); 599 expected = (MyInt[])ValueClass.newNullableAtomicArray(MyInt.class, 3); 600 expected[0] = (MyInt) MyInt.MIN; 601 expected[1] = (MyInt) MyInt.ZERO; 602 expected[2] = (MyInt) MyInt.MAX; 603 checkArrayElementsEqual(copyMyInts, expected); 604 605 List myIntList = Arrays.asList(copyMyInts); 606 607 MyInt[] dest = (MyInt[])ValueClass.newNullableAtomicArray(MyInt.class, copyMyInts.length); 608 checkArrayElementsEqual(copyMyInts, myIntList.toArray(dest)); 609 // This next line needs testMixedLayoutArrays to work 610 checkArrayElementsEqual(copyMyInts, myIntList.toArray()); 611 612 // Sanity check j.u.ArrayList 613 ArrayList<MyInt> aList = new ArrayList<MyInt>(Arrays.asList(copyMyInts)); 614 assertTrue(aList.indexOf(MyInt.MIN) == 0, "Bad Index"); 615 assertTrue(aList.indexOf(MyInt.ZERO) == 1, "Bad Index"); 616 assertTrue(aList.indexOf(MyInt.MAX) == 2, "Bad Index"); 617 618 aList.remove(2); 619 aList.add(MyInt.create(5)); 620 } 621 622 void testObjectArrayOfInlines() { 623 testSanityObjectArrays(); 624 testMixedLayoutArrays(); 625 } 626 627 void testSanityObjectArrays() { 628 Object[] objects = new Object[2]; 629 assertTrue(objects[0] == null && objects[1] == null, "Not null ?"); 630 631 objects[0] = MyInt.create(1); 632 objects[1] = Integer.valueOf(2); 633 assertTrue(objects[0].equals(MyInt.create(1)), "Bad Value"); 634 assertTrue(objects[1].equals(Integer.valueOf(2)), "Bad Object"); 635 636 Comparable[] copyComparables = new Comparable[objects.length]; 637 System.arraycopy(objects, 0, copyComparables, 0, objects.length); 638 checkArrayElementsEqual(objects, copyComparables); 639 640 objects[0] = null; 641 objects[1] = null; 642 assertTrue(objects[0] == null && objects[1] == null, "Not null ?"); 643 644 Comparable[] comparables = new Comparable[2]; 645 assertTrue(comparables[0] == null && comparables[1] == null, "Not null ?"); 646 comparables[0] = MyInt.create(3); 647 comparables[1] = Integer.valueOf(4); 648 assertTrue(comparables[0].equals(MyInt.create(3)), "Bad Value"); 649 assertTrue(comparables[1].equals(Integer.valueOf(4)), "Bad Object"); 650 651 Object[] copyObjects = new Object[2]; 652 System.arraycopy(comparables, 0, copyObjects, 0, comparables.length); 653 checkArrayElementsEqual(comparables, copyObjects); 654 655 comparables[0] = null; 656 comparables[1] = null; 657 assertTrue(comparables[0] == null && comparables[1] == null, "Not null ?"); 658 659 MyInt[] myIntRefArray = new MyInt[1]; 660 assertTrue(myIntRefArray[0] == null, "Got: " + myIntRefArray[0]); 661 myIntRefArray[0] = null; 662 663 MyInt[] srcNulls = new MyInt[2]; 664 MyInt[] dstNulls = new MyInt[2]; 665 System.arraycopy(srcNulls, 0, dstNulls, 0, 2); 666 checkArrayElementsEqual(srcNulls, dstNulls); 667 srcNulls[1] = MyInt.create(1); 668 System.arraycopy(srcNulls, 0, dstNulls, 0, 2); 669 checkArrayElementsEqual(srcNulls, dstNulls); 670 671 672 // Locked/unlocked flat array type checks 673 synchronized (srcNulls) { 674 System.arraycopy(srcNulls, 0, dstNulls, 0, 2); 675 checkArrayElementsEqual(srcNulls, dstNulls); 676 System.gc(); 677 } 678 System.gc(); 679 checkArrayElementsEqual(srcNulls, dstNulls); 680 } 681 682 void testMixedLayoutArrays() { 683 Object[] objArray = new Object[3]; 684 Comparable[] compArray = new Comparable[3]; 685 MyInt[] valArray = new MyInt[] { (MyInt) MyInt.MIN, (MyInt) MyInt.ZERO, (MyInt) MyInt.MAX }; 686 687 arrayCopy(valArray, 0, objArray, 0, 3); 688 checkArrayElementsEqual(valArray, objArray); 689 arrayCopy(valArray, 0, objArray, 0, 3); 690 691 objArray = new Object[3]; 692 System.arraycopy(valArray, 0, objArray, 0, 3); 693 checkArrayElementsEqual(valArray, objArray); 694 695 System.arraycopy(valArray, 0, compArray, 0, 3); 696 checkArrayElementsEqual(valArray, compArray); 697 698 valArray = (MyInt[])ValueClass.newNullRestrictedNonAtomicArray(MyInt.class, 3, new MyInt()); 699 valArray[0] = (MyInt) MyInt.ZERO; 700 valArray[1] = (MyInt) MyInt.ZERO; 701 valArray[2] = (MyInt) MyInt.ZERO; 702 System.arraycopy(compArray, 0, valArray, 0, 3); 703 checkArrayElementsEqual(valArray, compArray); 704 705 valArray = (MyInt[])ValueClass.newNullRestrictedNonAtomicArray(MyInt.class, 3, new MyInt()); 706 valArray[0] = (MyInt) MyInt.ZERO; 707 valArray[1] = (MyInt) MyInt.ZERO; 708 valArray[2] = (MyInt) MyInt.ZERO; 709 System.arraycopy(objArray, 0, valArray, 0, 3); 710 checkArrayElementsEqual(valArray, objArray); 711 712 // Sanity check dst == src 713 System.arraycopy(valArray, 0, valArray, 0, 3); 714 checkArrayElementsEqual(valArray, objArray); 715 716 objArray[0] = "Not an inline object"; 717 try { 718 System.arraycopy(objArray, 0, valArray, 0, 3); 719 throw new RuntimeException("Expected ArrayStoreException"); 720 } catch (ArrayStoreException ase) {} 721 722 MyInt[] myIntRefArray = new MyInt[3]; 723 System.arraycopy(valArray, 0, myIntRefArray, 0, 3); 724 checkArrayElementsEqual(valArray, myIntRefArray); 725 726 myIntRefArray[0] = null; 727 try { 728 System.arraycopy(myIntRefArray, 0, valArray, 0, 3); 729 throw new RuntimeException("Expected NullPointerException"); 730 } catch (NullPointerException npe) {} 731 } 732 733 @LooselyConsistentValue 734 static value class MyPoint { 735 @Strict 736 @NullRestricted 737 MyInt x; 738 @Strict 739 @NullRestricted 740 MyInt y; 741 742 private MyPoint() { this(0, 0); } 743 private MyPoint(int x, int y) { 744 this.x = new MyInt(x); 745 this.y = new MyInt(y); 746 } 747 public boolean equals(Object that) { 748 if (that instanceof MyPoint) { 749 MyPoint thatPoint = (MyPoint) that; 750 return x.equals(thatPoint.x) && java.util.Objects.equals(y, thatPoint.y); 751 } 752 return false; 753 } 754 static MyPoint create(int x) { 755 return new MyPoint(x, x); 756 } 757 static MyPoint create(int x, int y) { 758 return new MyPoint(x, y); 759 } 760 @Strict 761 @NullRestricted 762 static final MyPoint ORIGIN = create(0); 763 } 764 765 void testComposition() { 766 // Test array operations with compostion of inline types, check element payload is correct... 767 MyPoint a = MyPoint.create(1, 2); 768 MyPoint b = MyPoint.create(7, 21); 769 MyPoint c = MyPoint.create(Integer.MAX_VALUE, Integer.MIN_VALUE); 770 771 MyPoint[] pts = (MyPoint[])ValueClass.newNullRestrictedNonAtomicArray(MyPoint.class, 3, new MyPoint()); 772 if (!pts[0].equals(MyPoint.ORIGIN)) { 773 throw new RuntimeException("Equals failed: " + pts[0] + " vs " + MyPoint.ORIGIN); 774 } 775 pts = (MyPoint[])ValueClass.newNullRestrictedNonAtomicArray(MyPoint.class, 3, new MyPoint()); 776 pts[0] = a; 777 pts[1] = b; 778 pts[2] = c; 779 checkArrayElementsEqual(pts, new Object[] { a, b, c}); 780 Object[] oarr = new Object[3]; 781 782 arrayCopy(pts, 0, oarr, 0, 3); 783 checkArrayElementsEqual(pts, oarr); 784 785 oarr = new Object[3]; 786 System.arraycopy(pts, 0, oarr, 0, 3); 787 checkArrayElementsEqual(pts, oarr); 788 789 System.arraycopy(oarr, 0, pts, 0, 3); 790 checkArrayElementsEqual(pts, oarr); 791 792 oarr = new Object[3]; 793 try { 794 System.arraycopy(oarr, 0, pts, 0, 3); 795 throw new RuntimeException("Expected NPE"); 796 } 797 catch (NullPointerException npe) {} 798 799 oarr = new Object[3]; 800 oarr[0] = new Object(); 801 try { 802 System.arraycopy(oarr, 0, pts, 0, 3); 803 throw new RuntimeException("Expected ASE"); 804 } 805 catch (ArrayStoreException ase) {} 806 } 807 808 void checkArrayElementsEqual(MyInt[] arr1, Object[] arr2) { 809 assertTrue(arr1.length == arr2.length, "Bad length"); 810 for (int i = 0; i < arr1.length; i++) { 811 assertTrue(java.util.Objects.equals(arr1[i], arr2[i]), "Element " + i + " not equal"); 812 } 813 } 814 815 void checkArrayElementsEqual(MyPoint[] arr1, Object[] arr2) { 816 assertTrue(arr1.length == arr2.length, "Bad length"); 817 for (int i = 0; i < arr1.length; i++) { 818 assertTrue(java.util.Objects.equals(arr1[i], arr2[i]), "Element " + i + " not equal"); 819 } 820 } 821 822 void checkArrayElementsEqual(Object[] arr1, Object[] arr2) { 823 assertTrue(arr1.length == arr2.length, "Bad length"); 824 for (int i = 0; i < arr1.length; i++) { 825 assertTrue(java.util.Objects.equals(arr1[i], arr2[i]), "Element " + i + " not equal"); 826 } 827 } 828 829 void arrayCopy(MyInt[] src, int srcPos, Object[] dst, int dstPos, int length) { 830 for (int i = 0; i < length ; i++) { 831 dst[dstPos++] = src[srcPos++]; 832 } 833 } 834 void arrayCopy(MyPoint[] src, int srcPos, Object[] dst, int dstPos, int length) { 835 for (int i = 0; i < length ; i++) { 836 dst[dstPos++] = src[srcPos++]; 837 } 838 } 839 840 Object getNull() { return null; } 841 842 843 void testInlineArrayOom() { 844 int size = Integer.MAX_VALUE; 845 try { 846 MyPoint[] pts = new MyPoint[size]; 847 throw new RuntimeException("Excepted OOM"); 848 } catch (OutOfMemoryError oom) {} 849 } 850 851 }