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