1 /* 2 * Copyright (c) 2018, 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 Value 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:+ValueArrayFlatten -XX:+EnableValhalla runtime.valhalla.valuetypes.ValueTypeArray 39 * @run main/othervm -Xint -XX:-ValueArrayFlatten -XX:+EnableValhalla runtime.valhalla.valuetypes.ValueTypeArray 40 * @run main/othervm -Xcomp -XX:+ValueArrayFlatten -XX:+EnableValhalla runtime.valhalla.valuetypes.ValueTypeArray 41 * @run main/othervm -Xcomp -XX:-ValueArrayFlatten -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 try { 67 Class<?> arrayCls = Class.forName(arrayClsName); 68 assertTrue(arrayCls.isArray(), "Expected an array class"); 69 assertTrue(arrayCls.getComponentType() == Point.class, 70 "Expected component type of Point.class"); 71 72 arrayClsName = "[" + arrayClsName; 73 Class<?> mulArrayCls = Class.forName(arrayClsName); 74 assertTrue(mulArrayCls.isArray()); 75 assertTrue(mulArrayCls.getComponentType() == arrayCls); 76 } 77 catch (ClassNotFoundException cnfe) { 78 fail("Class.forName(" + arrayClsName + ") failed", cnfe); 79 } 80 } 81 82 void testSimplePointArray() { 83 Point[] defaultPoint = new Point[1]; 84 Point p = defaultPoint[0]; 85 assertEquals(p.x, 0, "invalid default loaded from array"); 86 assertEquals(p.y, 0, "invalid default loaded from array"); 87 boolean gotNpe = false; 88 try { 89 defaultPoint[0] = (Point) getNull(); 90 } catch (NullPointerException npe) { 91 gotNpe = true; 92 } 93 assertTrue(gotNpe, "Expected NullPointerException"); 94 95 Point[] points = createSimplePointArray(); 96 checkSimplePointArray(points); 97 System.gc(); // check that VTs survive GC 98 99 assertTrue(points instanceof Point[], "Instance of"); 100 101 Point[] pointsCopy = new Point[points.length]; 102 System.arraycopy(points, 0, pointsCopy, 0, points.length); 103 checkSimplePointArray(pointsCopy); 104 } 105 106 static Point[] createSimplePointArray() { 107 Point[] ps = new Point[2]; 108 assertEquals(ps.length, 2, "Length"); 109 ps.toString(); 110 ps[0] = Point.createPoint(1, 2); 111 ps[1] = Point.createPoint(3, 4); 112 boolean sawOob = false; 113 try { 114 ps[2] = Point.createPoint(0, 0); 115 } catch (ArrayIndexOutOfBoundsException aioobe) { sawOob = true; } 116 assertTrue(sawOob, "Didn't see AIOOBE"); 117 System.gc(); // check that VTs survive GC 118 return ps; 119 } 120 121 static void checkSimplePointArray(Point[] points) { 122 assertEquals(points[0].x, 1, "invalid 0 point x value"); 123 assertEquals(points[0].y, 2, "invalid 0 point y value"); 124 assertEquals(points[1].x, 3, "invalid 1 point x value"); 125 assertEquals(points[1].y, 4, "invalid 1 point y value"); 126 } 127 128 void testLong8Array() { 129 Long8Value[] values = new Long8Value[3]; 130 assertEquals(values.length, 3, "length"); 131 values.toString(); 132 Long8Value value = values[1]; 133 long zl = 0; 134 Long8Value.check(value, zl, zl, zl, zl, zl, zl, zl, zl); 135 values[1] = Long8Value.create(1, 2, 3, 4, 5, 6, 7, 8); 136 value = values[1]; 137 Long8Value.check(value, 1, 2, 3, 4, 5, 6, 7, 8); 138 139 Long8Value[] copy = new Long8Value[values.length]; 140 System.arraycopy(values, 0, copy, 0, values.length); 141 value = copy[1]; 142 Long8Value.check(value, 1, 2, 3, 4, 5, 6, 7, 8); 143 } 144 145 void testMixedPersonArray() { 146 Person[] people = new Person[3]; 147 148 people[0] = Person.create(1, "First", "Last"); 149 assertEquals(people[0].getId(), 1, "Invalid Id person"); 150 assertEquals(people[0].getFirstName(), "First", "Invalid First Name"); 151 assertEquals(people[0].getLastName(), "Last", "Invalid Last Name"); 152 153 people[1] = Person.create(2, "Jane", "Wayne"); 154 people[2] = Person.create(3, "Bob", "Dobalina"); 155 156 Person[] peopleCopy = new Person[people.length]; 157 System.arraycopy(people, 0, peopleCopy, 0, people.length); 158 assertEquals(peopleCopy[2].getId(), 3, "Invalid Id"); 159 assertEquals(peopleCopy[2].getFirstName(), "Bob", "Invalid First Name"); 160 assertEquals(peopleCopy[2].getLastName(), "Dobalina", "Invalid Last Name"); 161 } 162 163 void testMultiDimPointArray() { 164 Point[][][] multiPoints = new Point[2][3][4]; 165 assertEquals(multiPoints.length, 2, "1st dim length"); 166 assertEquals(multiPoints[0].length, 3, "2st dim length"); 167 assertEquals(multiPoints[0][0].length, 4, "3rd dim length"); 168 169 Point defaultPoint = multiPoints[1][2][3]; 170 assertEquals(defaultPoint.x, 0, "invalid point x value"); 171 assertEquals(defaultPoint.y, 0, "invalid point x value"); 172 } 173 174 void testReflectArray() { 175 // Check the java.lang.reflect.Array.newInstance methods... 176 Class<?> cls = (Class<?>) Point[].class; 177 Point[][] array = (Point[][]) Array.newInstance(cls, 1); 178 assertEquals(array.length, 1, "Incorrect length"); 179 assertTrue(array[0] == null, "Expected NULL"); 180 181 Point[][][] array3 = (Point[][][]) Array.newInstance(cls, 1, 2); 182 assertEquals(array3.length, 1, "Incorrect length"); 183 assertEquals(array3[0].length, 2, "Incorrect length"); 184 assertTrue(array3[0][0] == null, "Expected NULL"); 185 186 // Now create ObjArrays of ValueArray... 187 cls = (Class<?>) Point.class; 188 array = (Point[][]) Array.newInstance(cls, 1, 2); 189 assertEquals(array.length, 1, "Incorrect length"); 190 assertEquals(array[0].length, 2, "Incorrect length"); 191 Point p = array[0][1]; 192 int x = p.x; 193 assertEquals(x, 0, "Bad Point Value"); 194 } 195 196 static final value class MyInt implements Comparable<MyInt> { 197 final int value; 198 199 private MyInt() { value = 0; } 200 public int getValue() { return value; } 201 public String toString() { return "MyInt: " + getValue(); } 202 public int compareTo(MyInt that) { return Integer.compare(this.getValue(), that.getValue()); } 203 public boolean equals(Object o) { 204 if (o instanceof MyInt) { 205 return this.getValue() == ((MyInt) o).getValue(); 206 } 207 return false; 208 } 209 210 public static MyInt create(int v) { 211 MyInt mi = MyInt.default; 212 mi = __WithField(mi.value, v); 213 return mi; 214 } 215 216 public static final MyInt.box MIN = MyInt.create(Integer.MIN_VALUE); 217 public static final MyInt.box ZERO = MyInt.create(0); 218 public static final MyInt.box MAX = MyInt.create(Integer.MAX_VALUE); 219 } 220 221 static interface SomeSecondaryType { 222 default String hi() { return "Hi"; } 223 } 224 225 static final value class MyOtherInt implements SomeSecondaryType { 226 final int value; 227 private MyOtherInt() { value = 0; } 228 } 229 230 void testSanityCheckcasts() { 231 MyInt[] myInts = new MyInt[1]; 232 assertTrue(myInts instanceof Object[]); 233 assertTrue(myInts instanceof Comparable[]); 234 235 Object arrObj = Array.newInstance(MyInt.class, 1); 236 assertTrue(arrObj instanceof Object[], "Not Object array"); 237 assertTrue(arrObj instanceof Comparable[], "Not Comparable array"); 238 assertTrue(arrObj instanceof MyInt[], "Not MyInt array"); 239 240 Object[] arr = (Object[]) arrObj; 241 assertTrue(arr instanceof Comparable[], "Not Comparable array"); 242 assertTrue(arr instanceof MyInt[], "Not MyInt array"); 243 Comparable[] comparables = (Comparable[])arr; 244 MyInt[] myIntArr = (MyInt[]) arr; 245 246 // multi-dim, check secondary array types are setup... 247 MyOtherInt[][] matrix = new MyOtherInt[1][1]; 248 assertTrue(matrix[0] instanceof MyOtherInt[]); 249 assertTrue(matrix[0] instanceof SomeSecondaryType[]); 250 } 251 252 void testUtilArrays() { 253 // Sanity check j.u.Arrays 254 MyInt[] myInts = new MyInt[] { MyInt.MAX, MyInt.MIN }; 255 // Sanity sort another copy 256 MyInt[] copyMyInts = Arrays.copyOf(myInts, myInts.length + 1); 257 checkArrayElementsEqual(copyMyInts, new MyInt[] { myInts[0], myInts[1], MyInt.ZERO}); 258 259 Arrays.sort(copyMyInts); 260 checkArrayElementsEqual(copyMyInts, new MyInt[] { MyInt.MIN, MyInt.ZERO, MyInt.MAX }); 261 262 List myIntList = Arrays.asList(copyMyInts); 263 checkArrayElementsEqual(copyMyInts, myIntList.toArray(new MyInt[copyMyInts.length])); 264 // This next line needs testMixedLayoutArrays to work 265 checkArrayElementsEqual(copyMyInts, myIntList.toArray()); 266 267 // Sanity check j.u.ArrayList 268 ArrayList<MyInt> aList = new ArrayList<MyInt>(Arrays.asList(copyMyInts)); 269 assertTrue(aList.indexOf(MyInt.MIN) == 0, "Bad Index"); 270 assertTrue(aList.indexOf(MyInt.ZERO) == 1, "Bad Index"); 271 assertTrue(aList.indexOf(MyInt.MAX) == 2, "Bad Index"); 272 273 aList.remove(2); 274 aList.add(MyInt.create(5)); 275 276 // Interesting: 277 //aList.add((MyInt)getNull()); 278 279 // javac currently generating "java/util/Objects.requireNonNull 280 // should checkcast treat null against Value class as CCE ? 281 // Then in the end, ArrayList.elementData is Object[], (that's why remove works) 282 // why can't I write add(null) then ? 283 } 284 285 void testObjectArrayOfValues() { 286 testSanityObjectArrays(); 287 testMixedLayoutArrays(); 288 } 289 290 void testSanityObjectArrays() { 291 Object[] objects = new Object[2]; 292 assertTrue(objects[0] == null && objects[1] == null, "Not null ?"); 293 294 objects[0] = MyInt.create(1); 295 objects[1] = Integer.valueOf(2); 296 assertTrue(objects[0].equals(MyInt.create(1)), "Bad Value"); 297 assertTrue(objects[1].equals(Integer.valueOf(2)), "Bad Object"); 298 299 Comparable[] copyComparables = new Comparable[objects.length]; 300 System.arraycopy(objects, 0, copyComparables, 0, objects.length); 301 checkArrayElementsEqual(objects, copyComparables); 302 303 objects[0] = null; 304 objects[1] = null; 305 assertTrue(objects[0] == null && objects[1] == null, "Not null ?"); 306 307 Comparable[] comparables = new Comparable[2]; 308 assertTrue(comparables[0] == null && comparables[1] == null, "Not null ?"); 309 comparables[0] = MyInt.create(3); 310 comparables[1] = Integer.valueOf(4); 311 assertTrue(comparables[0].equals(MyInt.create(3)), "Bad Value"); 312 assertTrue(comparables[1].equals(Integer.valueOf(4)), "Bad Object"); 313 314 Object[] copyObjects = new Object[2]; 315 System.arraycopy(comparables, 0, copyObjects, 0, comparables.length); 316 checkArrayElementsEqual(comparables, copyObjects); 317 318 comparables[0] = null; 319 comparables[1] = null; 320 assertTrue(comparables[0] == null && comparables[1] == null, "Not null ?"); 321 } 322 323 void testMixedLayoutArrays() { 324 Object[] objArray = new Object[3]; 325 Comparable[] compArray = new Comparable[3]; 326 MyInt[] valArray = new MyInt[] { MyInt.MIN, MyInt.ZERO, MyInt.MAX }; 327 328 arrayCopy(valArray, 0, objArray, 0, 3); 329 checkArrayElementsEqual(valArray, objArray); 330 arrayCopy(valArray, 0, objArray, 0, 3); 331 332 objArray = new Object[3]; 333 System.arraycopy(valArray, 0, objArray, 0, 3); 334 checkArrayElementsEqual(valArray, objArray); 335 336 System.arraycopy(valArray, 0, compArray, 0, 3); 337 checkArrayElementsEqual(valArray, compArray); 338 339 valArray = new MyInt[] { MyInt.ZERO, MyInt.ZERO, MyInt.ZERO }; 340 System.arraycopy(compArray, 0, valArray, 0, 3); 341 checkArrayElementsEqual(valArray, compArray); 342 343 valArray = new MyInt[] { MyInt.ZERO, MyInt.ZERO, MyInt.ZERO }; 344 System.arraycopy(objArray, 0, valArray, 0, 3); 345 checkArrayElementsEqual(valArray, objArray); 346 347 // Sanity check dst == src 348 System.arraycopy(valArray, 0, valArray, 0, 3); 349 checkArrayElementsEqual(valArray, objArray); 350 351 objArray[0] = "Not a value object"; 352 try { 353 System.arraycopy(objArray, 0, valArray, 0, 3); 354 throw new RuntimeException("Expected ArrayStoreException"); 355 } catch (ArrayStoreException ase) {} 356 } 357 358 static final value class MyPoint { 359 final MyInt.val x; 360 final MyInt y; 361 362 private MyPoint() { 363 x = MyInt.ZERO; 364 y = x; 365 } 366 public boolean equals(Object that) { 367 if (that instanceof MyPoint) { 368 MyPoint thatPoint = (MyPoint) that; 369 return x.equals(thatPoint.x) && java.util.Objects.equals(y, thatPoint.y); 370 } 371 return false; 372 } 373 static MyPoint create(int x) { 374 MyPoint mp = MyPoint.default; 375 mp = __WithField(mp.x, MyInt.create(x)); 376 return mp; 377 } 378 static MyPoint create(int x, int y) { 379 MyPoint mp = MyPoint.default; 380 mp = __WithField(mp.x, MyInt.create(x)); 381 mp = __WithField(mp.y, MyInt.create(y)); 382 return mp; 383 } 384 static final MyPoint.box ORIGIN = create(0); 385 } 386 387 void testComposition() { 388 // Test array operations with compostion of values, check element payload is correct... 389 MyPoint a = MyPoint.create(1, 2); 390 MyPoint b = MyPoint.create(7, 21); 391 MyPoint c = MyPoint.create(Integer.MAX_VALUE, Integer.MIN_VALUE); 392 393 MyPoint[] pts = new MyPoint[3]; 394 if (!pts[0].equals(MyPoint.ORIGIN)) { 395 throw new RuntimeException("Equals failed: " + pts[0] + " vs " + MyPoint.ORIGIN); 396 } 397 pts = new MyPoint[] { a, b, c }; 398 checkArrayElementsEqual(pts, new Object[] { a, b, c}); 399 Object[] oarr = new Object[3]; 400 401 arrayCopy(pts, 0, oarr, 0, 3); 402 checkArrayElementsEqual(pts, oarr); 403 404 oarr = new Object[3]; 405 System.arraycopy(pts, 0, oarr, 0, 3); 406 checkArrayElementsEqual(pts, oarr); 407 408 System.arraycopy(oarr, 0, pts, 0, 3); 409 checkArrayElementsEqual(pts, oarr); 410 411 oarr = new Object[3]; 412 try { 413 System.arraycopy(oarr, 0, pts, 0, 3); 414 throw new RuntimeException("Expected NPE"); 415 } 416 catch (NullPointerException npe) {} 417 418 oarr = new Object[3]; 419 oarr[0] = new Object(); 420 try { 421 System.arraycopy(oarr, 0, pts, 0, 3); 422 throw new RuntimeException("Expected ASE"); 423 } 424 catch (ArrayStoreException ase) {} 425 } 426 427 void checkArrayElementsEqual(Object[] arr1, Object[] arr2) { 428 assertTrue(arr1.length == arr2.length, "Bad length"); 429 for (int i = 0; i < arr1.length; i++) { 430 assertTrue(java.util.Objects.equals(arr1[i], arr2[i]), "Element " + i + " not equal"); 431 } 432 } 433 434 void arrayCopy(Object[] src, int srcPos, Object[] dst, int dstPos, int length) { 435 for (int i = 0; i < length ; i++) { 436 dst[dstPos++] = src[srcPos++]; 437 } 438 } 439 440 Object getNull() { return null; } 441 442 }