1 /*
  2  * Copyright (c) 2018, 2022, 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 java.lang.reflect.Array;
 27 import java.util.Arrays;
 28 import java.util.ArrayList;
 29 import java.util.List;
 30 
 31 import jdk.internal.value.PrimitiveClass;
 32 
 33 import static jdk.test.lib.Asserts.*;
 34 
 35 /*
 36  * @test InlineTypeArray
 37  * @summary Plain array test for Inline Types
 38  * @modules java.base/jdk.internal.value
 39  * @library /test/lib
 40  * @compile -XDenablePrimitiveClasses InlineTypeArray.java Point.java Long8Inline.java Person.java
 41  * @run main/othervm -XX:+EnableValhalla -XX:+EnablePrimitiveClasses -XX:FlatArrayElementMaxSize=-1 runtime.valhalla.inlinetypes.InlineTypeArray
 42  * @run main/othervm -XX:+EnableValhalla -XX:+EnablePrimitiveClasses -XX:FlatArrayElementMaxSize=0  runtime.valhalla.inlinetypes.InlineTypeArray
 43  * @run main/othervm -XX:+EnableValhalla -XX:+EnablePrimitiveClasses -XX:+UnlockDiagnosticVMOptions -XX:ForceNonTearable=* runtime.valhalla.inlinetypes.InlineTypeArray
 44  */
 45 public class InlineTypeArray {
 46     public static void main(String[] args) {
 47         InlineTypeArray inlineTypeArray = new InlineTypeArray();
 48         inlineTypeArray.run();
 49     }
 50 
 51     public void run() {
 52         testClassForName();
 53         testSimplePointArray();
 54         testLong8Array();
 55         testMixedPersonArray();
 56         testMultiDimPointArray();
 57         testComposition();
 58 
 59         testSanityCheckcasts();
 60         testObjectArrayOfInlines();
 61 
 62         testReflectArray();
 63         testUtilArrays();
 64 
 65         testInlineArrayOom();
 66     }
 67 
 68     void testClassForName() {
 69         String arrayClsName = "[Lruntime.valhalla.inlinetypes.Point;";
 70         String qarrayClsName = "[Qruntime.valhalla.inlinetypes.Point;";
 71         try {
 72             // L-type..
 73             Class<?> arrayCls = Class.forName(arrayClsName);
 74             assertTrue(arrayCls.isArray(), "Expected an array class");
 75 
 76             arrayClsName = "[" + arrayClsName;
 77             Class<?> mulArrayCls = Class.forName(arrayClsName);
 78             assertTrue(mulArrayCls.isArray());
 79             assertTrue(mulArrayCls.getComponentType() == arrayCls);
 80 
 81             // Q-type...
 82             arrayCls = Class.forName(qarrayClsName);
 83             assertTrue(arrayCls.isArray(), "Expected an array class");
 84 
 85             assertTrue(arrayCls.getComponentType() == PrimitiveClass.asValueType(Point.class),
 86                        arrayCls +
 87                        " Expected component type of Point.class got: " + arrayCls.getComponentType());
 88 
 89             qarrayClsName = "[" + qarrayClsName;
 90             mulArrayCls = Class.forName(qarrayClsName);
 91             assertTrue(mulArrayCls.isArray());
 92             assertTrue(mulArrayCls.getComponentType() == arrayCls);
 93         }
 94         catch (ClassNotFoundException cnfe) {
 95             fail("Class.forName(" + arrayClsName + ") failed", cnfe);
 96         }
 97     }
 98 
 99     void testSimplePointArray() {
100         Point[] defaultPoint = new Point[1];
101         Point p = defaultPoint[0];
102         assertEquals(p.x, 0, "invalid default loaded from array");
103         assertEquals(p.y, 0, "invalid default loaded from array");
104         boolean gotNpe = false;
105         try {
106             defaultPoint[0] = (Point) getNull();
107         } catch (NullPointerException npe) {
108             gotNpe = true;
109         }
110         assertTrue(gotNpe, "Expected NullPointerException");
111 
112         Point[] points = createSimplePointArray();
113         System.gc(); // check that VTs survive GC
114         checkSimplePointArray(points);
115         assertTrue(points instanceof Point[], "Instance of");
116 
117         testSimplePointArrayCopy();
118 
119         // Locked/unlocked flat array type checks
120         points = createSimplePointArray();
121         Point[] pointsCopy = new Point[points.length];
122         synchronized (points) {
123             assertTrue(points instanceof Point[], "Instance of");
124             checkSimplePointArray(points);
125             System.arraycopy(points, 0, pointsCopy, 0, points.length);
126             synchronized (pointsCopy) {
127                 assertTrue(pointsCopy instanceof Point[], "Instance of");
128                 checkSimplePointArray(pointsCopy);
129                 System.gc();
130             }
131             System.gc();
132         }
133         assertTrue(pointsCopy instanceof Point[], "Instance of");
134         checkSimplePointArray(pointsCopy);
135     }
136 
137     void testSimplePointArrayCopy() {
138         Point[] points = createSimplePointArray();
139         Point[] pointsCopy = new Point[points.length];
140         System.arraycopy(points, 0, pointsCopy, 0, points.length);
141         checkSimplePointArray(pointsCopy);
142 
143         // Conjoint, overlap...left
144         System.arraycopy(points, 0, points, 1, 2);
145         checkArrayElementsEqual(points, new Point[] { pointsCopy[0], pointsCopy[0], pointsCopy[1], pointsCopy[3] });
146 
147         // Conjoint, overlap...right
148         points = createSimplePointArray();
149         System.arraycopy(points, 2, points, 1, 2);
150         checkArrayElementsEqual(points, new Point[] { pointsCopy[0], pointsCopy[2], pointsCopy[3], pointsCopy[3] });
151     }
152 
153     static Point[] createSimplePointArray() {
154         Point[] ps = new Point[4];
155         assertEquals(ps.length, 4, "Length");
156         ps.toString();
157         ps[0] = new Point(1, 2);
158         ps[1] = new Point(3, 4);
159         ps[2] = new Point(5, 6);
160         ps[3] = new Point(7, 8);
161         boolean sawOob = false;
162         try {
163             ps[ps.length] = new Point(0, 0);
164         } catch (ArrayIndexOutOfBoundsException aioobe) { sawOob = true; }
165         assertTrue(sawOob, "Didn't see AIOOBE");
166         return ps;
167     }
168 
169     static void checkSimplePointArray(Point[] points) {
170         assertEquals(points[0].x, 1, "invalid 0 point x value");
171         assertEquals(points[0].y, 2, "invalid 0 point y value");
172         assertEquals(points[1].x, 3, "invalid 1 point x value");
173         assertEquals(points[1].y, 4, "invalid 1 point y value");
174         assertEquals(points[2].x, 5, "invalid 2 point x value");
175         assertEquals(points[2].y, 6, "invalid 2 point y value");
176         assertEquals(points[3].x, 7, "invalid 3 point x value");
177         assertEquals(points[3].y, 8, "invalid 3 point y value");
178     }
179 
180     void testLong8Array() {
181         Long8Inline[] values = new Long8Inline[3];
182         assertEquals(values.length, 3, "length");
183         values.toString();
184         Long8Inline value = values[1];
185         long zl = 0;
186         Long8Inline.check(value, zl, zl, zl, zl, zl, zl, zl, zl);
187         values[1] = new Long8Inline(1, 2, 3, 4, 5, 6, 7, 8);
188         value = values[1];
189         Long8Inline.check(value, 1, 2, 3, 4, 5, 6, 7, 8);
190 
191         Long8Inline[] copy = new Long8Inline[values.length];
192         System.arraycopy(values, 0, copy, 0, values.length);
193         value = copy[1];
194         Long8Inline.check(value, 1, 2, 3, 4, 5, 6, 7, 8);
195     }
196 
197     void testMixedPersonArray() {
198         Person[] people = new Person[3];
199 
200         people[0] = new Person(1, "First", "Last");
201         assertEquals(people[0].getId(), 1, "Invalid Id person");
202         assertEquals(people[0].getFirstName(), "First", "Invalid First Name");
203         assertEquals(people[0].getLastName(), "Last", "Invalid Last Name");
204 
205         people[1] = new Person(2, "Jane", "Wayne");
206         people[2] = new Person(3, "Bob", "Dobalina");
207 
208         Person[] peopleCopy = new Person[people.length];
209         System.arraycopy(people, 0, peopleCopy, 0, people.length);
210         assertEquals(peopleCopy[2].getId(), 3, "Invalid Id");
211         assertEquals(peopleCopy[2].getFirstName(), "Bob", "Invalid First Name");
212         assertEquals(peopleCopy[2].getLastName(), "Dobalina", "Invalid Last Name");
213     }
214 
215     void testMultiDimPointArray() {
216         Point[][][] multiPoints = new Point[2][3][4];
217         assertEquals(multiPoints.length, 2, "1st dim length");
218         assertEquals(multiPoints[0].length, 3, "2st dim length");
219         assertEquals(multiPoints[0][0].length, 4, "3rd dim length");
220 
221         Point defaultPoint = multiPoints[1][2][3];
222         assertEquals(defaultPoint.x, 0, "invalid point x value");
223         assertEquals(defaultPoint.y, 0, "invalid point x value");
224     }
225 
226     void testReflectArray() {
227         // Check the java.lang.reflect.Array.newInstance methods...
228         Class<?> cls = (Class<?>) Point[].class;
229         Point[][] array = (Point[][]) Array.newInstance(cls, 1);
230         assertEquals(array.length, 1, "Incorrect length");
231         assertTrue(array[0] == null, "Expected NULL");
232 
233         Point[][][] array3 = (Point[][][]) Array.newInstance(cls, 1, 2);
234         assertEquals(array3.length, 1, "Incorrect length");
235         assertEquals(array3[0].length, 2, "Incorrect length");
236         assertTrue(array3[0][0] == null, "Expected NULL");
237 
238         // Now create ObjArrays of InlineArray...
239         Point.ref[][] barray = (Point.ref[][]) Array.newInstance(Point.ref.class, 1, 2);
240         assertEquals(barray.length, 1, "Incorrect length");
241         assertEquals(barray[0].length, 2, "Incorrect length");
242         barray[0][1] = new Point(1, 2);
243         Point.ref pb = barray[0][1];
244         int x = pb.getX();
245         assertEquals(x, 1, "Bad Point Value");
246     }
247 
248     static final primitive class MyInt implements Comparable<MyInt.ref> {
249         final int value;
250 
251         private MyInt() { this(0); }
252         private MyInt(int v) { value = v; }
253         public int getValue() { return value; }
254         public String toString() { return "MyInt: " + getValue(); }
255         public int compareTo(MyInt.ref that) { return Integer.compare(this.getValue(), that.getValue()); }
256         public boolean equals(Object o) {
257             if (o instanceof MyInt) {
258                 return this.getValue() == ((MyInt) o).getValue();
259             }
260             return false;
261         }
262 
263         public static MyInt create(int v) {
264             return new MyInt(v);
265         }
266 
267         // Null-able fields here are a temp hack to avoid ClassCircularityError
268         public static final MyInt.ref MIN = MyInt.create(Integer.MIN_VALUE);
269         public static final MyInt.ref ZERO = MyInt.create(0);
270         public static final MyInt.ref MAX = MyInt.create(Integer.MAX_VALUE);
271     }
272 
273     static MyInt staticMyInt = MyInt.create(-1);
274     static MyInt[] staticMyIntArray = new MyInt[] { staticMyInt };
275     static MyInt[][] staticMyIntArrayArray = new MyInt[][] { staticMyIntArray, staticMyIntArray };
276 
277     static interface SomeSecondaryType {
278         default String hi() { return "Hi"; }
279     }
280 
281     static final primitive class MyOtherInt implements SomeSecondaryType {
282         final int value;
283         private MyOtherInt() { value = 0; }
284     }
285 
286     void testSanityCheckcasts() {
287         MyInt[] myInts = new MyInt[1];
288         assertTrue(myInts instanceof Object[]);
289         assertTrue(myInts instanceof Comparable[]);
290         assertTrue(myInts instanceof MyInt[]);
291 
292         Class<?> cls = PrimitiveClass.asValueType(MyInt.class);
293         assertTrue(PrimitiveClass.isPrimitiveValueType(cls));
294         Object arrObj = Array.newInstance(cls, 1);
295         assertTrue(arrObj instanceof Object[], "Not Object array");
296         assertTrue(arrObj instanceof Comparable[], "Not Comparable array");
297         assertTrue(arrObj instanceof MyInt[], "Not MyInt array");
298 
299         Object[] arr = (Object[]) arrObj;
300         assertTrue(arr instanceof Comparable[], "Not Comparable array");
301         assertTrue(arr instanceof MyInt[], "Not MyInt array");
302         Comparable[] comparables = (Comparable[])arr;
303         MyInt[] myIntArr = (MyInt[]) arr;
304 
305         // multi-dim, check secondary array types are setup...
306         MyOtherInt[][] matrix = new MyOtherInt[1][1];
307         assertTrue(matrix[0] instanceof MyOtherInt[]);
308         assertTrue(matrix[0] instanceof SomeSecondaryType[]);
309         assertTrue(matrix[0] instanceof MyOtherInt.ref[]);
310 
311         // Box types vs Inline...
312         MyInt.ref[] myValueRefs = new MyInt.ref[1];
313         assertTrue(myValueRefs instanceof MyInt.ref[]);
314         assertTrue(myValueRefs instanceof Object[]);
315         assertTrue(myValueRefs instanceof Comparable[]);
316         assertFalse(myValueRefs instanceof MyInt[]);
317 
318         MyInt.ref[][] myMdValueRefs = new MyInt.ref[1][1];
319         assertTrue(myMdValueRefs[0] instanceof MyInt.ref[]);
320         assertTrue(myMdValueRefs[0] instanceof Object[]);
321         assertTrue(myMdValueRefs[0] instanceof Comparable[]);
322         assertFalse(myMdValueRefs[0] instanceof MyInt[]);
323 
324         // Did we break checkcast...
325         MyInt.ref[]     va1 = (MyInt.ref[])null;
326         MyInt.ref[]     va2 = null;
327         MyInt.ref[][]   va3 = (MyInt.ref[][])null;
328         MyInt.ref[][][] va4 = (MyInt.ref[][][])null;
329         MyInt[]      va5 = null;
330         MyInt[]      va6 = (MyInt[])null;
331         MyInt[][]    va7 = (MyInt[][])null;
332         MyInt[][][]  va8 = (MyInt[][][])null;
333     }
334 
335 
336     void testUtilArrays() {
337         // Sanity check j.u.Arrays
338 
339         // cast to q-type temp effect of avoiding circularity error (decl static MyInt.ref)
340         MyInt[] myInts = new MyInt[] { (MyInt) MyInt.MAX, (MyInt) MyInt.MIN };
341         // Sanity sort another copy
342         MyInt[] copyMyInts = (MyInt[]) Arrays.copyOf(myInts, myInts.length + 1);
343         checkArrayElementsEqual(copyMyInts, new MyInt[] { myInts[0], myInts[1], (MyInt) MyInt.ZERO});
344 
345         Arrays.sort(copyMyInts);
346         checkArrayElementsEqual(copyMyInts, new MyInt[] { (MyInt) MyInt.MIN, (MyInt) MyInt.ZERO, (MyInt) MyInt.MAX });
347 
348         List myIntList = Arrays.asList(copyMyInts);
349         checkArrayElementsEqual(copyMyInts, myIntList.toArray(new MyInt[copyMyInts.length]));
350         // This next line needs testMixedLayoutArrays to work
351         checkArrayElementsEqual(copyMyInts, myIntList.toArray());
352 
353         // Sanity check j.u.ArrayList
354         ArrayList<MyInt.ref> aList = new ArrayList<MyInt.ref>(Arrays.asList(copyMyInts));
355         assertTrue(aList.indexOf(MyInt.MIN) == 0, "Bad Index");
356         assertTrue(aList.indexOf(MyInt.ZERO) == 1, "Bad Index");
357         assertTrue(aList.indexOf(MyInt.MAX) == 2, "Bad Index");
358 
359         aList.remove(2);
360         aList.add(MyInt.create(5));
361     }
362 
363 
364     void testObjectArrayOfInlines() {
365         testSanityObjectArrays();
366         testMixedLayoutArrays();
367     }
368 
369     void testSanityObjectArrays() {
370         Object[] objects = new Object[2];
371         assertTrue(objects[0] == null && objects[1] == null, "Not null ?");
372 
373         objects[0] = MyInt.create(1);
374         objects[1] = Integer.valueOf(2);
375         assertTrue(objects[0].equals(MyInt.create(1)), "Bad Value");
376         assertTrue(objects[1].equals(Integer.valueOf(2)), "Bad Object");
377 
378         Comparable[] copyComparables = new Comparable[objects.length];
379         System.arraycopy(objects, 0, copyComparables, 0, objects.length);
380         checkArrayElementsEqual(objects, copyComparables);
381 
382         objects[0] = null;
383         objects[1] = null;
384         assertTrue(objects[0] == null && objects[1] == null, "Not null ?");
385 
386         Comparable[] comparables = new Comparable[2];
387         assertTrue(comparables[0] == null && comparables[1] == null, "Not null ?");
388         comparables[0] = MyInt.create(3);
389         comparables[1] = Integer.valueOf(4);
390         assertTrue(comparables[0].equals(MyInt.create(3)), "Bad Value");
391         assertTrue(comparables[1].equals(Integer.valueOf(4)), "Bad Object");
392 
393         Object[] copyObjects = new Object[2];
394         System.arraycopy(comparables, 0, copyObjects, 0, comparables.length);
395         checkArrayElementsEqual(comparables, copyObjects);
396 
397         comparables[0] = null;
398         comparables[1] = null;
399         assertTrue(comparables[0] == null && comparables[1] == null, "Not null ?");
400 
401         MyInt.ref[] myIntRefArray = new MyInt.ref[1];
402         assertTrue(myIntRefArray[0] == null, "Got: " + myIntRefArray[0]);
403         myIntRefArray[0] = null;
404 
405         MyInt.ref[] srcNulls = new MyInt.ref[2];
406         MyInt.ref[] dstNulls = new MyInt.ref[2];
407         System.arraycopy(srcNulls, 0, dstNulls, 0, 2);
408         checkArrayElementsEqual(srcNulls, dstNulls);
409         srcNulls[1] = MyInt.create(1);
410         System.arraycopy(srcNulls, 0, dstNulls, 0, 2);
411         checkArrayElementsEqual(srcNulls, dstNulls);
412 
413 
414         // Locked/unlocked flat array type checks
415         synchronized (srcNulls) {
416             System.arraycopy(srcNulls, 0, dstNulls, 0, 2);
417             checkArrayElementsEqual(srcNulls, dstNulls);
418             System.gc();
419         }
420         System.gc();
421         checkArrayElementsEqual(srcNulls, dstNulls);
422     }
423 
424     void testMixedLayoutArrays() {
425         Object[] objArray = new Object[3];
426         Comparable[] compArray = new Comparable[3];
427         MyInt[] valArray = new MyInt[] { (MyInt) MyInt.MIN, (MyInt) MyInt.ZERO, (MyInt) MyInt.MAX };
428 
429         arrayCopy(valArray, 0, objArray, 0, 3);
430         checkArrayElementsEqual(valArray, objArray);
431         arrayCopy(valArray, 0, objArray, 0, 3);
432 
433         objArray = new Object[3];
434         System.arraycopy(valArray, 0, objArray, 0, 3);
435         checkArrayElementsEqual(valArray, objArray);
436 
437         System.arraycopy(valArray, 0, compArray, 0, 3);
438         checkArrayElementsEqual(valArray, compArray);
439 
440         valArray = new MyInt[] { (MyInt) MyInt.ZERO, (MyInt) MyInt.ZERO, (MyInt) MyInt.ZERO };
441         System.arraycopy(compArray, 0, valArray, 0, 3);
442         checkArrayElementsEqual(valArray, compArray);
443 
444         valArray = new MyInt[] { (MyInt) MyInt.ZERO, (MyInt) MyInt.ZERO, (MyInt) MyInt.ZERO };
445         System.arraycopy(objArray, 0, valArray, 0, 3);
446         checkArrayElementsEqual(valArray, objArray);
447 
448         // Sanity check dst == src
449         System.arraycopy(valArray, 0, valArray, 0, 3);
450         checkArrayElementsEqual(valArray, objArray);
451 
452         objArray[0] = "Not an inline object";
453         try {
454             System.arraycopy(objArray, 0, valArray, 0, 3);
455             throw new RuntimeException("Expected ArrayStoreException");
456         } catch (ArrayStoreException ase) {}
457 
458         MyInt.ref[] myIntRefArray = new MyInt.ref[3];
459         System.arraycopy(valArray, 0, myIntRefArray, 0, 3);
460         checkArrayElementsEqual(valArray, myIntRefArray);
461 
462         myIntRefArray[0] = null;
463         try {
464             System.arraycopy(myIntRefArray, 0, valArray, 0, 3);
465             throw new RuntimeException("Expected NullPointerException");
466         } catch (NullPointerException npe) {}
467     }
468 
469     static final primitive class MyPoint {
470         final               MyInt x;
471         final               MyInt y;
472 
473         private MyPoint() { this(0, 0); }
474         private MyPoint(int x, int y) {
475             this.x = new MyInt(x);
476             this.y = new MyInt(y);
477         }
478         public boolean equals(Object that) {
479             if (that instanceof MyPoint) {
480                 MyPoint thatPoint = (MyPoint) that;
481                 return x.equals(thatPoint.x) && java.util.Objects.equals(y, thatPoint.y);
482             }
483             return false;
484         }
485         static MyPoint create(int x) {
486             return new MyPoint(x, x);
487         }
488         static MyPoint create(int x, int y) {
489             return new MyPoint(x, y);
490         }
491         static final MyPoint.ref ORIGIN = create(0);
492     }
493 
494     void testComposition() {
495         // Test array operations with compostion of inline types, check element payload is correct...
496         MyPoint a = MyPoint.create(1, 2);
497         MyPoint b = MyPoint.create(7, 21);
498         MyPoint c = MyPoint.create(Integer.MAX_VALUE, Integer.MIN_VALUE);
499 
500         MyPoint[] pts = new MyPoint[3];
501         if (!pts[0].equals(MyPoint.ORIGIN)) {
502             throw new RuntimeException("Equals failed: " + pts[0] + " vs " + MyPoint.ORIGIN);
503         }
504         pts = new MyPoint[] { a, b, c };
505         checkArrayElementsEqual(pts, new Object[] { a, b, c});
506         Object[] oarr = new Object[3];
507 
508         arrayCopy(pts, 0, oarr, 0, 3);
509         checkArrayElementsEqual(pts, oarr);
510 
511         oarr = new Object[3];
512         System.arraycopy(pts, 0, oarr, 0, 3);
513         checkArrayElementsEqual(pts, oarr);
514 
515         System.arraycopy(oarr, 0, pts, 0, 3);
516         checkArrayElementsEqual(pts, oarr);
517 
518         oarr = new Object[3];
519         try {
520             System.arraycopy(oarr, 0, pts, 0, 3);
521             throw new RuntimeException("Expected NPE");
522         }
523         catch (NullPointerException npe) {}
524 
525         oarr = new Object[3];
526         oarr[0] = new Object();
527         try {
528             System.arraycopy(oarr, 0, pts, 0, 3);
529             throw new RuntimeException("Expected ASE");
530         }
531         catch (ArrayStoreException ase) {}
532     }
533 
534     void checkArrayElementsEqual(MyInt[] arr1, Object[] arr2) {
535         assertTrue(arr1.length == arr2.length, "Bad length");
536         for (int i = 0; i < arr1.length; i++) {
537             assertTrue(java.util.Objects.equals(arr1[i], arr2[i]), "Element " + i + " not equal");
538         }
539     }
540 
541     void checkArrayElementsEqual(MyPoint[] arr1, Object[] arr2) {
542         assertTrue(arr1.length == arr2.length, "Bad length");
543         for (int i = 0; i < arr1.length; i++) {
544             assertTrue(java.util.Objects.equals(arr1[i], arr2[i]), "Element " + i + " not equal");
545         }
546     }
547 
548     void checkArrayElementsEqual(Object[] arr1, Object[] arr2) {
549         assertTrue(arr1.length == arr2.length, "Bad length");
550         for (int i = 0; i < arr1.length; i++) {
551             assertTrue(java.util.Objects.equals(arr1[i], arr2[i]), "Element " + i + " not equal");
552         }
553     }
554 
555     void arrayCopy(MyInt[] src, int srcPos, Object[] dst, int dstPos, int length) {
556         for (int i = 0; i < length ; i++) {
557             dst[dstPos++] = src[srcPos++];
558         }
559     }
560     void arrayCopy(MyPoint[] src, int srcPos, Object[] dst, int dstPos, int length) {
561         for (int i = 0; i < length ; i++) {
562             dst[dstPos++] = src[srcPos++];
563         }
564     }
565 
566     Object getNull() { return null; }
567 
568 
569     void testInlineArrayOom() {
570         int size = Integer.MAX_VALUE;
571         try {
572             MyPoint[] pts = new MyPoint[size];
573             throw new RuntimeException("Excepted OOM");
574         } catch (OutOfMemoryError oom) {}
575     }
576 
577 }