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