--- /dev/null 2017-05-05 06:40:48.273288351 -0700 +++ new/test/hotspot/jtreg/runtime/valhalla/valuetypes/consistency/ConsistencyTest.java 2018-07-18 10:23:20.087871992 -0700 @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @summary Test for value types consistency checks + * + * @comment CASE [A] ConsistencyTest.java uses Point as a VT, but Mismatched.java uses Point as a POJO Type. + * @compile -XDenableValueTypes -XDallowFlattenabilityModifiers ConsistencyTest.java POJOPoint.java Mismatched.java + * @compile -XDenableValueTypes -XDallowFlattenabilityModifiers ConsistencyTest.java ValuePoint.java + * @run main/othervm -Xint -XX:+EnableValhalla ConsistencyTest + * @run main/othervm -Xcomp -XX:+EnableValhalla ConsistencyTest + * + * @comment CASE [B] ConsistencyTest.java uses Point as a POJO Type, but Mismatched.java uses Point as a VT. + * @compile -XDenableValueTypes -XDallowFlattenabilityModifiers ConsistencyTest.java ValuePoint.java Mismatched.java + * @compile -XDenableValueTypes -XDallowFlattenabilityModifiers ConsistencyTest.java POJOPoint.java + * @run main/othervm -Xint -XX:+EnableValhalla ConsistencyTest + * @run main/othervm -Xcomp -XX:+EnableValhalla ConsistencyTest + */ + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.invoke.*; +import java.lang.reflect.*; +import java.util.*; + + +// !!! NOTE !!! +// ConsistentTest.java and Mismatched.java are compiled separately, such that the classes in the two files +// will have the exact opposite understanding of whether Point is a VT. + +// Each test case for ConsistencyTest is written as a separate class, which must have exactly +// one of the following 3 annotations: @NegativeTest, @PositiveTest or @LegacyPositiveTest. + +// The test case must always fail with an ICCE. +@Retention(RetentionPolicy.RUNTIME) +@interface NegativeTest {} + +// The test case must always succeed. +@Retention(RetentionPolicy.RUNTIME) +@interface PositiveTest {} + +// The test case is for a "legacy" class, which doesn't know that Point is a VT. Some +// operations by such legacy classes are allowed (such as declaring, but not using, a method +// whose signature includes LPoint;). See LocalMethod in Mismatched.java for an example +@Retention(RetentionPolicy.RUNTIME) +@interface LegacyPositiveTest {} + +public class ConsistencyTest { + public static void main(String[] args) { + // Resolve this class now, before some of the test classes try to declare + // a field or parameter of this type. + Class pointClass = Point.class; + boolean isVT = pointClass.isValue(); + System.out.println("Is class " + pointClass + " a ValueType? " + (isVT ? "YES" : "NO")); + + // Run with "jtreg -DNonVTOnly ConsistencyTest.java", etc, to select a test scenario. + if (isVT && (System.getProperty("NonVTOnly") != null)) { + System.out.println("-DNonVTOnly is specified. Test skipped"); + return; + } + if (!isVT && (System.getProperty("VTOnly") != null)) { + System.out.println("-DVTOnly is specified. Test skipped"); + return; + } + + test( + "InvokeMethodHandle", + "FlattenableField", + "NotFlattenableField", + "NotFlattenableStaticField", + "ValueArrayField", + "ResolveClass", + "ResolveArray", + "ResolveMultiArray", + "ResolveMethod", + "LocalMethod", + "LocalMethodWithArray", + "LocalOverridingMethod", + "LocalOverridingDefaultMethod", + "RemoteMethod", + "RemoteMethodNull", + "RemoteMethodWithArray", + "BothWrongRemoteMethod"); + } + + public static void test(String...tests) { + List failed = new ArrayList<>(); + List exceptions = new ArrayList<>(); + Arrays.sort(tests); + + for (String name : tests) { + try { + testOne(name); + } catch (Throwable t) { + failed.add(name); + exceptions.add(t); + } + } + if (failed.size() > 0) { + System.out.println("-----------------------------------------"); + for (int i=0; i"); + } + } +} + +// This class has a *correct* notion of whether Point is a VT +class CorrectProvider { + static __NotFlattened Point p; // to get a null value + + static Point getPoint() { + return Point.createPoint(); + } + static Point getNullPoint() { + return p; + } + static Point[] getPointArray() { + return new Point[10]; + } +} + +//---------------------------------------------------------------------- +// Here are the test cases. More test cases are in Mismatched.java +//---------------------------------------------------------------------- + +// It must not be possible to override a method with a mismatched type +@NegativeTest +class LocalOverridingMethod { + static class Helper extends Parent { + Point foo() { + return Point.createPoint(); + } + } + public static void run() { + new Helper(); + } +} + +// It must not be possible to override a default method with a mismatched type +@NegativeTest +class LocalOverridingDefaultMethod { + static class Helper implements InterfaceWithDefault { + public Point foo() { + return Point.createPoint(); + } + } + public static void run() { + new Helper(); + } +} + +// Cannot call a method whose signature contains a mismatched VT. +@NegativeTest +class RemoteMethod { + public static void run() { + Point p = Provider.getPoint(); + } +} + +// Cannot call a method whose parameter is a mismatched VT, even if you are passing null. +@NegativeTest +class RemoteMethodNull { + static __NotFlattened Point p; // to get a null value + public static void run() { + Provider.processPoint(p); + } +} + +// Cannot call a method whose signature contains an array of a mismatched VT, even if you are passing null. +@NegativeTest +class RemoteMethodWithArray { + public static void run() { + Provider.foo(null); + } +} + +// You shouldn't be able to invoke a method defined by a class who has a different idea of whether Point is VT. +@NegativeTest +class InvokeMethodHandle { + public static void run() throws Throwable { + MethodHandles.Lookup lookup = MethodHandles.lookup(); + MethodType mt = MethodType.methodType(Point.class); + MethodHandle mh = lookup.findStatic(CorrectProvider.class, "getNullPoint", mt); + InvokeMethodHandle_mismatched.test(mh); + } +} --- /dev/null 2017-05-05 06:40:48.273288351 -0700 +++ new/test/hotspot/jtreg/runtime/valhalla/valuetypes/consistency/Mismatched.java 2018-07-18 10:23:21.255916746 -0700 @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.invoke.*; + +class Parent { + Point foo() { + return Point.createPoint(); + } +} + +interface InterfaceWithDefault { + default Point foo() { + return Point.createPoint(); + } +} + +class Provider { + static Point getPoint() { + return Point.createPoint(); + } + static void foo(Point[] array) { } + + static void processPoint(Point p) { } +} + +// It's OK to declare a Flattenable field of a mismatched type, but only from a legacy class that doesn't know Point is a VT. +@LegacyPositiveTest +class FlattenableField { + static class Helper { + // test assumes __Flattenable is the default for non static fields + Point p; + } + public static void run() { + // Helper will fail to load if it's not a legacy class (i.e., it declares that Point is a VT, but + // point ends up not being a VT. + new Helper(); + } +} + +// It's OK to declare a NonFlattenable field of a mismatched type +@PositiveTest +class NotFlattenableField { + __NotFlattened Point p; + public static void run() {}; +} + +// It's OK to declare a NonFlattenable static field of a mismatched type +@PositiveTest +class NotFlattenableStaticField { + __NotFlattened static Point p; + public static void run() {} +} + +// It's OK to declare a NonFlattenable static field of a mismatched type +@PositiveTest +class ValueArrayField { + Point[] p; + public static void run() {}; +} + +// Cannot resolve the Point class if your idea of whether it's a ValueType is wrong. +@NegativeTest +class ResolveClass { + public static void run() { + Class c = Point.class; + //TODO Point p = Point.createPoint(); + } +} + +// It's NOT OK to resolve the array class of Point even if your idea of whether it's a ValueType is wrong. +@NegativeTest +class ResolveArray { + public static void run() { + Point[] array = new Point[5]; + } +} + +// Yet it's OK to resolve a higher-dimensional array class of Point even if your idea of whether it's a ValueType is wrong. (BUG??) +@PositiveTest +class ResolveMultiArray { + public static void run() { + Point[][] array = new Point[5][4]; + } +} + +// Cannot resolve a method in the Point class if your idea of whether it's a ValueType is wrong. +@NegativeTest +class ResolveMethod { + public static void run() { + Point.createPoint(); + } +} + +// It's OK for a legacy class to declare (but not use) a method whose signature contains a mismatched VT. +@LegacyPositiveTest +class LocalMethod { + static class Helper { + Point foo() { + return Point.createPoint(); + } + } + public static void run() { + new Helper(); + } +} + +// It's OK for a legacy class to declare (but not use) a method whose signature contains a array of a mismatched VT. +@LegacyPositiveTest +class LocalMethodWithArray { + static class Helper { + void foo(Point[] array) { } + } + public static void run() { + new Helper(); + } +} + + +// Two legacy classes can call each other's methods, as long as both of them +// have the wrong understanding of whether Point is a VT. +@LegacyPositiveTest +class BothWrongRemoteMethod { + static __NotFlattened Point p; // to get a null value + public static void run() { + Provider.processPoint(p); + } +} + +// helper class used by InvokeMethodHandle (defined in ConsistencyTest.java). +class InvokeMethodHandle_mismatched { + static void test(MethodHandle mh) throws Throwable { + Point p = (Point)mh.invoke(); + System.out.println("(should not get here) Point = " + p); + } +} --- /dev/null 2017-05-05 06:40:48.273288351 -0700 +++ new/test/hotspot/jtreg/runtime/valhalla/valuetypes/consistency/POJOPoint.java 2018-07-18 10:23:22.431961806 -0700 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// Point is a plain-old-java-object Type. +class Point { + final int x; + final int y; + + public int getX() { return x; } + public int getY() { return y; } + + public static Point createPoint() { + return new Point(); + } + + public Point() { + x = 0; + y = 0; + } +} --- /dev/null 2017-05-05 06:40:48.273288351 -0700 +++ new/test/hotspot/jtreg/runtime/valhalla/valuetypes/consistency/ValuePoint.java 2018-07-18 10:23:23.736011771 -0700 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// Point is a Value Type. +__ByValue final class Point { + final int x; + final int y; + + private Point() { + x = 0; + y = 0; + } + + public int getX() { return x; } + public int getY() { return y; } + + public static Point createPoint() { + Point p = __MakeDefault Point(); + return p; + } +}