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