--- old/test/jdk/valhalla/valuetypes/ArrayElementVarHandleTest.java 2019-05-10 13:18:33.689909954 -0400 +++ new/test/jdk/valhalla/valuetypes/ArrayElementVarHandleTest.java 2019-05-10 13:18:33.317908109 -0400 @@ -44,6 +44,11 @@ private static final Line L = Line.makeLine(10, 20, 30, 40); private static final MutablePath PATH = MutablePath.makePath(10, 20, 30, 40); + private static Class nullablePointArrayClass() { + Object a = new Point?[0]; + return a.getClass(); + } + @DataProvider(name="arrayTests") static Object[][] arrayTests() { return new Object[][]{ @@ -54,6 +59,10 @@ new Object[] { Point[][].class, new Point[][] { new Point[] { Point.makePoint(1, 2), Point.makePoint(10, 20)}}}, + new Object[] { nullablePointArrayClass(), + new Point?[] { Point.makePoint(11, 22), + Point.makePoint(110, 220), + null}}, new Object[] { Line[].class, new Line[] { Line.makeLine(1, 2, 3, 4), Line.makeLine(10, 20, 30, 40), --- old/test/jdk/valhalla/valuetypes/MethodHandleTest.java 2019-05-10 13:18:37.201927369 -0400 +++ new/test/jdk/valhalla/valuetypes/MethodHandleTest.java 2019-05-10 13:18:36.797925365 -0400 @@ -119,10 +119,12 @@ assertEquals(v, o); } - // set an array element to null Class elementType = c.getComponentType(); + if (elementType.isValue()) { + assertTrue(elementType == elementType.asValueType()); + } + // set an array element to null try { - // inline array element is flattenable Object v = (Object)setter.invoke(array, 0, null); assertFalse(elementType.isValue(), "should fail to set an inline class array element to null"); } catch (NullPointerException e) { @@ -130,6 +132,22 @@ } } + @Test + public static void testNullableArray() throws Throwable { + Class arrayClass = (new Point?[0]).getClass(); + Class elementType = arrayClass.getComponentType(); + assertTrue(elementType == Point.class.asBoxType()); + + MethodHandle setter = MethodHandles.arrayElementSetter(arrayClass); + MethodHandle getter = MethodHandles.arrayElementGetter(arrayClass); + MethodHandle ctor = MethodHandles.arrayConstructor(arrayClass); + Object[] array = (Object[]) ctor.invoke(2); + setter.invoke(array, 0, P); + setter.invoke(array, 1, null); + assertEquals((Point)getter.invoke(array, 0), P); + assertNull((Object)getter.invoke(array, 1)); + } + private final Class c; private final Object o; private final List names; --- old/test/jdk/valhalla/valuetypes/ValueArray.java 2019-05-10 13:18:38.361933121 -0400 +++ new/test/jdk/valhalla/valuetypes/ValueArray.java 2019-05-10 13:18:37.985931256 -0400 @@ -30,7 +30,7 @@ * @run testng/othervm -XX:+EnableValhalla -XX:ValueArrayElemMaxFlatSize=0 ValueArray */ -import java.lang.reflect.*; +import java.lang.reflect.Array; import java.util.Arrays; import org.testng.annotations.BeforeTest; @@ -39,6 +39,11 @@ import static org.testng.Assert.*; public class ValueArray { + private static Class nullablePointArrayClass() { + Object a = new Point?[0]; + return a.getClass(); + } + @DataProvider(name="arrayTypes") static Object[][] arrayTypes() { return new Object[][] { @@ -51,7 +56,10 @@ new Object[] { Point[][].class, new Point[][] { new Point[] { Point.makePoint(1, 2), Point.makePoint(10, 20)}}}, - + new Object[] { nullablePointArrayClass(), + new Point?[] { Point.makePoint(11, 22), + Point.makePoint(110, 220), + null}}, new Object[] { NonFlattenValue[].class, new NonFlattenValue[] { NonFlattenValue.make(1, 2), NonFlattenValue.make(10, 20), @@ -59,12 +67,14 @@ }; } + @Test(dataProvider="arrayTypes") public static void test(Class c, Object[] elements) { ValueArray test = new ValueArray(c, elements.length); test.run(elements); - if (c.getComponentType().isValue()) { - test.ensureNonNullable(); + Class compType = c.getComponentType(); + if (compType.isValue()) { + test.testSetNullElement(compType == compType.asBoxType()); } } @@ -76,6 +86,17 @@ } @Test + public static void testNullablePointArray() { + Point ?[]array = new Point ?[3]; + array[0] = Point.makePoint(1, 2); + array[1] = null; + array[2] = Point.makePoint(3, 4); + + ValueArray test = new ValueArray(array); + test.run(null, Point.makePoint(3, 4), null); + } + + @Test public static void testIntArray() { int[] array = new int[] { 1, 2, 3}; for (int i=0; i < array.length; i++) { @@ -103,11 +124,53 @@ } catch (IllegalArgumentException e) {} } + + @Test() + static void testArrayCovariance() { + Point[] lArray = new Point[0]; + Point?[] qArray = new Point?[0]; + + // language instanceof + assertTrue(lArray instanceof Point[]); + assertTrue(qArray instanceof Point?[]); + + // Class.instanceOf (self) + assertTrue(lArray.getClass().isInstance(lArray)); + assertTrue(qArray.getClass().isInstance(qArray)); + + // Class.instanceof inline vs indirect + assertFalse(lArray.getClass().isInstance(qArray)); + assertTrue(qArray.getClass().isInstance(lArray)); + + // Class.isAssignableFrom (self) + assertTrue(lArray.getClass().isAssignableFrom(lArray.getClass())); + assertTrue(qArray.getClass().isAssignableFrom(qArray.getClass())); + + // Class.isAssignableFrom inline vs indirect + assertTrue(qArray.getClass().isAssignableFrom(lArray.getClass())); + assertFalse(lArray.getClass().isAssignableFrom(qArray.getClass())); + + // Class.cast (self) + lArray.getClass().cast(lArray); + qArray.getClass().cast(qArray); + + // Class.cast inline vs indirect + qArray.getClass().cast(lArray); + try { + lArray.getClass().cast(qArray); + fail("cast of Point? to Point should not succeed"); + } catch (ClassCastException cce) { + // expected + } + } + private final Object[] array; + ValueArray(Class arrayClass, int len) { this((Object[])Array.newInstance(arrayClass.getComponentType(), len)); assertTrue(array.getClass() == arrayClass); } + ValueArray(Object[] array) { this.array = array; } @@ -125,28 +188,31 @@ Arrays.setAll(array, i -> elements[i]); } - void ensureNonNullable() { + void testSetNullElement(boolean nullable) { assert(array.getClass().getComponentType().isValue()); for (int i=0; i < array.length; i++) { try { Array.set(array, i, null); - throw new AssertionError("NPE not thrown"); - } catch (NullPointerException e) {} + if (!nullable) + throw new AssertionError("NPE not thrown"); + } catch (NullPointerException e) { + assertFalse(nullable); + } } } - static inline class PointArray { - public Point?[] points; + static inline class PointArray { + public Point[] points; PointArray() { - points = new Point?[0]; + points = new Point[0]; } public static PointArray makeArray(Point... points) { PointArray a = PointArray.default; - Point?[] boxArray = new Point?[points.length]; + Point[] array = new Point[points.length]; for (int i=0; i < points.length; i++) { - boxArray[i] = points[i]; + array[i] = points[i]; } - a = __WithField(a.points, boxArray); + a = __WithField(a.points, array); return a; } }