--- old/make/common/Modules.gmk 2017-09-14 22:57:39.000000000 -0700 +++ new/make/common/Modules.gmk 2017-09-14 22:57:39.000000000 -0700 @@ -113,6 +113,7 @@ jdk.crypto.ec \ jdk.dynalink \ jdk.incubator.httpclient \ + jdk.incubator.mvt \ jdk.jsobject \ jdk.localedata \ jdk.naming.dns \ @@ -155,6 +156,7 @@ jdk.hotspot.agent \ jdk.httpserver \ jdk.incubator.httpclient \ + jdk.incubator.mvt \ jdk.jartool \ jdk.javadoc \ jdk.jcmd \ --- old/hotspot/src/share/vm/classfile/classFileParser.cpp 2017-09-14 22:57:40.000000000 -0700 +++ new/hotspot/src/share/vm/classfile/classFileParser.cpp 2017-09-14 22:57:40.000000000 -0700 @@ -1046,7 +1046,7 @@ _jdk_internal_vm_annotation_Contended, _field_Stable, _jdk_internal_vm_annotation_ReservedStackAccess, - _jvm_internal_value_ValueCapableClass, + _jdk_incubator_mvt_ValueCapableClass, _annotation_LIMIT }; const Location _location; @@ -1083,7 +1083,7 @@ void set_stable(bool stable) { set_annotation(_field_Stable); } bool is_stable() const { return has_annotation(_field_Stable); } - bool is_value_capable_class() const { return has_annotation(_jvm_internal_value_ValueCapableClass); } + bool is_value_capable_class() const { return has_annotation(_jdk_incubator_mvt_ValueCapableClass); } }; // This class also doubles as a holder for metadata cleanup. @@ -2134,11 +2134,11 @@ if (RestrictReservedStack && !privileged) break; // honor privileges return _jdk_internal_vm_annotation_ReservedStackAccess; } - case vmSymbols::VM_SYMBOL_ENUM_NAME(jvm_internal_value_ValueCapableClass_signature) : { + case vmSymbols::VM_SYMBOL_ENUM_NAME(jdk_incubator_mvt_ValueCapableClass_signature) : { if (_location != _in_class) { break; } - return _jvm_internal_value_ValueCapableClass; + return _jdk_incubator_mvt_ValueCapableClass; } default: { break; --- old/hotspot/src/share/vm/classfile/systemDictionary.hpp 2017-09-14 22:57:42.000000000 -0700 +++ new/hotspot/src/share/vm/classfile/systemDictionary.hpp 2017-09-14 22:57:41.000000000 -0700 @@ -189,7 +189,6 @@ do_klass(ParseUtil_klass, sun_net_www_ParseUtil, Pre ) \ \ /* support for valhalla "shady" value type bytecode transformer */ \ - do_klass(ValueCapableClass_klass, jvm_internal_value_ValueCapableClass, MVTClasses ) \ do_klass(Valhalla_MVT1_0_klass, valhalla_shady_MVT1_0, MVTClasses ) \ \ do_klass(StackTraceElement_klass, java_lang_StackTraceElement, Opt ) \ --- old/hotspot/src/share/vm/classfile/vmSymbols.hpp 2017-09-14 22:57:43.000000000 -0700 +++ new/hotspot/src/share/vm/classfile/vmSymbols.hpp 2017-09-14 22:57:42.000000000 -0700 @@ -320,8 +320,8 @@ LP64_ONLY( do_alias(intptr_signature, long_signature) ) \ \ /* support for valhalla "shady" value types */ \ - template(jvm_internal_value_ValueCapableClass, "jvm/internal/value/ValueCapableClass") \ - template(jvm_internal_value_ValueCapableClass_signature, "Ljvm/internal/value/ValueCapableClass;") \ + template(jdk_incubator_mvt_ValueCapableClass, "jdk/incubator/mvt/ValueCapableClass") \ + template(jdk_incubator_mvt_ValueCapableClass_signature, "Ljdk/incubator/mvt/ValueCapableClass;") \ template(valhalla_shady_MVT1_0, "valhalla/shady/MinimalValueTypes_1_0") \ template(valhalla_shady_MVT1_0_createDerivedValueType, "createDerivedValueType") \ template(valhalla_shady_MVT1_0_createDerivedValueType_signature, "(Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/security/ProtectionDomain;[Ljava/lang/String;[I)Ljava/lang/String;") \ --- old/hotspot/src/share/vm/runtime/arguments.cpp 2017-09-14 22:57:43.000000000 -0700 +++ new/hotspot/src/share/vm/runtime/arguments.cpp 2017-09-14 22:57:43.000000000 -0700 @@ -3712,6 +3712,11 @@ UNSUPPORTED_OPTION(TieredCompilation); #endif + if ((EnableMVT || EnableValhalla) && + !create_numbered_property("jdk.module.addmods", "jdk.incubator.mvt", addmods_count++)) { + return JNI_ENOMEM; + } + #if INCLUDE_JVMCI if (EnableJVMCI && !create_numbered_property("jdk.module.addmods", "jdk.internal.vm.ci", addmods_count++)) { --- old/hotspot/test/compiler/valhalla/valuetypes/TestBoundValueTypes.java 2017-09-14 22:57:45.000000000 -0700 +++ new/hotspot/test/compiler/valhalla/valuetypes/TestBoundValueTypes.java 2017-09-14 22:57:44.000000000 -0700 @@ -25,12 +25,16 @@ import java.lang.invoke.*; -import jdk.experimental.value.*; + +import jdk.experimental.value.MethodHandleBuilder; +import jdk.incubator.mvt.ValueType; /** * @test * @bug 8185339 * @summary Test correct compilation of MethodHandles with bound value type arguments. + * @modules java.base/jdk.experimental.value + * jdk.incubator.mvt * @compile -XDenableValueTypes ValueCapableClass2.java TestBoundValueTypes.java * @run main/othervm -noverify -XX:+EnableMVT -XX:CompileCommand=compileonly,compiler.valhalla.valuetypes.TestBoundValueTypes::* * -XX:CompileCommand=compileonly,java.lang.invoke.*::* compiler.valhalla.valuetypes.TestBoundValueTypes --- old/hotspot/test/compiler/valhalla/valuetypes/TestUnloadedValueTypeArray.java 2017-09-14 22:57:45.000000000 -0700 +++ new/hotspot/test/compiler/valhalla/valuetypes/TestUnloadedValueTypeArray.java 2017-09-14 22:57:45.000000000 -0700 @@ -25,6 +25,7 @@ * @test * @bug 8182997 * @summary Array of unloaded value class should consistently use L signature + * @modules jdk.incubator.mvt * @compile -XDenableValueTypes TestUnloadedValueTypeArray.java * @run main/othervm -XX:+EnableValhalla -noverify -Xcomp -XX:CompileOnly=TestUnloadedValueTypeArray::test TestUnloadedValueTypeArray * --- old/hotspot/test/compiler/valhalla/valuetypes/ValueCapableClass1.java 2017-09-14 22:57:46.000000000 -0700 +++ new/hotspot/test/compiler/valhalla/valuetypes/ValueCapableClass1.java 2017-09-14 22:57:46.000000000 -0700 @@ -28,7 +28,7 @@ */ package compiler.valhalla.valuetypes; -@jvm.internal.value.ValueCapableClass +@jdk.incubator.mvt.ValueCapableClass public final class ValueCapableClass1 { public final long t; public final int x; --- old/hotspot/test/compiler/valhalla/valuetypes/ValueCapableClass2.java 2017-09-14 22:57:47.000000000 -0700 +++ new/hotspot/test/compiler/valhalla/valuetypes/ValueCapableClass2.java 2017-09-14 22:57:47.000000000 -0700 @@ -30,9 +30,10 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; -import jdk.experimental.value.ValueType; -@jvm.internal.value.ValueCapableClass +import jdk.incubator.mvt.ValueType; + +@jdk.incubator.mvt.ValueCapableClass public final class ValueCapableClass2 { public final long u; --- old/hotspot/test/compiler/valhalla/valuetypes/ValueTypeTestBench.java 2017-09-14 22:57:48.000000000 -0700 +++ new/hotspot/test/compiler/valhalla/valuetypes/ValueTypeTestBench.java 2017-09-14 22:57:47.000000000 -0700 @@ -27,7 +27,9 @@ * @test * @library /testlibrary /test/lib /compiler/whitebox / * @requires os.simpleArch == "x64" - * @modules java.base/jdk.internal.misc:+open + * @modules java.base/jdk.experimental.value + * java.base/jdk.internal.misc:+open + * jdk.incubator.mvt * @compile -XDenableValueTypes ValueCapableClass1.java ValueCapableClass2.java ValueTypeTestBench.java * @run main ClassFileInstaller sun.hotspot.WhiteBox * @run main ClassFileInstaller jdk.test.lib.Platform @@ -42,7 +44,7 @@ * -XX:+EnableValhalla -XX:+EnableMVT -XX:-ValueTypePassFieldsAsArgs -XX:-ValueTypeReturnedAsFields -XX:-ValueArrayFlatten * -Djdk.lang.reflect.DVT=true * compiler.valhalla.valuetypes.ValueTypeTestBench - * @run main/othervm -Xbootclasspath/a:. -ea -noverify -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions + * @run main/othervm/timeout=200 -Xbootclasspath/a:. -ea -noverify -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI -XX:-TieredCompilation -XX:+AlwaysIncrementalInline * -XX:+EnableValhalla -XX:+EnableMVT -XX:+ValueTypePassFieldsAsArgs -XX:+ValueTypeReturnedAsFields -XX:+ValueArrayFlatten * -XX:ValueArrayElemMaxFlatSize=-1 -XX:ValueArrayElemMaxFlatOops=-1 @@ -53,7 +55,8 @@ package compiler.valhalla.valuetypes; import compiler.whitebox.CompilerWhiteBoxTest; -import jdk.internal.misc.Unsafe; +import jdk.experimental.value.MethodHandleBuilder; +import jdk.incubator.mvt.ValueType; import jdk.test.lib.Asserts; import jdk.test.lib.management.InputArguments; import jdk.test.lib.Platform; @@ -75,7 +78,6 @@ import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; -import jdk.experimental.value.*; // Test value types __ByValue final class MyValue1 { --- old/hotspot/test/runtime/valhalla/valuetypes/DeriveValueTypeCreation.java 2017-09-14 22:57:49.000000000 -0700 +++ new/hotspot/test/runtime/valhalla/valuetypes/DeriveValueTypeCreation.java 2017-09-14 22:57:49.000000000 -0700 @@ -22,6 +22,7 @@ */ package runtime.valhalla.valuetypes; +import jdk.incubator.mvt.ValueType; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -31,7 +32,6 @@ import java.util.HashMap; import jdk.experimental.bytecode.*; -import jdk.experimental.value.ValueType; import jdk.internal.org.objectweb.asm.*; import static jdk.internal.org.objectweb.asm.Opcodes.*; @@ -43,7 +43,9 @@ * @summary Derive Value Type creation test * @library /test/lib * @compile DeriveValueTypeCreation.java - * @modules java.base/jdk.internal.org.objectweb.asm + * @modules java.base/jdk.experimental.bytecode + * java.base/jdk.internal.org.objectweb.asm + * jdk.incubator.mvt * @build runtime.valhalla.valuetypes.ValueCapableClass * @run main/othervm -Xint -XX:+EnableMVT runtime.valhalla.valuetypes.DeriveValueTypeCreation * @run main/othervm -Xcomp -XX:+EnableMVT runtime.valhalla.valuetypes.DeriveValueTypeCreation @@ -96,9 +98,6 @@ if (vt.boxClass() != clazz) { fail("ValueType.boxClass() failed"); } - if (vt.sourceClass() != clazz) { - fail("ValueType.sourceClass() failed"); - } // DVT class matches our expectations for the current implementation... Class vtClass = vt.valueClass(); @@ -179,7 +178,7 @@ ClassWriter cw = new ClassWriter(0); cw.visit(52, klassAccess, name, null, superKlass, null); if (vccAnnotation ) { - cw.visitAnnotation("Ljvm/internal/value/ValueCapableClass;", true); + cw.visitAnnotation("Ljdk/incubator/mvt/ValueCapableClass;", true); } if (fieldType != null) { cw.visitField(fieldAccess, "x", fieldType, null, null); --- old/hotspot/test/runtime/valhalla/valuetypes/MVTCombo.java 2017-09-14 22:57:50.000000000 -0700 +++ new/hotspot/test/runtime/valhalla/valuetypes/MVTCombo.java 2017-09-14 22:57:49.000000000 -0700 @@ -31,13 +31,10 @@ import jdk.test.lib.combo.ComboTask.Result; import jdk.test.lib.combo.ComboTestHelper; import jdk.test.lib.combo.ComboTestHelper.ArrayDimensionKind; -import jdk.experimental.value.ValueType; +import jdk.incubator.mvt.ValueType; -import java.io.File; -import java.io.FileInputStream; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; import static java.lang.invoke.MethodType.methodType; import java.lang.reflect.Field; import java.lang.reflect.Modifier; @@ -197,7 +194,7 @@ } public static final String VCC_TEMPLATE = - "@jvm.internal.value.ValueCapableClass\n" + + "@jdk.incubator.mvt.ValueCapableClass\n" + "public final class Test {\n\n" + " // Declare fields...\n" + " #{ARITY.FIELD_DECL}\n" + @@ -298,6 +295,7 @@ public void doWork() throws Throwable { Result> result = newCompilationTask() .withSourceFromTemplate(VCC_TEMPLATE) + .withOption("--add-modules=jdk.incubator.mvt") .generate(); //System.out.println("COMP: " + result.compilationInfo()); // Print the generated source if (result.hasErrors()) { @@ -322,16 +320,12 @@ } ValueType vt = ValueType.forClass(testSubject); Class boxClass = vt.boxClass(); - Class sourceClass = vt.sourceClass(); Class vtClass = vt.valueClass(); Class arrayClass = vt.arrayValueClass(); Class mArrayClass = vt.arrayValueClass(4); if (boxClass != testSubject) { throw new RuntimeException("Box class != VCC"); } - if (sourceClass != testSubject) { - throw new RuntimeException("Source class != VCC"); - } if (vt.toString() == null) { throw new RuntimeException("No toString() return"); } @@ -367,7 +361,7 @@ printFieldValues(MethodHandles.filterReturnValue(vt.defaultValueConstant(), box)); System.out.println("VERSUS value from array:"); printFieldValues(MethodHandles.filterReturnValue(arrayGetter, box).invoke(array, i)); - throw new IllegalStateException("Failed equality test for class: " + vt.sourceClass().getName() + " at index: " + i); + throw new IllegalStateException("Failed equality test for class: " + vt.boxClass().getName() + " at index: " + i); } } --- old/hotspot/test/runtime/valhalla/valuetypes/MVTComboDebugTier1.java 2017-09-14 22:57:50.000000000 -0700 +++ new/hotspot/test/runtime/valhalla/valuetypes/MVTComboDebugTier1.java 2017-09-14 22:57:50.000000000 -0700 @@ -34,6 +34,7 @@ * jdk.compiler/com.sun.tools.javac.main * jdk.compiler/com.sun.tools.javac.tree * jdk.compiler/com.sun.tools.javac.util + * jdk.incubator.mvt * @compile MVTCombo.java * @build jdk.test.lib.combo.ComboTestHelper * @run main/othervm -Xint -XX:+EnableMVT runtime.valhalla.valuetypes.MVTComboTier1 3 --- old/hotspot/test/runtime/valhalla/valuetypes/MVTComboTier1.java 2017-09-14 22:57:51.000000000 -0700 +++ new/hotspot/test/runtime/valhalla/valuetypes/MVTComboTier1.java 2017-09-14 22:57:51.000000000 -0700 @@ -34,6 +34,7 @@ * jdk.compiler/com.sun.tools.javac.main * jdk.compiler/com.sun.tools.javac.tree * jdk.compiler/com.sun.tools.javac.util + * jdk.incubator.mvt * @compile MVTCombo.java * @build jdk.test.lib.combo.ComboTestHelper * @run main/othervm -Xint -XX:+EnableMVT runtime.valhalla.valuetypes.MVTComboTier1 3 --- old/hotspot/test/runtime/valhalla/valuetypes/PersonVcc.java 2017-09-14 22:57:52.000000000 -0700 +++ new/hotspot/test/runtime/valhalla/valuetypes/PersonVcc.java 2017-09-14 22:57:52.000000000 -0700 @@ -23,7 +23,7 @@ package runtime.valhalla.valuetypes; -@jvm.internal.value.ValueCapableClass +@jdk.incubator.mvt.ValueCapableClass public final class PersonVcc { final int id; final String firstName; --- old/hotspot/test/runtime/valhalla/valuetypes/UninitializedValueFieldsTest.java 2017-09-14 22:57:53.000000000 -0700 +++ new/hotspot/test/runtime/valhalla/valuetypes/UninitializedValueFieldsTest.java 2017-09-14 22:57:53.000000000 -0700 @@ -5,8 +5,9 @@ /* * @test * @summary Uninitialized value fields test + * @modules jdk.incubator.mvt * @library /test/lib - * @compile -XDenableValueTypes Point.java UninitializedValueFieldsTest.java + * @compile -XDenableValueTypes Point.java * @run main/othervm -Xint -XX:+EnableValhalla runtime.valhalla.valuetypes.UninitializedValueFieldsTest * @run main/othervm -Xcomp -XX:+EnableValhalla runtime.valhalla.valuetypes.UninitializedValueFieldsTest */ --- old/hotspot/test/runtime/valhalla/valuetypes/VDefaultTest.java 2017-09-14 22:57:54.000000000 -0700 +++ new/hotspot/test/runtime/valhalla/valuetypes/VDefaultTest.java 2017-09-14 22:57:53.000000000 -0700 @@ -29,7 +29,8 @@ * @test VDefaultTest * @summary vdefault bytecode test * @library /test/lib - * @compile -XDenableValueTypes Point.java VDefaultTest.java + * @compile -XDenableValueTypes --add-modules jdk.incubator.mvt Point.java + * @compile -XDenableValueTypes VDefaultTest.java * @run main/othervm -Xint -XX:+EnableValhalla runtime.valhalla.valuetypes.VDefaultTest * @run main/othervm -Xcomp -XX:+EnableValhalla runtime.valhalla.valuetypes.VDefaultTest */ --- old/hotspot/test/runtime/valhalla/valuetypes/VTBufferTest.java 2017-09-14 22:57:54.000000000 -0700 +++ new/hotspot/test/runtime/valhalla/valuetypes/VTBufferTest.java 2017-09-14 22:57:54.000000000 -0700 @@ -46,8 +46,6 @@ * $ java VTBufferTest run */ -import jvm.internal.value.*; - import javax.management.*; import javax.tools.JavaCompiler; import javax.tools.JavaFileObject; --- old/hotspot/test/runtime/valhalla/valuetypes/VWithFieldTest.java 2017-09-14 22:57:55.000000000 -0700 +++ new/hotspot/test/runtime/valhalla/valuetypes/VWithFieldTest.java 2017-09-14 22:57:55.000000000 -0700 @@ -29,7 +29,8 @@ * @test VWithFieldTest * @summary vwithfield bytecode test * @library /test/lib - * @compile -XDenableValueTypes Point.java VWithFieldTest.java + * @compile -XDenableValueTypes --add-modules jdk.incubator.mvt Point.java + * @compile -XDenableValueTypes VWithFieldTest.java * @run main/othervm -Xint -XX:+EnableValhalla runtime.valhalla.valuetypes.VWithFieldTest * @run main/othervm -Xcomp -XX:+EnableValhalla runtime.valhalla.valuetypes.VWithFieldTest */ --- old/hotspot/test/runtime/valhalla/valuetypes/ValueCapableClass.java 2017-09-14 22:57:56.000000000 -0700 +++ new/hotspot/test/runtime/valhalla/valuetypes/ValueCapableClass.java 2017-09-14 22:57:56.000000000 -0700 @@ -22,7 +22,7 @@ */ package runtime.valhalla.valuetypes; -@jvm.internal.value.ValueCapableClass +@jdk.incubator.mvt.ValueCapableClass public final class ValueCapableClass { public static final int DEFAULT_X = 11; --- old/hotspot/test/runtime/valhalla/valuetypes/ValueOops.java 2017-09-14 22:57:57.000000000 -0700 +++ new/hotspot/test/runtime/valhalla/valuetypes/ValueOops.java 2017-09-14 22:57:57.000000000 -0700 @@ -26,7 +26,9 @@ import java.lang.invoke.*; import java.lang.ref.*; import java.util.concurrent.*; -import jdk.experimental.value.*; + +import jdk.experimental.value.MethodHandleBuilder; +import jdk.incubator.mvt.ValueType; import static jdk.test.lib.Asserts.*; import jdk.test.lib.Utils; @@ -35,6 +37,8 @@ /** * @test ValueOops * @summary Test embedding oops into Value types + * @modules java.base/jdk.experimental.value + * jdk.incubator.mvt * @library /test/lib * @compile PersonVcc.java * @compile -XDenableValueTypes Person.java --- old/hotspot/test/runtime/valhalla/valuetypes/VboxUnbox.java 2017-09-14 22:57:58.000000000 -0700 +++ new/hotspot/test/runtime/valhalla/valuetypes/VboxUnbox.java 2017-09-14 22:57:58.000000000 -0700 @@ -23,13 +23,17 @@ package runtime.valhalla.valuetypes; import java.lang.invoke.*; -import jdk.experimental.value.*; + +import jdk.experimental.value.MethodHandleBuilder; +import jdk.incubator.mvt.ValueType; import static jdk.test.lib.Asserts.*; /* * @test VboxUnbox * @summary Exercise vbox & vunbox bytecodes + * @modules java.base/jdk.experimental.value + * jdk.incubator.mvt * @library /test/lib * @build runtime.valhalla.valuetypes.ValueCapableClass * @run main/othervm -Xint -noverify -XX:+EnableMVT runtime.valhalla.valuetypes.VboxUnbox --- old/hotspot/test/runtime/valhalla/valuetypes/verifier/ValueCapableClass.java 2017-09-14 22:57:59.000000000 -0700 +++ new/hotspot/test/runtime/valhalla/valuetypes/verifier/ValueCapableClass.java 2017-09-14 22:57:59.000000000 -0700 @@ -22,7 +22,7 @@ */ package runtime.valhalla.valuetypes.verifier; -@jvm.internal.value.ValueCapableClass +@jdk.incubator.mvt.ValueCapableClass public final class ValueCapableClass { public static final int DEFAULT_X = 11; --- old/hotspot/test/runtime/valhalla/valuetypes/verifier/VloadTest.java 2017-09-14 22:57:59.000000000 -0700 +++ new/hotspot/test/runtime/valhalla/valuetypes/verifier/VloadTest.java 2017-09-14 22:57:59.000000000 -0700 @@ -24,14 +24,15 @@ package runtime.valhalla.valuetypes.verifier; import java.lang.invoke.*; -import java.lang.ref.*; -import java.util.concurrent.*; -import jdk.experimental.value.*; + +import jdk.experimental.value.MethodHandleBuilder; import sun.hotspot.WhiteBox; /** * @test VloadTest * @summary Test vload opcode + * @modules java.base/jdk.experimental.value + * jdk.incubator.mvt * @library /test/lib * @compile -XDenableValueTypes VloadTest.java * @run main ClassFileInstaller sun.hotspot.WhiteBox --- old/hotspot/test/runtime/valhalla/valuetypes/verifier/VunboxErrorIndex.java 2017-09-14 22:58:00.000000000 -0700 +++ new/hotspot/test/runtime/valhalla/valuetypes/verifier/VunboxErrorIndex.java 2017-09-14 22:58:00.000000000 -0700 @@ -23,13 +23,16 @@ package runtime.valhalla.valuetypes.verifier; import java.lang.invoke.*; -import jdk.experimental.value.*; +import jdk.incubator.mvt.ValueType; +import jdk.experimental.value.MethodHandleBuilder; import static jdk.test.lib.Asserts.*; /* * @test VunboxErrorIndex * @summary Exercise the verifier for vunbox bytecode with a non-value type CP index. + * @modules java.base/jdk.experimental.value + * jdk.incubator.mvt * @library /test/lib * @build runtime.valhalla.valuetypes.verifier.ValueCapableClass * @run main/othervm -Xint -verify -XX:+EnableMVT runtime.valhalla.valuetypes.verifier.VunboxErrorIndex --- old/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java 2017-09-14 22:58:01.000000000 -0700 +++ new/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java 2017-09-14 22:58:01.000000000 -0700 @@ -25,7 +25,6 @@ package java.lang.invoke; -import jdk.experimental.value.ValueType; import jdk.internal.misc.JavaLangInvokeAccess; import jdk.internal.misc.SharedSecrets; import jdk.internal.org.objectweb.asm.AnnotationVisitor; @@ -40,6 +39,7 @@ import sun.invoke.util.VerifyType; import sun.invoke.util.Wrapper; import valhalla.shady.MinimalValueTypes_1_0; +import valhalla.shady.ValueTypeHolder; import java.lang.reflect.Array; import java.util.Arrays; @@ -434,8 +434,8 @@ assert(!VerifyType.isNullConversion(src, dst, /*keepInterfaces=*/ strict)); // caller responsibility if (dst == void.class) return dst; - ValueType srcVT = getValueFor(src); - ValueType dstVT = getValueFor(dst); + ValueTypeHolder srcVT = MinimalValueTypes_1_0.findValueType(src); + ValueTypeHolder dstVT = MinimalValueTypes_1_0.findValueType(dst); MethodHandle fn; if (src.isPrimitive()) { if (src == void.class) { @@ -496,19 +496,6 @@ return fn; } - @SuppressWarnings("unchecked") - static ValueType getValueFor(Class c) { - try { - if (MinimalValueTypes_1_0.isValueType(c)) { - return (ValueType)ValueType.forClass(MinimalValueTypes_1_0.getValueCapableClass(c)); - } else { - return null; - } - } catch (Throwable ex) { - return null; - } - } - static MethodHandle makeVarargsCollector(MethodHandle target, Class arrayType) { MethodType type = target.type(); int last = type.parameterCount() - 1; @@ -1821,7 +1808,7 @@ return ValueConversions.unboxExact(w); } } else if (MinimalValueTypes_1_0.isValueType(returnType)) { - return ValueType.forClass(MinimalValueTypes_1_0.getValueCapableClass(returnType)).unbox(); + return MinimalValueTypes_1_0.findValueType(returnType).unbox(); } else { return MethodHandles.identity(Object.class); } --- old/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java 2017-09-14 22:58:02.000000000 -0700 +++ new/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java 2017-09-14 22:58:02.000000000 -0700 @@ -25,7 +25,6 @@ package java.lang.invoke; -import jdk.experimental.value.ValueType; import jdk.internal.misc.SharedSecrets; import jdk.internal.module.IllegalAccessLogger; import jdk.internal.org.objectweb.asm.ClassReader; @@ -38,6 +37,7 @@ import sun.reflect.misc.ReflectUtil; import sun.security.util.SecurityConstants; import valhalla.shady.MinimalValueTypes_1_0; +import valhalla.shady.ValueTypeHolder; import java.lang.invoke.LambdaForm.BasicType; import java.lang.reflect.Constructor; @@ -56,7 +56,6 @@ import java.util.Iterator; import java.util.List; import java.util.Objects; -import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -1427,7 +1426,7 @@ */ public MethodHandle findGetter(Class refc, String name, Class type) throws NoSuchFieldException, IllegalAccessException { if (MinimalValueTypes_1_0.isValueType(refc)) { - return ValueType.forClass(MinimalValueTypes_1_0.getValueCapableClass(refc)).findGetter(this, name, type); + return MinimalValueTypes_1_0.findValueType(refc).findGetter(this, name, type); } else { MemberName field = resolveOrFail(REF_getField, refc, name, type); return getDirectField(REF_getField, refc, field); @@ -2539,7 +2538,7 @@ */ public static MethodHandle arrayConstructor(Class arrayClass) throws IllegalArgumentException { - ValueType compValue = valueComponent(arrayClass); + ValueTypeHolder compValue = valueComponent(arrayClass); if (compValue != null) { return compValue.newArray(); } else { @@ -2561,7 +2560,7 @@ */ public static MethodHandle arrayLength(Class arrayClass) throws IllegalArgumentException { - ValueType compValue = valueComponent(arrayClass); + ValueTypeHolder compValue = valueComponent(arrayClass); return (compValue != null) ? compValue.arrayLength() : MethodHandleImpl.makeArrayElementAccessor(arrayClass, MethodHandleImpl.ArrayAccess.LENGTH); @@ -2579,7 +2578,7 @@ */ public static MethodHandle arrayElementGetter(Class arrayClass) throws IllegalArgumentException { - ValueType compValue = valueComponent(arrayClass); + ValueTypeHolder compValue = valueComponent(arrayClass); return (compValue != null) ? compValue.arrayGetter() : MethodHandleImpl.makeArrayElementAccessor(arrayClass, MethodHandleImpl.ArrayAccess.GET); @@ -2597,21 +2596,21 @@ */ public static MethodHandle arrayElementSetter(Class arrayClass) throws IllegalArgumentException { - ValueType compValue = valueComponent(arrayClass); + ValueTypeHolder compValue = valueComponent(arrayClass); return (compValue != null) ? compValue.arraySetter() : MethodHandleImpl.makeArrayElementAccessor(arrayClass, MethodHandleImpl.ArrayAccess.SET); } @SuppressWarnings("unchecked") - private static ValueType valueComponent(Class arrayClass) { + private static ValueTypeHolder valueComponent(Class arrayClass) { if (!arrayClass.isArray()) { throw newIllegalArgumentException("not an array class: " + arrayClass.getName()); } Class comp = arrayClass.getComponentType(); if (MinimalValueTypes_1_0.isValueType(comp)) { - return (ValueType)ValueType.forClass(MinimalValueTypes_1_0.getValueCapableClass(comp)); + return (ValueTypeHolder) MinimalValueTypes_1_0.findValueType(comp); } else { return null; } @@ -3383,7 +3382,7 @@ if (type.isPrimitive()) { return zero(Wrapper.forPrimitiveType(type), type); } else if (MinimalValueTypes_1_0.isValueType(type)) { - return ValueType.forClass(MinimalValueTypes_1_0.getValueCapableClass(type)).defaultValueConstant(); + return MinimalValueTypes_1_0.findValueType(type).defaultValueConstant(); } else { return zero(Wrapper.OBJECT, type); } @@ -3421,7 +3420,7 @@ LambdaForm lform = LambdaForm.identityForm(BasicType.basicType(ptype)); return MethodHandleImpl.makeIntrinsic(mtype, lform, Intrinsic.IDENTITY); } else { - return ValueType.forClass(MinimalValueTypes_1_0.getValueCapableClass(ptype)).identity(); + return MinimalValueTypes_1_0.findValueType(ptype).identity(); } } @@ -3498,7 +3497,7 @@ Class vcc = MinimalValueTypes_1_0.getValueCapableClass(ptype); Objects.requireNonNull(value); // throw NPE if needed value = vcc.cast(value); // throw CCE if needed - MethodHandle unbox = ValueType.forClass(vcc).unbox(); + MethodHandle unbox = MinimalValueTypes_1_0.findValueType(ptype).unbox(); result = result.bindArgumentQ(pos, value, unbox); } else { value = ptype.cast(value); // throw CCE if needed --- old/jdk/src/java.base/share/classes/jdk/experimental/value/MethodHandleBuilder.java 2017-09-14 22:58:04.000000000 -0700 +++ new/jdk/src/java.base/share/classes/jdk/experimental/value/MethodHandleBuilder.java 2017-09-14 22:58:03.000000000 -0700 @@ -39,6 +39,7 @@ import jdk.internal.misc.Unsafe; import sun.security.action.GetPropertyAction; import valhalla.shady.MinimalValueTypes_1_0; +import valhalla.shady.ValueTypeHolder; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles.Lookup; @@ -104,11 +105,11 @@ } } - static class IsolatedMethodBuilder extends ClassBuilder, String, IsolatedMethodBuilder> { + public static class IsolatedMethodBuilder extends ClassBuilder, String, IsolatedMethodBuilder> { private static final Class THIS_CLASS = new Object() { }.getClass(); - IsolatedMethodBuilder(String clazz, Lookup lookup) { + public IsolatedMethodBuilder(String clazz, Lookup lookup) { super(ENABLE_POOL_PATCHES ? new IsolatedMethodPatchingPoolHelper(clazz) : new IsolatedMethodPoolHelper(clazz), @@ -116,7 +117,7 @@ withThisClass(THIS_CLASS); } - Class thisClass() { + public Class thisClass() { return THIS_CLASS; } @@ -182,7 +183,7 @@ Class box = Class.forName(basicTypeHelper.symbol(desc) .replaceAll("/", ".") .replaceAll("\\$Value", ""), true, lookup.lookupClass().getClassLoader()); - ValueType vt = ValueType.forClass(box); + ValueTypeHolder vt = MinimalValueTypes_1_0.getValueFor(box); return numDims == 0 ? vt.valueClass() : vt.arrayValueClass(numDims); } catch (ReflectiveOperationException ex) { --- old/jdk/src/java.base/share/classes/module-info.java 2017-09-14 22:58:05.000000000 -0700 +++ new/jdk/src/java.base/share/classes/module-info.java 2017-09-14 22:58:05.000000000 -0700 @@ -128,12 +128,6 @@ exports javax.security.auth.x500; exports javax.security.cert; - // Valhalla support - exports jvm.internal.value; - exports jdk.experimental.value; - exports valhalla.shady; - exports jdk.experimental.bytecode; - // additional qualified exports may be inserted at build time // see make/gensrc/GenModuleInfo.gmk @@ -324,6 +318,7 @@ exports sun.util.resources to jdk.localedata; + exports valhalla.shady to jdk.incubator.mvt; // the service types defined by the APIs in this module --- old/jdk/src/java.base/share/classes/valhalla/shady/MinimalValueTypes_1_0.java 2017-09-14 22:58:06.000000000 -0700 +++ new/jdk/src/java.base/share/classes/valhalla/shady/MinimalValueTypes_1_0.java 2017-09-14 22:58:05.000000000 -0700 @@ -29,6 +29,7 @@ import jdk.internal.misc.VM; import sun.security.action.GetPropertyAction; +import java.lang.annotation.Annotation; import java.io.BufferedOutputStream; import java.io.File; import java.io.IOException; @@ -38,6 +39,7 @@ import java.nio.file.Paths; import java.security.ProtectionDomain; import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; import static jdk.internal.org.objectweb.asm.Opcodes.*; @@ -50,7 +52,7 @@ public static final String OBJECT_CLASS_DESC = "java/lang/Object"; public static final String VALUE_CLASS_DESC = "java/lang/__Value"; - public static final String DERIVE_VALUE_TYPE_DESC = "Ljvm/internal/value/ValueCapableClass;"; + public static final String DERIVE_VALUE_TYPE_DESC = "Ljdk/incubator/mvt/ValueCapableClass;"; public static final String DERIVE_VT_CLASSNAME_POSTFIX = "$Value"; public static final int DERIVE_VT_CLASS_ACCESS = ACC_PUBLIC|ACC_SUPER|ACC_FINAL|ACC_VALUE|ACC_SYNTHETIC; @@ -70,28 +72,76 @@ JLA = SharedSecrets.getJavaLangAccess(); } - public static boolean isValueTypeEnabled() { - return VALUE_TYPE_ENABLED; - } + private static final ConcurrentHashMap, ValueTypeHolder> BOX_TO_VT + = new ConcurrentHashMap<>(); - public static String getValueTypeClassName(ValueTypeDesc valueTypeDesc) { - return getValueTypeClassName(valueTypeDesc.getName()); + /** + * Returns the {@code ValueTypeHolder} representing the value type + * for the given value capable type. + * + * @throws UnsupportedOperationException if MVT is not enabled + * @throws IllegalArgumentException if the given class is not value capable class + */ + @SuppressWarnings("unchecked") + public static ValueTypeHolder getValueFor(Class vcc) { + if (!MinimalValueTypes_1_0.isValueTypeEnabled()) { + throw new UnsupportedOperationException("MVT is not enabled"); + } + + if (!MinimalValueTypes_1_0.isValueCapable(vcc)) { + throw new IllegalArgumentException("Class " + vcc + " not a value capable class"); + } + + ValueTypeHolder vt = (ValueTypeHolder) BOX_TO_VT.get(vcc); + if (vt != null) { + return vt; + } + + Class valueClass = (Class) MinimalValueTypes_1_0.getValueTypeClass(vcc); + vt = new ValueTypeHolder(vcc, valueClass); + ValueTypeHolder old = (ValueTypeHolder) BOX_TO_VT.putIfAbsent(vcc, vt); + if (old != null) { + vt = old; + } + return vt; } - public static String getValueTypeClassName(String vccName) { - return vccName + DERIVE_VT_CLASSNAME_POSTFIX; + /** + * Returns the {@code ValueTypeHolder} representing the value type + * for the given class is a derived value type; otherwise {@code null}. + */ + @SuppressWarnings("unchecked") + public static ValueTypeHolder findValueType(Class c) { + if (MinimalValueTypes_1_0.isValueType(c)) { + return (ValueTypeHolder) getValueFor(MinimalValueTypes_1_0.getValueCapableClass(c)); + } else { + return null; + } } - public static String getValueCapableClassName(String valName) { - return valName.substring(0, valName.length() - DERIVE_VT_CLASSNAME_POSTFIX.length()); + /** + * Returns true if MVT is enabled. + * + * jdk.incubator.mvt must be resolved in the boot layer. + */ + public static boolean isValueTypeEnabled() { + return VALUE_TYPE_ENABLED; } public static boolean isValueType(Class dvt) { return (dvt.getModifiers() & ACC_VALUE) != 0; } + /** + * Returns true if the given class is a value-capable class, i.e. + * annotated with @ValueCapableClass. + */ public static boolean isValueCapable(Class vcc) { - return vcc.getDeclaredAnnotation(jvm.internal.value.ValueCapableClass.class) != null; + if (!isValueTypeEnabled()) { + return false; + } + + return ValueClassHelper.hasValueCapableAnnotation(vcc); } public static Class getValueCapableClass(Class dvt) { @@ -202,7 +252,19 @@ private final native Class getDerivedValueType(Class ofClass); public static Class getValueClass() { - return VALUE_TYPE_ENABLED ? ValueClassHolder.CLASS_OBJECT : null; + return isValueTypeEnabled() ? ValueClassHelper.VALUE_CLASS : null; + } + + public static String getValueTypeClassName(ValueTypeDesc valueTypeDesc) { + return getValueTypeClassName(valueTypeDesc.getName()); + } + + public static String getValueTypeClassName(String vccName) { + return vccName + DERIVE_VT_CLASSNAME_POSTFIX; + } + + public static String getValueCapableClassName(String valName) { + return valName.substring(0, valName.length() - DERIVE_VT_CLASSNAME_POSTFIX.length()); } public static String mangleValueClassName(String name) { @@ -210,12 +272,60 @@ } /* - * A holder class that references __Value to be loaded only when MVT is enabled. - * - * This holder class would fail verification if loaded if MVT is not enabled. + * This helper class should only be loaded when MVT is enabled. + * Otherwise, it will load __Value but if MVT is not enabled and + * that would fail verification. */ - private static class ValueClassHolder { - static final Class CLASS_OBJECT = + private static class ValueClassHelper { + static final Class VALUE_CLASS = (Class)(Object)__Value.class; //hack around static type-system checks + + static volatile Class annotationClass; + static volatile Class valueTypeClass; + + static boolean hasValueCapableAnnotation(Class c) { + if (!VM.isModuleSystemInited()) { + return false; + } + Class annClass = annotationClass; + if (annClass == null) { + annotationClass = annClass = loadValueCapableAnnotation(); + } + return annClass != null && + c.getDeclaredAnnotation(annClass) != null; + } + + static Class loadValueCapableAnnotation() { + try { + @SuppressWarnings("unchecked") + Class c = (Class) + Class.forName("jdk.incubator.mvt.ValueCapableClass", false, + ClassLoader.getPlatformClassLoader()); + return c; + + } catch (ClassNotFoundException e) { + return null; + } + } + + static Class incubatorValueTypeClass() { + Class c = valueTypeClass; + if (c == null) { + try { + valueTypeClass = c = + Class.forName("jdk.incubator.mvt.ValueType", false, + ClassLoader.getPlatformClassLoader()); + } catch (ClassNotFoundException e) { + } + } + return valueTypeClass; + } + } + + static Class getIncubatorValueTypeClass() { + if (!isValueTypeEnabled()) { + throw new UnsupportedOperationException("MVT is not enabled"); + } + return ValueClassHelper.incubatorValueTypeClass(); } } --- old/jdk/test/valhalla/mvt/ConstructorTest.java 2017-09-14 22:58:07.000000000 -0700 +++ new/jdk/test/valhalla/mvt/ConstructorTest.java 2017-09-14 22:58:06.000000000 -0700 @@ -21,7 +21,7 @@ * questions. */ -import jdk.experimental.value.ValueType; +import jdk.incubator.mvt.ValueType; import org.testng.annotations.Test; import java.lang.invoke.MethodHandle; --- old/jdk/test/valhalla/mvt/Interval.java 2017-09-14 22:58:08.000000000 -0700 +++ new/jdk/test/valhalla/mvt/Interval.java 2017-09-14 22:58:07.000000000 -0700 @@ -1,4 +1,4 @@ -import jvm.internal.value.ValueCapableClass; +import jdk.incubator.mvt.ValueCapableClass; @ValueCapableClass public final class Interval { --- old/jdk/test/valhalla/mvt/MVTAccessCheck.java 2017-09-14 22:58:09.000000000 -0700 +++ new/jdk/test/valhalla/mvt/MVTAccessCheck.java 2017-09-14 22:58:08.000000000 -0700 @@ -29,7 +29,7 @@ * @run testng/othervm -XX:+EnableMVT -Dvalhalla.enableValueLambdaForms=true -Dvalhalla.enablePoolPatches=true MVTAccessCheck */ -import jdk.experimental.value.ValueType; +import jdk.incubator.mvt.ValueType; import org.testng.Assert; import org.testng.annotations.Test; --- old/jdk/test/valhalla/mvt/MVTReflectionTest.java 2017-09-14 22:58:10.000000000 -0700 +++ new/jdk/test/valhalla/mvt/MVTReflectionTest.java 2017-09-14 22:58:09.000000000 -0700 @@ -24,11 +24,10 @@ /* * @test * @summary basic test for reflection on MVT - * @build Point * @run testng/othervm -XX:+EnableMVT MVTReflectionTest */ -import jdk.experimental.value.ValueType; +import jdk.incubator.mvt.ValueType; import org.testng.annotations.Test; import static org.testng.Assert.*; --- old/jdk/test/valhalla/mvt/MVTTest.java 2017-09-14 22:58:11.000000000 -0700 +++ new/jdk/test/valhalla/mvt/MVTTest.java 2017-09-14 22:58:10.000000000 -0700 @@ -23,13 +23,15 @@ /* * @test + * @modules java.base/valhalla.shady + * jdk.incubator.mvt * @run testng/othervm -XX:+EnableMVT -XX:+ValueArrayFlatten MVTTest * @run testng/othervm -XX:+EnableMVT -XX:-ValueArrayFlatten MVTTest * @run testng/othervm -XX:+EnableMVT -Dvalhalla.enableValueLambdaForms=true MVTTest * @run testng/othervm -XX:+EnableMVT -Dvalhalla.enableValueLambdaForms=true -Dvalhalla.enablePoolPatches=true MVTTest */ -import jdk.experimental.value.ValueType; +import jdk.incubator.mvt.ValueType; import org.testng.annotations.Test; import valhalla.shady.MinimalValueTypes_1_0; --- old/jdk/test/valhalla/mvt/MethodHandlesTest.java 2017-09-14 22:58:12.000000000 -0700 +++ new/jdk/test/valhalla/mvt/MethodHandlesTest.java 2017-09-14 22:58:12.000000000 -0700 @@ -20,8 +20,8 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -import jdk.experimental.value.ValueType; -import jvm.internal.value.ValueCapableClass; +import jdk.incubator.mvt.ValueType; +import jdk.incubator.mvt.ValueCapableClass; import org.testng.annotations.Test; import java.lang.invoke.MethodHandle; --- old/jdk/test/valhalla/mvt/Point.java 2017-09-14 22:58:13.000000000 -0700 +++ new/jdk/test/valhalla/mvt/Point.java 2017-09-14 22:58:13.000000000 -0700 @@ -23,7 +23,7 @@ * questions. */ -import jvm.internal.value.ValueCapableClass; +import jdk.incubator.mvt.ValueCapableClass; import java.lang.invoke.MethodHandles; import java.util.Objects; --- old/jdk/test/valhalla/mvt/PrivatePoint.java 2017-09-14 22:58:14.000000000 -0700 +++ new/jdk/test/valhalla/mvt/PrivatePoint.java 2017-09-14 22:58:13.000000000 -0700 @@ -23,7 +23,7 @@ * questions. */ -import jvm.internal.value.ValueCapableClass; +import jdk.incubator.mvt.ValueCapableClass; import java.util.Objects; --- old/jdk/test/valhalla/mvt/TestValueInValue.java 2017-09-14 22:58:15.000000000 -0700 +++ new/jdk/test/valhalla/mvt/TestValueInValue.java 2017-09-14 22:58:14.000000000 -0700 @@ -26,7 +26,7 @@ * @run testng/othervm -Xverify:none -XX:+EnableMVT TestValueInValue */ -import jdk.experimental.value.ValueType; +import jdk.incubator.mvt.ValueType; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; --- old/jdk/test/valhalla/mvt/UnreflectWithersTest.java 2017-09-14 22:58:15.000000000 -0700 +++ new/jdk/test/valhalla/mvt/UnreflectWithersTest.java 2017-09-14 22:58:15.000000000 -0700 @@ -26,8 +26,8 @@ * @run testng/othervm -XX:+EnableMVT -Dvalhalla.enablePoolPatches=true UnreflectWithersTest */ -import jdk.experimental.value.ValueType; -import jvm.internal.value.ValueCapableClass; +import jdk.incubator.mvt.ValueType; +import jdk.incubator.mvt.ValueCapableClass; import org.testng.annotations.Test; import java.lang.invoke.MethodHandle; --- old/jdk/test/valhalla/mvt/WithFieldTest.java 2017-09-14 22:58:17.000000000 -0700 +++ new/jdk/test/valhalla/mvt/WithFieldTest.java 2017-09-14 22:58:16.000000000 -0700 @@ -22,7 +22,7 @@ */ import jdk.experimental.value.MethodHandleBuilder; -import jdk.experimental.value.ValueType; +import jdk.incubator.mvt.ValueType; import org.testng.annotations.Test; import java.lang.invoke.MethodHandle; @@ -33,6 +33,8 @@ /* * @test + * @modules java.base/jdk.experimental.value + * jdk.incubator.mvt * @run testng/othervm -XX:+EnableMVT -Dvalhalla.enablePoolPatches=true WithFieldTest */ --- old/jdk/test/valhalla/mvt/modules/m/module-info.java 2017-09-14 22:58:17.000000000 -0700 +++ new/jdk/test/valhalla/mvt/modules/m/module-info.java 2017-09-14 22:58:17.000000000 -0700 @@ -22,5 +22,6 @@ */ module m { + requires jdk.incubator.mvt; exports p; } --- old/jdk/test/valhalla/mvt/modules/m/p/Main.java 2017-09-14 22:58:18.000000000 -0700 +++ new/jdk/test/valhalla/mvt/modules/m/p/Main.java 2017-09-14 22:58:18.000000000 -0700 @@ -30,7 +30,7 @@ import java.util.List; import java.util.stream.Collectors; -import jdk.experimental.value.ValueType; +import jdk.incubator.mvt.ValueType; import p.internal.Point; public class Main { --- old/jdk/test/valhalla/mvt/modules/m/p/internal/Point.java 2017-09-14 22:58:19.000000000 -0700 +++ new/jdk/test/valhalla/mvt/modules/m/p/internal/Point.java 2017-09-14 22:58:19.000000000 -0700 @@ -23,7 +23,7 @@ package p.internal; -import jvm.internal.value.ValueCapableClass; +import jdk.incubator.mvt.ValueCapableClass; import java.util.Objects; --- old/jdk/test/valhalla/mvt/point/Point.java 2017-09-14 22:58:20.000000000 -0700 +++ new/jdk/test/valhalla/mvt/point/Point.java 2017-09-14 22:58:20.000000000 -0700 @@ -23,7 +23,7 @@ * questions. */ -import jvm.internal.value.ValueCapableClass; +import jdk.incubator.mvt.ValueCapableClass; @ValueCapableClass final class Point { --- old/jdk/test/valhalla/mvt/point/TestPoint.java 2017-09-14 22:58:21.000000000 -0700 +++ new/jdk/test/valhalla/mvt/point/TestPoint.java 2017-09-14 22:58:21.000000000 -0700 @@ -26,7 +26,7 @@ import jdk.experimental.bytecode.MacroCodeBuilder.CondKind; import jdk.experimental.bytecode.TypeTag; import jdk.experimental.value.MethodHandleBuilder; -import jdk.experimental.value.ValueType; +import jdk.incubator.mvt.ValueType; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; @@ -40,6 +40,9 @@ /* * @test + * @modules java.base/jdk.experimental.bytecode + * java.base/jdk.experimental.value + * jdk.incubator.mvt * @run testng/othervm -XX:+EnableMVT TestPoint */ --- old/jdk/test/valhalla/mvt/vector/Long2.java 2017-09-14 22:58:22.000000000 -0700 +++ new/jdk/test/valhalla/mvt/vector/Long2.java 2017-09-14 22:58:22.000000000 -0700 @@ -23,7 +23,7 @@ * questions. */ -import jvm.internal.value.ValueCapableClass; +import jdk.incubator.mvt.ValueCapableClass; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; --- old/jdk/test/valhalla/mvt/vector/VectorLibrary.java 2017-09-14 22:58:23.000000000 -0700 +++ new/jdk/test/valhalla/mvt/vector/VectorLibrary.java 2017-09-14 22:58:22.000000000 -0700 @@ -23,7 +23,7 @@ * questions. */ -import jdk.experimental.value.ValueType; +import jdk.incubator.mvt.ValueType; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; --- old/jdk/test/valhalla/mvt/vector/VectorTest.java 2017-09-14 22:58:24.000000000 -0700 +++ new/jdk/test/valhalla/mvt/vector/VectorTest.java 2017-09-14 22:58:23.000000000 -0700 @@ -23,7 +23,7 @@ * questions. */ -import jdk.experimental.value.ValueType; +import jdk.incubator.mvt.ValueType; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; --- old/jdk/test/valhalla/mvt/vector/VectorUtils.java 2017-09-14 22:58:25.000000000 -0700 +++ new/jdk/test/valhalla/mvt/vector/VectorUtils.java 2017-09-14 22:58:24.000000000 -0700 @@ -23,7 +23,7 @@ * questions. */ -import jdk.experimental.value.ValueType; +import jdk.incubator.mvt.ValueType; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; --- old/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java 2017-09-14 22:58:25.000000000 -0700 +++ new/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java 2017-09-14 22:58:25.000000000 -0700 @@ -154,6 +154,7 @@ /** A symbol for the java.base module. */ public final ModuleSymbol java_base; + public final ModuleSymbol jdk_incubator_mvt; /** Predefined types. */ @@ -529,8 +530,13 @@ //avoid completing java.base during the Symtab initialization java_base.completer = Completer.NULL_COMPLETER; java_base.visiblePackages = Collections.emptyMap(); + + jdk_incubator_mvt = enterModule(names.fromString("jdk.incubator.mvt")); + jdk_incubator_mvt.completer = Completer.NULL_COMPLETER; + jdk_incubator_mvt.visiblePackages = Collections.emptyMap(); } else { java_base = noModule; + jdk_incubator_mvt = noModule; } // Get the initial completer for ModuleSymbols from Modules @@ -600,7 +606,9 @@ lambdaMetafactory = enterClass("java.lang.invoke.LambdaMetafactory"); stringConcatFactory = enterClass("java.lang.invoke.StringConcatFactory"); functionalInterfaceType = enterClass("java.lang.FunctionalInterface"); - valueCapableClass = enterClass("jvm.internal.value.ValueCapableClass"); + + Name vccName = names.fromString("jdk.incubator.mvt.ValueCapableClass"); + valueCapableClass = enterClass(jdk_incubator_mvt, vccName).type; synthesizeEmptyInterfaceIfMissing(autoCloseableType); synthesizeEmptyInterfaceIfMissing(cloneableType); @@ -646,8 +654,10 @@ arrayClass); arrayClass.members().enter(arrayCloneMethod); - if (java_base != noModule) + if (java_base != noModule) { java_base.completer = moduleCompleter::complete; //bootstrap issues + jdk_incubator_mvt.completer = moduleCompleter::complete; //bootstrap issues + } } --- old/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java 2017-09-14 22:58:26.000000000 -0700 +++ new/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java 2017-09-14 22:58:26.000000000 -0700 @@ -81,6 +81,7 @@ import com.sun.tools.javac.jvm.JNIWriter; import com.sun.tools.javac.main.Option; import com.sun.tools.javac.resources.CompilerProperties.Errors; +import com.sun.tools.javac.resources.CompilerProperties.Notes; import com.sun.tools.javac.resources.CompilerProperties.Warnings; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; @@ -1305,7 +1306,7 @@ .collect(Collectors.joining(",")); if (!incubatingModules.isEmpty()) { - log.warning(Warnings.IncubatingModules(incubatingModules)); + log.note(Notes.IncubatingModules(incubatingModules)); } allModules = result; --- old/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties 2017-09-14 22:58:27.000000000 -0700 +++ new/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties 2017-09-14 22:58:27.000000000 -0700 @@ -1584,7 +1584,7 @@ module name component {0} should avoid terminal digits # 0: string -compiler.warn.incubating.modules=\ +compiler.note.incubating.modules=\ using incubating module(s): {0} # 0: symbol, 1: symbol --- old/langtools/test/tools/javac/diags/examples.not-yet.txt 2017-09-14 22:58:28.000000000 -0700 +++ new/langtools/test/tools/javac/diags/examples.not-yet.txt 2017-09-14 22:58:28.000000000 -0700 @@ -106,7 +106,7 @@ compiler.warn.big.major.version # ClassReader compiler.warn.future.attr # ClassReader compiler.warn.illegal.char.for.encoding -compiler.warn.incubating.modules # requires adjusted classfile +compiler.note.incubating.modules # requires adjusted classfile compiler.warn.invalid.archive.file compiler.warn.override.bridge compiler.warn.position.overflow # CRTable: caused by files with long lines >= 1024 chars --- old/langtools/test/tools/javac/modules/IncubatingTest.java 2017-09-14 22:58:29.000000000 -0700 +++ new/langtools/test/tools/javac/modules/IncubatingTest.java 2017-09-14 22:58:29.000000000 -0700 @@ -189,19 +189,15 @@ log = new JavacTask(tb) .options("--module-path", classes.toString(), "--add-modules", "jdk.i", - "-XDrawDiagnostics", - "-Werror") + "-XDrawDiagnostics") .outdir(testClasses) .files(findJavaFiles(testSrc)) - .run(Expect.FAIL) + .run(Expect.SUCCESS) .writeAll() .getOutputLines(Task.OutputKind.DIRECT); expected = Arrays.asList( - "- compiler.warn.incubating.modules: jdk.i", - "- compiler.err.warnings.and.werror", - "1 error", - "1 warning" + "- compiler.note.incubating.modules: jdk.i" ); if (!expected.equals(log)) { @@ -217,19 +213,15 @@ log = new JavacTask(tb) .options("--module-path", classes.toString(), - "-XDrawDiagnostics", - "-Werror") + "-XDrawDiagnostics") .outdir(testModuleClasses) .files(findJavaFiles(testModuleSrc)) - .run(Expect.FAIL) + .run(Expect.SUCCESS) .writeAll() .getOutputLines(Task.OutputKind.DIRECT); expected = Arrays.asList( - "- compiler.warn.incubating.modules: jdk.i", - "- compiler.err.warnings.and.werror", - "1 error", - "1 warning" + "- compiler.note.incubating.modules: jdk.i" ); if (!expected.equals(log)) { --- old/langtools/test/tools/javac/valhalla/minimalvalues/CheckClone.java 2017-09-14 22:58:30.000000000 -0700 +++ new/langtools/test/tools/javac/valhalla/minimalvalues/CheckClone.java 2017-09-14 22:58:30.000000000 -0700 @@ -1,12 +1,12 @@ /* * @test /nodynamiccopyright/ * @summary Value types do not support clone - * @modules java.base/jvm.internal.value - * @compile/fail/ref=CheckClone.out -XDrawDiagnostics -Werror -Xlint:values CheckClone.java + * @modules jdk.incubator.mvt + * @compile/fail/ref=CheckClone.out -XDrawDiagnostics -Werror -Xlint:values CheckClone.java */ -@jvm.internal.value.ValueCapableClass +@jdk.incubator.mvt.ValueCapableClass final class CheckClone { - @jvm.internal.value.ValueCapableClass + @jdk.incubator.mvt.ValueCapableClass final class InnerValue { void foo(InnerValue iv) { iv.clone(); // <-- error --- old/langtools/test/tools/javac/valhalla/minimalvalues/CheckClone.out 2017-09-14 22:58:31.000000000 -0700 +++ new/langtools/test/tools/javac/valhalla/minimalvalues/CheckClone.out 2017-09-14 22:58:30.000000000 -0700 @@ -1,3 +1,4 @@ +- compiler.note.incubating.modules: jdk.incubator.mvt CheckClone.java:12:21: compiler.warn.value.does.not.support: calling java.lang.Object's method: clone CheckClone.java:16:22: compiler.warn.value.does.not.support: overriding java.lang.Object's method: clone - compiler.err.warnings.and.werror --- old/langtools/test/tools/javac/valhalla/minimalvalues/CheckCyclicMembership.java 2017-09-14 22:58:31.000000000 -0700 +++ new/langtools/test/tools/javac/valhalla/minimalvalues/CheckCyclicMembership.java 2017-09-14 22:58:31.000000000 -0700 @@ -1,15 +1,15 @@ /* * @test /nodynamiccopyright/ * @summary Value types may not declare fields of its own type either directly or indirectly. - * @modules java.base/jvm.internal.value + * @modules jdk.incubator.mvt * @compile/fail/ref=CheckCyclicMembership.out -XDrawDiagnostics -Werror -Xlint:values CheckCyclicMembership.java */ -@jvm.internal.value.ValueCapableClass +@jdk.incubator.mvt.ValueCapableClass final class CheckCyclicMembership { class InnerRef { CheckCyclicMembership ccm; } - @jvm.internal.value.ValueCapableClass final class InnerValue { + @jdk.incubator.mvt.ValueCapableClass final class InnerValue { final CheckCyclicMembership ccm = new CheckCyclicMembership(); // Error. } final CheckCyclicMembership ccm = new CheckCyclicMembership(); // Error. --- old/langtools/test/tools/javac/valhalla/minimalvalues/CheckCyclicMembership.out 2017-09-14 22:58:32.000000000 -0700 +++ new/langtools/test/tools/javac/valhalla/minimalvalues/CheckCyclicMembership.out 2017-09-14 22:58:32.000000000 -0700 @@ -1,3 +1,4 @@ +- compiler.note.incubating.modules: jdk.incubator.mvt CheckCyclicMembership.java:15:33: compiler.warn.cyclic.value.type.membership: CheckCyclicMembership CheckCyclicMembership.java:13:37: compiler.warn.cyclic.value.type.membership: CheckCyclicMembership.InnerValue CheckCyclicMembership.java:13:37: compiler.warn.cyclic.value.type.membership: CheckCyclicMembership --- old/langtools/test/tools/javac/valhalla/minimalvalues/CheckEquals.java 2017-09-14 22:58:33.000000000 -0700 +++ new/langtools/test/tools/javac/valhalla/minimalvalues/CheckEquals.java 2017-09-14 22:58:33.000000000 -0700 @@ -1,10 +1,10 @@ /* * @test /nodynamiccopyright/ * @summary Value types do not support == or != - * @modules java.base/jvm.internal.value + * @modules jdk.incubator.mvt * @compile/fail/ref=CheckEquals.out -XDrawDiagnostics -Werror -Xlint:values CheckEquals.java */ -@jvm.internal.value.ValueCapableClass +@jdk.incubator.mvt.ValueCapableClass final class CheckEquals { boolean foo(CheckEquals a, CheckEquals b) { return (a == b) || (a != b); --- old/langtools/test/tools/javac/valhalla/minimalvalues/CheckEquals.out 2017-09-14 22:58:34.000000000 -0700 +++ new/langtools/test/tools/javac/valhalla/minimalvalues/CheckEquals.out 2017-09-14 22:58:34.000000000 -0700 @@ -1,3 +1,4 @@ +- compiler.note.incubating.modules: jdk.incubator.mvt CheckEquals.java:10:19: compiler.warn.value.does.not.support: == CheckEquals.java:10:31: compiler.warn.value.does.not.support: != - compiler.err.warnings.and.werror --- old/langtools/test/tools/javac/valhalla/minimalvalues/CheckExtends.java 2017-09-14 22:58:35.000000000 -0700 +++ new/langtools/test/tools/javac/valhalla/minimalvalues/CheckExtends.java 2017-09-14 22:58:35.000000000 -0700 @@ -1,9 +1,9 @@ /* * @test /nodynamiccopyright/ * @summary Values may not extend - * @modules java.base/jvm.internal.value + * @modules jdk.incubator.mvt * @compile/fail/ref=CheckExtends.out -XDrawDiagnostics -Werror -Xlint:values CheckExtends.java */ -@jvm.internal.value.ValueCapableClass +@jdk.incubator.mvt.ValueCapableClass final class CheckExtends extends Object { } --- old/langtools/test/tools/javac/valhalla/minimalvalues/CheckExtends.out 2017-09-14 22:58:36.000000000 -0700 +++ new/langtools/test/tools/javac/valhalla/minimalvalues/CheckExtends.out 2017-09-14 22:58:36.000000000 -0700 @@ -1,3 +1,4 @@ +- compiler.note.incubating.modules: jdk.incubator.mvt CheckExtends.java:8:7: compiler.warn.value.may.not.extend - compiler.err.warnings.and.werror 1 error --- old/langtools/test/tools/javac/valhalla/minimalvalues/CheckFinal.java 2017-09-14 22:58:37.000000000 -0700 +++ new/langtools/test/tools/javac/valhalla/minimalvalues/CheckFinal.java 2017-09-14 22:58:36.000000000 -0700 @@ -1,16 +1,16 @@ /* * @test /nodynamiccopyright/ * @summary Value types and their instance fields must be final - * @modules java.base/jvm.internal.value + * @modules jdk.incubator.mvt * @compile/fail/ref=CheckFinal.out -XDrawDiagnostics -Werror -Xlint:values CheckFinal.java */ -@jvm.internal.value.ValueCapableClass +@jdk.incubator.mvt.ValueCapableClass class CheckFinal { // <- error int x; // <- error void f(int x) { // <- ok int y; // <- ok - @jvm.internal.value.ValueCapableClass + @jdk.incubator.mvt.ValueCapableClass final class CheckLocalFinal { int x; // <- error. } --- old/langtools/test/tools/javac/valhalla/minimalvalues/CheckFinal.out 2017-09-14 22:58:37.000000000 -0700 +++ new/langtools/test/tools/javac/valhalla/minimalvalues/CheckFinal.out 2017-09-14 22:58:37.000000000 -0700 @@ -1,3 +1,4 @@ +- compiler.note.incubating.modules: jdk.incubator.mvt CheckFinal.java:9:1: compiler.warn.value.must.be.final CheckFinal.java:10:9: compiler.warn.value.field.must.be.final CheckFinal.java:15:17: compiler.warn.value.field.must.be.final --- old/langtools/test/tools/javac/valhalla/minimalvalues/CheckFinalize.java 2017-09-14 22:58:38.000000000 -0700 +++ new/langtools/test/tools/javac/valhalla/minimalvalues/CheckFinalize.java 2017-09-14 22:58:38.000000000 -0700 @@ -1,15 +1,15 @@ /* * @test /nodynamiccopyright/ * @summary Value types do not support finalize - * @modules java.base/jvm.internal.value + * @modules jdk.incubator.mvt * @compile/fail/ref=CheckFinalize.out -XDrawDiagnostics -Werror -Xlint:values CheckFinalize.java */ -@jvm.internal.value.ValueCapableClass +@jdk.incubator.mvt.ValueCapableClass final class CheckFinalize { @Override protected void finalize() {} // <-- error - @jvm.internal.value.ValueCapableClass + @jdk.incubator.mvt.ValueCapableClass final class CheckFinalizeInner {} void foo(CheckFinalizeInner cfi, CheckFinalize cf) { --- old/langtools/test/tools/javac/valhalla/minimalvalues/CheckFinalize.out 2017-09-14 22:58:39.000000000 -0700 +++ new/langtools/test/tools/javac/valhalla/minimalvalues/CheckFinalize.out 2017-09-14 22:58:39.000000000 -0700 @@ -1,3 +1,4 @@ +- compiler.note.incubating.modules: jdk.incubator.mvt CheckFinalize.java:16:12: compiler.err.report.access: finalize(), protected, java.lang.Object CheckFinalize.java:10:20: compiler.warn.value.does.not.support: overriding java.lang.Object's method: finalize CheckFinalize.java:16:21: compiler.warn.value.does.not.support: calling java.lang.Object's method: finalize --- old/langtools/test/tools/javac/valhalla/minimalvalues/CheckIdentityHash.java 2017-09-14 22:58:39.000000000 -0700 +++ new/langtools/test/tools/javac/valhalla/minimalvalues/CheckIdentityHash.java 2017-09-14 22:58:39.000000000 -0700 @@ -1,10 +1,10 @@ /* * @test /nodynamiccopyright/ * @summary Value types do not support identityHashCode - * @modules java.base/jvm.internal.value + * @modules jdk.incubator.mvt * @compile/fail/ref=CheckIdentityHash.out -XDrawDiagnostics -Werror -Xlint:values CheckIdentityHash.java */ -@jvm.internal.value.ValueCapableClass +@jdk.incubator.mvt.ValueCapableClass final class CheckIdentityHash { int identityHashCode(CheckIdentityHash x) { return 0; --- old/langtools/test/tools/javac/valhalla/minimalvalues/CheckIdentityHash.out 2017-09-14 22:58:40.000000000 -0700 +++ new/langtools/test/tools/javac/valhalla/minimalvalues/CheckIdentityHash.out 2017-09-14 22:58:40.000000000 -0700 @@ -1,3 +1,4 @@ +- compiler.note.incubating.modules: jdk.incubator.mvt CheckIdentityHash.java:14:32: compiler.warn.value.does.not.support: identityHashCode CheckIdentityHash.java:15:32: compiler.warn.value.does.not.support: identityHashCode CheckIdentityHash.java:16:42: compiler.warn.value.does.not.support: identityHashCode --- old/langtools/test/tools/javac/valhalla/minimalvalues/CheckIdentityHash01.java 2017-09-14 22:58:41.000000000 -0700 +++ new/langtools/test/tools/javac/valhalla/minimalvalues/CheckIdentityHash01.java 2017-09-14 22:58:41.000000000 -0700 @@ -1,12 +1,12 @@ /* * @test /nodynamiccopyright/ * @summary Value types do not support identityHashCode - * @modules java.base/jvm.internal.value + * @modules jdk.incubator.mvt * @compile/fail/ref=CheckIdentityHash01.out -XDrawDiagnostics -Werror -Xlint:values CheckIdentityHash01.java */ import static java.lang.System.*; -@jvm.internal.value.ValueCapableClass +@jdk.incubator.mvt.ValueCapableClass final class CheckIdentityHash01 { void test(CheckIdentityHash01 v) { --- old/langtools/test/tools/javac/valhalla/minimalvalues/CheckIdentityHash01.out 2017-09-14 22:58:42.000000000 -0700 +++ new/langtools/test/tools/javac/valhalla/minimalvalues/CheckIdentityHash01.out 2017-09-14 22:58:41.000000000 -0700 @@ -1,3 +1,4 @@ +- compiler.note.incubating.modules: jdk.incubator.mvt CheckIdentityHash01.java:13:25: compiler.warn.value.does.not.support: identityHashCode CheckIdentityHash01.java:14:25: compiler.warn.value.does.not.support: identityHashCode CheckIdentityHash01.java:17:32: compiler.warn.value.does.not.support: identityHashCode --- old/langtools/test/tools/javac/valhalla/minimalvalues/CheckNullAssign.java 2017-09-14 22:58:43.000000000 -0700 +++ new/langtools/test/tools/javac/valhalla/minimalvalues/CheckNullAssign.java 2017-09-14 22:58:42.000000000 -0700 @@ -1,10 +1,10 @@ /* * @test /nodynamiccopyright/ * @summary Assignment of null to value types should be disallowed. - * @modules java.base/jvm.internal.value + * @modules jdk.incubator.mvt * @compile/fail/ref=CheckNullAssign.out -XDrawDiagnostics -Werror -Xlint:values CheckNullAssign.java */ -@jvm.internal.value.ValueCapableClass +@jdk.incubator.mvt.ValueCapableClass final class CheckNullAssign { CheckNullAssign foo(CheckNullAssign cna) { // All of the below involve subtype/assignability checks and should be rejected. --- old/langtools/test/tools/javac/valhalla/minimalvalues/CheckNullAssign.out 2017-09-14 22:58:44.000000000 -0700 +++ new/langtools/test/tools/javac/valhalla/minimalvalues/CheckNullAssign.out 2017-09-14 22:58:43.000000000 -0700 @@ -1,3 +1,4 @@ +- compiler.note.incubating.modules: jdk.incubator.mvt CheckNullAssign.java:11:32: compiler.warn.prob.found.req: (compiler.misc.inconvertible.types: compiler.misc.type.null, CheckNullAssign) CheckNullAssign.java:12:15: compiler.warn.prob.found.req: (compiler.misc.inconvertible.types: compiler.misc.type.null, CheckNullAssign) CheckNullAssign.java:13:13: compiler.warn.prob.found.req: (compiler.misc.inconvertible.types: compiler.misc.type.null, CheckNullAssign) --- old/langtools/test/tools/javac/valhalla/minimalvalues/CheckNullCastable.java 2017-09-14 22:58:45.000000000 -0700 +++ new/langtools/test/tools/javac/valhalla/minimalvalues/CheckNullCastable.java 2017-09-14 22:58:44.000000000 -0700 @@ -1,10 +1,10 @@ /* * @test /nodynamiccopyright/ * @summary null cannot be casted to and compared with value types. - * @modules java.base/jvm.internal.value + * @modules jdk.incubator.mvt * @compile/fail/ref=CheckNullCastable.out -XDrawDiagnostics -Werror -Xlint:values CheckNullCastable.java */ -@jvm.internal.value.ValueCapableClass +@jdk.incubator.mvt.ValueCapableClass final class CheckNullCastable { void foo(CheckNullCastable cnc) { CheckNullCastable cncl = (CheckNullCastable) null; --- old/langtools/test/tools/javac/valhalla/minimalvalues/CheckNullCastable.out 2017-09-14 22:58:45.000000000 -0700 +++ new/langtools/test/tools/javac/valhalla/minimalvalues/CheckNullCastable.out 2017-09-14 22:58:45.000000000 -0700 @@ -1,3 +1,4 @@ +- compiler.note.incubating.modules: jdk.incubator.mvt CheckNullCastable.java:10:54: compiler.warn.prob.found.req: (compiler.misc.inconvertible.types: compiler.misc.type.null, CheckNullCastable) CheckNullCastable.java:11:17: compiler.warn.incomparable.types: CheckNullCastable, compiler.misc.type.null CheckNullCastable.java:11:17: compiler.warn.value.does.not.support: != --- old/langtools/test/tools/javac/valhalla/minimalvalues/CheckSync.java 2017-09-14 22:58:46.000000000 -0700 +++ new/langtools/test/tools/javac/valhalla/minimalvalues/CheckSync.java 2017-09-14 22:58:46.000000000 -0700 @@ -1,16 +1,16 @@ /* * @test /nodynamiccopyright/ * @summary May not synchronize on value types - * @modules java.base/jvm.internal.value + * @modules jdk.incubator.mvt * @compile/fail/ref=CheckSync.out -XDrawDiagnostics -Werror -Xlint:values CheckSync.java */ /* Note: ATM, value types do not have jlO in their lineage. So they anyway cannot synchronize using the methods declared on jlO. */ -@jvm.internal.value.ValueCapableClass +@jdk.incubator.mvt.ValueCapableClass public final class CheckSync { - @jvm.internal.value.ValueCapableClass + @jdk.incubator.mvt.ValueCapableClass final class Val { void foo() { --- old/langtools/test/tools/javac/valhalla/minimalvalues/CheckSync.out 2017-09-14 22:58:47.000000000 -0700 +++ new/langtools/test/tools/javac/valhalla/minimalvalues/CheckSync.out 2017-09-14 22:58:47.000000000 -0700 @@ -1,3 +1,4 @@ +- compiler.note.incubating.modules: jdk.incubator.mvt CheckSync.java:38:12: compiler.err.cant.apply.symbols: kindname.method, wait, java.lang.String,{(compiler.misc.inapplicable.method: kindname.method, java.lang.Object, wait(long), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.String, long))),(compiler.misc.inapplicable.method: kindname.method, java.lang.Object, wait(long,int), (compiler.misc.arg.length.mismatch)),(compiler.misc.inapplicable.method: kindname.method, java.lang.Object, wait(), (compiler.misc.arg.length.mismatch))} CheckSync.java:18:17: compiler.warn.value.does.not.support: calling java.lang.Object's method: wait CheckSync.java:19:17: compiler.warn.value.does.not.support: calling java.lang.Object's method: wait --- old/langtools/test/tools/javac/valhalla/minimalvalues/CheckSynchronized.java 2017-09-14 22:58:48.000000000 -0700 +++ new/langtools/test/tools/javac/valhalla/minimalvalues/CheckSynchronized.java 2017-09-14 22:58:48.000000000 -0700 @@ -1,10 +1,10 @@ /* * @test /nodynamiccopyright/ * @summary Check behavior of synzhronized key word on value instances and methods. - * @modules java.base/jvm.internal.value + * @modules jdk.incubator.mvt * @compile/fail/ref=CheckSynchronized.out -XDrawDiagnostics -Werror -Xlint:values CheckSynchronized.java */ -@jvm.internal.value.ValueCapableClass +@jdk.incubator.mvt.ValueCapableClass final class CheckSynchronized { synchronized void foo() { // <<-- ERROR, no monitor associated with `this' } --- old/langtools/test/tools/javac/valhalla/minimalvalues/CheckSynchronized.out 2017-09-14 22:58:49.000000000 -0700 +++ new/langtools/test/tools/javac/valhalla/minimalvalues/CheckSynchronized.out 2017-09-14 22:58:49.000000000 -0700 @@ -1,3 +1,4 @@ +- compiler.note.incubating.modules: jdk.incubator.mvt CheckSynchronized.java:9:23: compiler.warn.mod.not.allowed.here: synchronized CheckSynchronized.java:12:9: compiler.warn.type.found.req: CheckSynchronized, (compiler.misc.type.req.ref) CheckSynchronized.java:15:9: compiler.warn.type.found.req: CheckSynchronized, (compiler.misc.type.req.ref) --- old/langtools/test/tools/javac/valhalla/minimalvalues/ClassFileReaderTest.java 2017-09-14 22:58:50.000000000 -0700 +++ new/langtools/test/tools/javac/valhalla/minimalvalues/ClassFileReaderTest.java 2017-09-14 22:58:50.000000000 -0700 @@ -1,7 +1,7 @@ /* * @test /nodynamiccopyright/ * @summary Verify that the class reader flags Value capable classes appropriately. - * @modules java.base/jvm.internal.value + * @modules jdk.incubator.mvt * @compile Point.java * @compile/fail/ref=ClassFileReaderTest.out -XDrawDiagnostics -Werror -Xlint:values ClassFileReaderTest.java */ --- old/langtools/test/tools/javac/valhalla/minimalvalues/ClassFileReaderTest.out 2017-09-14 22:58:51.000000000 -0700 +++ new/langtools/test/tools/javac/valhalla/minimalvalues/ClassFileReaderTest.out 2017-09-14 22:58:51.000000000 -0700 @@ -1,3 +1,4 @@ +- compiler.note.incubating.modules: jdk.incubator.mvt ClassFileReaderTest.java:10:19: compiler.warn.prob.found.req: (compiler.misc.inconvertible.types: compiler.misc.type.null, Point) - compiler.err.warnings.and.werror 1 error --- old/langtools/test/tools/javac/valhalla/minimalvalues/Point.java 2017-09-14 22:58:52.000000000 -0700 +++ new/langtools/test/tools/javac/valhalla/minimalvalues/Point.java 2017-09-14 22:58:51.000000000 -0700 @@ -21,7 +21,7 @@ * questions. */ -@jvm.internal.value.ValueCapableClass +@jdk.incubator.mvt.ValueCapableClass final class Point { final int x = 0; final int y = 0; --- old/langtools/test/tools/javac/valhalla/values/CheckNoInvokeDirect.java 2017-09-14 22:58:52.000000000 -0700 +++ new/langtools/test/tools/javac/valhalla/values/CheckNoInvokeDirect.java 2017-09-14 22:58:52.000000000 -0700 @@ -66,11 +66,11 @@ "CheckNoInvokeDirect$Value.class").toString() }; runCheck(params, new String [] { - "#1 = Methodref #7.#24 // \";Qjava/lang/__Value;\".\"\":()V", - "#2 = Methodref #6.#25 // \";QCheckNoInvokeDirect$Value;\".soo:()V", - "#3 = Methodref #6.#26 // \";QCheckNoInvokeDirect$Value;\".foo:()V", - "#4 = Methodref #6.#27 // \";QCheckNoInvokeDirect$Value;\".goo:()V", - "#5 = Methodref #6.#28 // \";QCheckNoInvokeDirect$Value;\".boo:()V", + "#1 = Methodref #7.#19 // \";Qjava/lang/__Value;\".\"\":()V", + "#2 = Methodref #6.#20 // \";QCheckNoInvokeDirect$Value;\".soo:()V", + "#3 = Methodref #6.#21 // \";QCheckNoInvokeDirect$Value;\".foo:()V", + "#4 = Methodref #6.#22 // \";QCheckNoInvokeDirect$Value;\".goo:()V", + "#5 = Methodref #6.#23 // \";QCheckNoInvokeDirect$Value;\".boo:()V", "0: vload 0", "2: invokespecial #1 // Method \";Qjava/lang/__Value;\".\"\":()V", --- old/jdk/src/java.base/share/classes/jdk/experimental/value/ValueType.java 2017-09-14 22:58:53.000000000 -0700 +++ /dev/null 2017-09-14 22:58:53.000000000 -0700 @@ -1,582 +0,0 @@ -/* - * Copyright (c) 2016, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -package jdk.experimental.value; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodHandles.Lookup; -import java.lang.invoke.MethodType; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Consumer; -import java.util.function.Supplier; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import java.util.stream.Stream; - -import jdk.experimental.bytecode.AnnotationsBuilder.Kind; -import jdk.experimental.bytecode.Flag; -import jdk.experimental.bytecode.Opcode; -import jdk.experimental.value.MethodHandleBuilder.IsolatedMethodBuilder; -import jdk.experimental.value.MethodHandleBuilder.MethodHandleCodeBuilder; -import jdk.experimental.value.ValueType.ValueHandleKind.ValueHandleKey; -import jdk.experimental.bytecode.MacroCodeBuilder.CondKind; -import jdk.experimental.bytecode.TypeTag; -import jdk.internal.misc.Unsafe; -import sun.invoke.util.BytecodeDescriptor; -import sun.invoke.util.Wrapper; -import valhalla.shady.MinimalValueTypes_1_0; - -// Rough place holder just now... -public class ValueType { - - enum ValueHandleKind { - BOX("box"), - UNBOX("unbox"), - DEFAULT("defaultValueConstant"), - EQ("substitutabilityTest"), - HASH("substitutabilityHashCode"), - ARRAYLENGTH("arrayLength"), - WITHER("findWither", Lookup.class, String.class, Class.class) { - @Override - ValueHandleKey key(Object fieldName) { - return new ValueHandleKey(this, fieldName); - } - }, - UNREFLECT_WITHERS("unreflectWithers", Lookup.class, boolean.class, Field[].class) { - @Override - ValueHandleKey key(Object fields) { - return new ValueHandleKey(this, fields); - } - }, - NEWARRAY("newArray"), - VALOAD("arrayGetter"), - VASTORE("arraySetter"), - MULTINEWARRAY("newMultiArray", int.class) { - @Override - ValueHandleKey key(Object dims) { - return new ValueHandleKey(this, dims); - } - }, - IDENTITY("identity"), - GETTER("findGetter", Lookup.class, String.class, Class.class) { - @Override - ValueHandleKey key(Object fieldName) { - return new ValueHandleKey(this, fieldName); - } - }; - - final MethodHandle handle; - - ValueHandleKind(String handleName, Class... argtypes) { - try { - this.handle = MethodHandles.lookup().findVirtual(ValueType.class, handleName, MethodType.methodType(MethodHandle.class, argtypes)); - } catch (ReflectiveOperationException ex) { - throw new IllegalArgumentException("Cannot initialize value handle key for: " + handleName); - } - } - - String handleName() { - return MethodHandles.lookup().revealDirect(handle).getName(); - } - - MethodType handleType() { - return MethodHandles.lookup().revealDirect(handle).getMethodType(); - } - - ValueHandleKey key() { - return new ValueHandleKey(this, null); - } - - ValueHandleKey key(Object optArg) { - throw new IllegalStateException(); - } - - static class ValueHandleKey { - ValueHandleKind kind; - Object optArg; - - ValueHandleKey(ValueHandleKind kind, Object optArg) { - this.kind = kind; - this.optArg = optArg; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof ValueHandleKey) { - ValueHandleKey that = (ValueHandleKey)obj; - return Objects.equals(kind, that.kind) && - Objects.equals(optArg, that.optArg); - } else { - return false; - } - } - - @Override - public int hashCode() { - return Objects.hashCode(kind) * 31 + Objects.hashCode(optArg); - } - } - } - - private static final Lookup IMPL_LOOKUP; - - static { - try { - Field f = Lookup.class.getDeclaredField("IMPL_LOOKUP"); - f.setAccessible(true); - IMPL_LOOKUP = (Lookup)f.get(null); - } catch (ReflectiveOperationException ex) { - throw new AssertionError(ex); - } - } - - private static final ConcurrentHashMap, ValueType> BOX_TO_VT = new ConcurrentHashMap<>(); - - public static boolean classHasValueType(Class x) { - if (!MinimalValueTypes_1_0.isValueCapable(x)) { - return false; - } - return MinimalValueTypes_1_0.getValueTypeClass(x) != null; - } - - @SuppressWarnings("unchecked") - public static ValueType forClass(Class x) { - if (!MinimalValueTypes_1_0.isValueCapable(x)) { - throw new IllegalArgumentException("Class " + x + " not a value capable class"); - } - - ValueType vt = (ValueType) BOX_TO_VT.get(x); - if (vt != null) { - return vt; - } - - Class valueClass = (Class) MinimalValueTypes_1_0.getValueTypeClass(x); - vt = new ValueType(x, valueClass); - ValueType old = (ValueType) BOX_TO_VT.putIfAbsent(x, vt); - if (old != null) { - vt = old; - } - return vt; - } - - public static ValueType make(Lookup lookup, String name, String[] fieldNames, Class... fieldTypes) throws ReflectiveOperationException { - if (fieldNames.length != fieldTypes.length) { - throw new IllegalArgumentException("Field names length and field types length must match"); - } - if (!(fieldNames.length > 0)) { - throw new IllegalArgumentException("Field length must be greater than zero"); - } - IsolatedMethodBuilder builder = new IsolatedMethodBuilder(name, lookup); - builder.withMajorVersion(53) - .withMinorVersion(0) - .withSuperclass(Object.class) - .withFlags(Flag.ACC_FINAL) - .withAnnotation(Kind.RUNTIME_VISIBLE, "Ljvm/internal/value/ValueCapableClass;"); - //add fields - for (int i = 0 ; i < fieldNames.length ; i++) { - builder.withField(fieldNames[i], BytecodeDescriptor.unparse(fieldTypes[i]), F -> F.withFlags(Flag.ACC_FINAL)); - } - //add constructor - String ctype = BytecodeDescriptor.unparseMethod(void.class, fieldTypes); - builder.withMethod("", ctype, M -> M.withCode(MethodHandleCodeBuilder::new, C -> { - C.aload_0().invokespecial(Object.class, "", "()V", false); - int l = 1; - for (int i = 0 ; i < fieldNames.length ; i++) { - String fType = BytecodeDescriptor.unparse(fieldTypes[i]); - C.aload_0().load(l).putfield(builder.thisClass(), fieldNames[i], fType); - l += Wrapper.forBasicType(fieldTypes[i]).stackSlots(); - } - C.return_(); - })); - //add equals and hashCode - builder.withMethod("equals", "(Ljava/lang/Object;)Z", M -> - M.withFlags(Flag.ACC_PUBLIC).withCode(MethodHandleCodeBuilder::new, - C -> substitutabilityTestBuilder(true, builder.thisClass(), FieldInfo.stream(fieldNames, fieldTypes), C))); - builder.withMethod("hashCode", "()I", M -> - M.withFlags(Flag.ACC_PUBLIC).withCode(MethodHandleCodeBuilder::new, - C -> substitutabilityHashCodeBuilder(builder.thisClass(), FieldInfo.stream(fieldNames, fieldTypes), C))); - byte[] barr = builder.build(); - MinimalValueTypes_1_0.maybeDump(name, barr); - @SuppressWarnings("unchecked") - Class vtClass = (Class)lookup.defineClass(barr); - return forClass(vtClass); - } - - private Lookup boxLookup; - private Lookup valueLookup; - private Map handleMap = new ConcurrentHashMap<>(); - - private ValueType(Class boxClass, Class valueClass) { - this.boxLookup = IMPL_LOOKUP.in(boxClass); - this.valueLookup = IMPL_LOOKUP.in(valueClass); - } - - @SuppressWarnings("unchecked") - public Class boxClass() { - return (Class)boxLookup.lookupClass(); - } - - public Class sourceClass() { - return boxClass(); - } - - public Class valueClass() { - return valueLookup.lookupClass(); - } - - public Class arrayValueClass() { - return arrayValueClass(1); - } - - public Class arrayValueClass(int dims) { - String dimsStr = "[[[[[[[[[[[[[[[["; - if (dims < 1 || dims > 16) { - throw new IllegalArgumentException("cannot create array class for dimension > 16"); - } - String cn = dimsStr.substring(0, dims) + "Q" + valueClass().getName() + ";"; - return MinimalValueTypes_1_0.loadValueTypeClass(boxLookup.lookupClass(), cn); - } - - public String toString() { - return "ValueType boxClass=" + boxClass() + " valueClass=" + valueClass(); - } - - public MethodHandle defaultValueConstant() { - ValueHandleKey key = ValueHandleKind.DEFAULT.key(); - return getOrLoad(boxLookup, key, - () -> MethodType.methodType(valueClass()), - C -> C.vdefault(valueClass()).vreturn()); - } - - public MethodHandle substitutabilityTest() { - ValueHandleKey key = ValueHandleKind.EQ.key(); - return getOrLoad(valueLookup, key, - () -> MethodType.methodType(boolean.class, valueClass(), valueClass()), - C -> substitutabilityTestBuilder(false, valueClass(), FieldInfo.stream(valueFields()), C)); - } - - private static > void substitutabilityTestBuilder(boolean needsInstanceCheck, Class clazz, Stream fInfos, MethodHandleCodeBuilder C) { - if (needsInstanceCheck) { - C.aload_1() - .instanceof_(clazz) - .emitCondJump(Opcode.IFEQ, CondKind.EQ, "fail") - .aload_1() - .checkcast(clazz) - .store(1); - } - fInfos.forEach(fInfo -> { - String fDesc = BytecodeDescriptor.unparse(fInfo.getType()); - if (fInfo.getType().isPrimitive()) { - //field is a primitive type - perform bytecode comparison - C.load(0).getfield(clazz, fInfo.getName(), fDesc); - C.load(1).getfield(clazz, fInfo.getName(), fDesc); - C.ifcmp(fDesc, CondKind.NE, "fail"); - } else if (MinimalValueTypes_1_0.isValueType(fInfo.getType())) { - //field is a value type - call subst handle recursively - C.load(0).getfield(clazz, fInfo.getName(), fDesc).dup().store(2); - valueHandleBuilder(fInfo.getType(), ValueHandleKind.EQ.key(), C) - .load(2) - .load(1).getfield(clazz, fInfo.getName(), fDesc) - .invokevirtual(MethodHandle.class, "invoke", - MethodType.methodType(boolean.class, fInfo.getType(), fInfo.getType()).toMethodDescriptorString(), false) - .const_(0).ifcmp(TypeTag.I, CondKind.EQ, "fail"); - } else { - //otherwise, field is a reference type, fallback to Objects.equals - C.load(0).getfield(clazz, fInfo.getName(), fDesc); - C.load(1).getfield(clazz, fInfo.getName(), fDesc); - C.invokestatic(Objects.class, "equals", "(Ljava/lang/Object;Ljava/lang/Object;)Z", false); - C.const_(0).ifcmp(TypeTag.I, CondKind.EQ, "fail"); - } - }); - C.const_(1); - C.ireturn(); - C.label("fail"); - C.const_(0); - C.ireturn(); - } - - public MethodHandle substitutabilityHashCode() { - ValueHandleKey key = ValueHandleKind.HASH.key(); - return getOrLoad(valueLookup, key, - () -> MethodType.methodType(int.class, valueClass()), - C -> substitutabilityHashCodeBuilder(valueClass(), FieldInfo.stream(valueFields()), C)); - } - - private static > void substitutabilityHashCodeBuilder(Class clazz, Stream fInfos, MethodHandleCodeBuilder C) { - C.withLocal("res", "I"); - C.const_(1).store("res"); - fInfos.forEach(fInfo -> { - String desc = BytecodeDescriptor.unparse(fInfo.getType()); - if (fInfo.getType().isPrimitive()) { - C.load(0).getfield(clazz, fInfo.getName(), desc); - C.invokestatic(Wrapper.asWrapperType(fInfo.getType()), "hashCode", "(" + desc + ")I", false); - } else if (MinimalValueTypes_1_0.isValueType(fInfo.getType())) { - //field is a value type - call subst handle recursively - C.load(0).getfield(clazz, fInfo.getName(), desc).dup().store(2); - valueHandleBuilder(fInfo.getType(), ValueHandleKind.HASH.key(), C) - .load(2) - .invokevirtual(MethodHandle.class, "invoke", - MethodType.methodType(int.class, fInfo.getType()).toMethodDescriptorString(), false); - } else { - C.load(0).getfield(clazz, fInfo.getName(), desc); - C.invokestatic(Objects.class, "hashCode", "(Ljava/lang/Object;)I", false); - } - C.load("res").const_(31).imul(); - C.iadd().store("res"); - }); - C.load("res").ireturn(); - } - - // ()Q - public MethodHandle findConstructor(Lookup lookup, MethodType type) throws NoSuchMethodException, IllegalAccessException { - return MethodHandles.filterReturnValue(lookup.findConstructor(boxClass(), type), unbox()); - } - - // (F1, ..., Fn)Q, fromDefault == true - // (Q, F1, ..., Fn)Q, fromDefault == false - public MethodHandle unreflectWithers(Lookup lookup, - boolean fromDefault, - Field... fields) throws NoSuchFieldException, IllegalAccessException { - // Allow access if the lookup class is the VCC or DVT and the lookup - // has private access - Class lc = lookup.lookupClass(); - if (!lookup.hasPrivateAccess() || (valueClass() != lc && boxClass() != lc)) { - throw new IllegalAccessException(String.format("Class %s does not have vwithfield access to fields of %s", - lc.getName(), boxClass().getName())); - } - - // Ensure fields are value component fields declared by the VCC - for (Field f : fields) { - if (!isValueField(f) || f.getDeclaringClass() != sourceClass()) { - throw new IllegalArgumentException( - String.format("Field %s is not a value component field declared in value capable class %s", f.getName(), sourceClass().getName())); - } - } - - ValueHandleKey key = ValueHandleKind.UNREFLECT_WITHERS.key(List.of(fromDefault, - FieldInfo.stream(fields).collect(Collectors.toList()))); - return getOrLoad(valueLookup, key, - () -> { - MethodType mt = MethodType.methodType( - valueClass(), - Stream.of(fields).map(Field::getType).toArray(Class[]::new)); - - if (!fromDefault) { - mt = mt.insertParameterTypes(0, valueClass()); - } - return mt; - }, - C -> { - int l = 0; - if (fromDefault) { - C.vdefault(valueClass()); - } else { - C.load(0); - l = 1; - } - - for (Field f : fields) { - String fType = BytecodeDescriptor.unparse(f.getType()); - C.load(l).vwithfield(valueClass(), f.getName(), fType); - l += Wrapper.forBasicType(f.getType()).stackSlots(); - } - C.vreturn(); - }); - } - - // (Q, T)Q - public MethodHandle findWither(Lookup lookup, String name, Class type) throws NoSuchFieldException, IllegalAccessException { - // Allow access if the lookup class is the VCC or DVT and the lookup - // has private access - Class lc = lookup.lookupClass(); - if (!lookup.hasPrivateAccess() || (valueClass() != lc && boxClass() != lc)) { - throw new IllegalAccessException(String.format("Class %s does not have vwithfield access to field %s.%s", - lc.getName(), boxClass().getName(), name)); - } - - // Check field exists on VCC - lookup.findGetter(boxClass(), name, type); - - ValueHandleKey key = ValueHandleKind.WITHER.key(new FieldInfo(name, type)); - return getOrLoad(valueLookup, key, - () -> MethodType.methodType(valueClass(), valueClass(), type), - C -> C.vload(0).load(1).vwithfield(valueClass(), name, BytecodeDescriptor.unparse(type)).vreturn()); - } - - public MethodHandle unbox() { - ValueHandleKey key = ValueHandleKind.UNBOX.key(); - return getOrLoad(boxLookup, key, - () -> MethodType.methodType(valueClass(), boxClass()), - C -> C.load(0).vunbox(valueClass()).vreturn()); - } - - public MethodHandle box() { - ValueHandleKey key = ValueHandleKind.BOX.key(); - return getOrLoad(boxLookup, key, - () -> MethodType.methodType(boxClass(), valueClass()), - C -> C.vload(0).vbox(boxClass()).areturn()); - } - - public MethodHandle newArray() { - ValueHandleKey key = ValueHandleKind.NEWARRAY.key(); - return getOrLoad(boxLookup, key, - () -> MethodType.methodType(arrayValueClass(), int.class), - C -> C.load(0).anewarray(valueClass()).areturn()); - } - - public MethodHandle arrayGetter() { - ValueHandleKey key = ValueHandleKind.VALOAD.key(); - return getOrLoad(boxLookup, key, - () -> MethodType.methodType(valueClass(), arrayValueClass(), int.class), - C -> C.load(0).load(1).vaload().vreturn()); - } - - public MethodHandle arraySetter() { - ValueHandleKey key = ValueHandleKind.VASTORE.key(); - return getOrLoad(boxLookup, key, - () -> MethodType.methodType(void.class, arrayValueClass(), int.class, valueClass()), - C -> C.load(0).load(1).load(2).vastore().return_()); - } - - public MethodHandle newMultiArray(int dims) { - Class arrayValueClass = arrayValueClass(dims); - ValueHandleKey key = ValueHandleKind.MULTINEWARRAY.key(dims); - return getOrLoad(boxLookup, key, - () -> { - Class[] params = new Class[dims]; - Arrays.fill(params, int.class); - return MethodType.methodType(arrayValueClass, params); - }, - C -> { - for (int i = 0 ; i < dims ; i++) { - C.load(i); - } - C.multianewarray(arrayValueClass, (byte)dims).areturn(); - }); - } - - public MethodHandle arrayLength() { - ValueHandleKey key = ValueHandleKind.ARRAYLENGTH.key(); - return getOrLoad(boxLookup, key, - () -> MethodType.methodType(int.class, arrayValueClass()), - C -> C.load(0).arraylength().ireturn()); - } - - public MethodHandle identity() { - ValueHandleKey key = ValueHandleKind.IDENTITY.key(); - return getOrLoad(boxLookup, key, - () -> MethodType.methodType(valueClass(), valueClass()), - C -> C.vload(0).vreturn()); - } - - public MethodHandle findGetter(Lookup lookup, String name, Class type) throws NoSuchFieldException, IllegalAccessException { - //force access-check - lookup.findGetter(boxClass(), name, type); - - ValueHandleKey key = ValueHandleKind.GETTER.key(new FieldInfo(name, type)); - String fieldType = BytecodeDescriptor.unparse(type); - return getOrLoad(boxLookup, key, - () -> MethodType.methodType(type, valueClass()), - C -> C.vload(0).getfield(valueClass(), name, fieldType).return_(fieldType)); - } - - private static > T valueHandleBuilder(Class dvt, ValueHandleKey key, MethodHandleCodeBuilder C) { - MethodType mt = key.kind.handleType(); - if (mt.parameterCount() > 0) { - throw new AssertionError("Non-nilary handle builders not supported yet"); - } - return C.vbox(MinimalValueTypes_1_0.getValueCapableClass(dvt)) - .invokevirtual(Object.class, "getClass", "()Ljava/lang/Class;", false) - .invokestatic(ValueType.class, "forClass", - MethodType.methodType(ValueType.class, Class.class).toMethodDescriptorString(), false) - .invokevirtual(ValueType.class, key.kind.handleName(), key.kind.handleType().toMethodDescriptorString(), false); - } - - private MethodHandle getOrLoad(Lookup lookup, ValueHandleKey key, Supplier typeSupplier, Consumer> codeBuilder) { - MethodHandle result = handleMap.get(key); - if (result == null) { - String handleDebugName = sourceClass().getName() + "_" + key.kind.handleName(); - result = MethodHandleBuilder.loadCode(lookup, handleDebugName, typeSupplier.get(), codeBuilder); - handleMap.put(key, result); - } - return result; - } - - boolean isValueField(Field f) { - return (f.getModifiers() & (Modifier.FINAL | Modifier.STATIC)) == Modifier.FINAL; - } - - public Field[] valueFields() { - return Stream.of(sourceClass().getDeclaredFields()) - .filter(this::isValueField) - .toArray(Field[]::new); - } - - final static class FieldInfo { - - private final String name; - private final Class type; - - FieldInfo(String name, Class type) { - this.name = name; - this.type = type; - } - - String getName() { return name; } - Class getType() { return type; } - - @Override - public boolean equals(Object o) { - if (o instanceof FieldInfo) { - FieldInfo that = (FieldInfo)o; - return Objects.equals(name, that.name) && - Objects.equals(type, that.type); - } else { - return false; - } - } - - @Override - public int hashCode() { - return Objects.hash(name, type); - } - - private static Stream stream(Field[] fields) { - return Stream.of(fields).map(f -> new FieldInfo(f.getName(), f.getType())); - } - - private static Stream stream(String[] fieldNames, Class[] fieldTypes) { - return IntStream.range(0, fieldNames.length) - .mapToObj(i -> new FieldInfo(fieldNames[i], fieldTypes[i])); - } - } -} --- /dev/null 2017-09-14 22:58:53.000000000 -0700 +++ new/jdk/src/java.base/share/classes/valhalla/shady/ValueTypeHolder.java 2017-09-14 22:58:53.000000000 -0700 @@ -0,0 +1,553 @@ +/* + * Copyright (c) 2016, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package valhalla.shady; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodHandles.Lookup; +import java.lang.invoke.MethodType; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Consumer; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import jdk.experimental.bytecode.AnnotationsBuilder.Kind; +import jdk.experimental.bytecode.Flag; +import jdk.experimental.bytecode.Opcode; +import jdk.experimental.value.MethodHandleBuilder.IsolatedMethodBuilder; +import jdk.experimental.value.MethodHandleBuilder.MethodHandleCodeBuilder; +import jdk.experimental.value.MethodHandleBuilder; +import jdk.experimental.bytecode.MacroCodeBuilder.CondKind; +import jdk.experimental.bytecode.TypeTag; +import sun.invoke.util.BytecodeDescriptor; +import sun.invoke.util.Wrapper; +import valhalla.shady.ValueTypeHolder.ValueHandleKind.ValueHandleKey; + +// Rough place holder just now... +public class ValueTypeHolder { + + enum ValueHandleKind { + BOX("box"), + UNBOX("unbox"), + DEFAULT("defaultValueConstant"), + EQ("substitutabilityTest"), + HASH("substitutabilityHashCode"), + ARRAYLENGTH("arrayLength"), + WITHER("findWither", Lookup.class, String.class, Class.class) { + @Override + ValueHandleKey key(Object fieldName) { + return new ValueHandleKey(this, fieldName); + } + }, + UNREFLECT_WITHERS("unreflectWithers", Lookup.class, boolean.class, Field[].class) { + @Override + ValueHandleKey key(Object fields) { + return new ValueHandleKey(this, fields); + } + }, + NEWARRAY("newArray"), + VALOAD("arrayGetter"), + VASTORE("arraySetter"), + MULTINEWARRAY("newMultiArray", int.class) { + @Override + ValueHandleKey key(Object dims) { + return new ValueHandleKey(this, dims); + } + }, + IDENTITY("identity"), + GETTER("findGetter", Lookup.class, String.class, Class.class) { + @Override + ValueHandleKey key(Object fieldName) { + return new ValueHandleKey(this, fieldName); + } + }; + + final MethodHandle handle; + + ValueHandleKind(String handleName, Class... argtypes) { + try { + this.handle = MethodHandles.lookup().findVirtual(ValueTypeHolder.class, handleName, MethodType.methodType(MethodHandle.class, argtypes)); + } catch (ReflectiveOperationException ex) { + throw new IllegalArgumentException("Cannot initialize value handle key for: " + handleName); + } + } + + String handleName() { + return MethodHandles.lookup().revealDirect(handle).getName(); + } + + MethodType handleType() { + return MethodHandles.lookup().revealDirect(handle).getMethodType(); + } + + ValueHandleKey key() { + return new ValueHandleKey(this, null); + } + + ValueHandleKey key(Object optArg) { + throw new IllegalStateException(); + } + + static class ValueHandleKey { + ValueHandleKind kind; + Object optArg; + + ValueHandleKey(ValueHandleKind kind, Object optArg) { + this.kind = kind; + this.optArg = optArg; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof ValueHandleKey) { + ValueHandleKey that = (ValueHandleKey)obj; + return Objects.equals(kind, that.kind) && + Objects.equals(optArg, that.optArg); + } else { + return false; + } + } + + @Override + public int hashCode() { + return Objects.hashCode(kind) * 31 + Objects.hashCode(optArg); + } + } + } + + private static final Lookup IMPL_LOOKUP; + + static { + try { + Field f = Lookup.class.getDeclaredField("IMPL_LOOKUP"); + f.setAccessible(true); + IMPL_LOOKUP = (Lookup)f.get(null); + } catch (ReflectiveOperationException ex) { + throw new AssertionError(ex); + } + } + + public static Class makeValueTypeClass(Lookup lookup, String name, String[] fieldNames, Class... fieldTypes) throws ReflectiveOperationException { + if (fieldNames.length != fieldTypes.length) { + throw new IllegalArgumentException("Field names length and field types length must match"); + } + if (!(fieldNames.length > 0)) { + throw new IllegalArgumentException("Field length must be greater than zero"); + } + IsolatedMethodBuilder builder = new IsolatedMethodBuilder(name, lookup); + builder.withMajorVersion(53) + .withMinorVersion(0) + .withSuperclass(Object.class) + .withFlags(Flag.ACC_FINAL) + .withAnnotation(Kind.RUNTIME_VISIBLE, MinimalValueTypes_1_0.DERIVE_VALUE_TYPE_DESC); + //add fields + for (int i = 0 ; i < fieldNames.length ; i++) { + builder.withField(fieldNames[i], BytecodeDescriptor.unparse(fieldTypes[i]), F -> F.withFlags(Flag.ACC_FINAL)); + } + //add constructor + String ctype = BytecodeDescriptor.unparseMethod(void.class, fieldTypes); + builder.withMethod("", ctype, M -> M.withCode(MethodHandleCodeBuilder::new, C -> { + C.aload_0().invokespecial(Object.class, "", "()V", false); + int l = 1; + for (int i = 0 ; i < fieldNames.length ; i++) { + String fType = BytecodeDescriptor.unparse(fieldTypes[i]); + C.aload_0().load(l).putfield(builder.thisClass(), fieldNames[i], fType); + l += Wrapper.forBasicType(fieldTypes[i]).stackSlots(); + } + C.return_(); + })); + //add equals and hashCode + builder.withMethod("equals", "(Ljava/lang/Object;)Z", M -> + M.withFlags(Flag.ACC_PUBLIC).withCode(MethodHandleCodeBuilder::new, + C -> substitutabilityTestBuilder(true, builder.thisClass(), FieldInfo.stream(fieldNames, fieldTypes), C))); + builder.withMethod("hashCode", "()I", M -> + M.withFlags(Flag.ACC_PUBLIC).withCode(MethodHandleCodeBuilder::new, + C -> substitutabilityHashCodeBuilder(builder.thisClass(), FieldInfo.stream(fieldNames, fieldTypes), C))); + byte[] barr = builder.build(); + MinimalValueTypes_1_0.maybeDump(name, barr); + @SuppressWarnings("unchecked") + Class vtClass = (Class)lookup.defineClass(barr); + return vtClass; + } + + private Lookup boxLookup; + private Lookup valueLookup; + private Map handleMap = new ConcurrentHashMap<>(); + + ValueTypeHolder(Class boxClass, Class valueClass) { + this.boxLookup = IMPL_LOOKUP.in(boxClass); + this.valueLookup = IMPL_LOOKUP.in(valueClass); + } + + @SuppressWarnings("unchecked") + public Class boxClass() { + return (Class)boxLookup.lookupClass(); + } + + public Class sourceClass() { + return boxClass(); + } + + public Class valueClass() { + return valueLookup.lookupClass(); + } + + public Class arrayValueClass() { + return arrayValueClass(1); + } + + public Class arrayValueClass(int dims) { + String dimsStr = "[[[[[[[[[[[[[[[["; + if (dims < 1 || dims > 16) { + throw new IllegalArgumentException("cannot create array class for dimension > 16"); + } + String cn = dimsStr.substring(0, dims) + "Q" + valueClass().getName() + ";"; + return MinimalValueTypes_1_0.loadValueTypeClass(boxLookup.lookupClass(), cn); + } + + public String toString() { + return "ValueType boxClass=" + boxClass() + " valueClass=" + valueClass(); + } + + public MethodHandle defaultValueConstant() { + ValueHandleKey key = ValueHandleKind.DEFAULT.key(); + return getOrLoad(boxLookup, key, + () -> MethodType.methodType(valueClass()), + C -> C.vdefault(valueClass()).vreturn()); + } + + public MethodHandle substitutabilityTest() { + ValueHandleKey key = ValueHandleKind.EQ.key(); + return getOrLoad(valueLookup, key, + () -> MethodType.methodType(boolean.class, valueClass(), valueClass()), + C -> substitutabilityTestBuilder(false, valueClass(), FieldInfo.stream(valueFields()), C)); + } + + private static > void substitutabilityTestBuilder(boolean needsInstanceCheck, Class clazz, Stream fInfos, MethodHandleCodeBuilder C) { + if (needsInstanceCheck) { + C.aload_1() + .instanceof_(clazz) + .emitCondJump(Opcode.IFEQ, CondKind.EQ, "fail") + .aload_1() + .checkcast(clazz) + .store(1); + } + fInfos.forEach(fInfo -> { + String fDesc = BytecodeDescriptor.unparse(fInfo.getType()); + if (fInfo.getType().isPrimitive()) { + //field is a primitive type - perform bytecode comparison + C.load(0).getfield(clazz, fInfo.getName(), fDesc); + C.load(1).getfield(clazz, fInfo.getName(), fDesc); + C.ifcmp(fDesc, CondKind.NE, "fail"); + } else if (MinimalValueTypes_1_0.isValueType(fInfo.getType())) { + //field is a value type - call subst handle recursively + C.load(0).getfield(clazz, fInfo.getName(), fDesc).dup().store(2); + valueHandleBuilder(fInfo.getType(), ValueHandleKind.EQ.key(), C) + .load(2) + .load(1).getfield(clazz, fInfo.getName(), fDesc) + .invokevirtual(MethodHandle.class, "invoke", + MethodType.methodType(boolean.class, fInfo.getType(), fInfo.getType()).toMethodDescriptorString(), false) + .const_(0).ifcmp(TypeTag.I, CondKind.EQ, "fail"); + } else { + //otherwise, field is a reference type, fallback to Objects.equals + C.load(0).getfield(clazz, fInfo.getName(), fDesc); + C.load(1).getfield(clazz, fInfo.getName(), fDesc); + C.invokestatic(Objects.class, "equals", "(Ljava/lang/Object;Ljava/lang/Object;)Z", false); + C.const_(0).ifcmp(TypeTag.I, CondKind.EQ, "fail"); + } + }); + C.const_(1); + C.ireturn(); + C.label("fail"); + C.const_(0); + C.ireturn(); + } + + public MethodHandle substitutabilityHashCode() { + ValueHandleKey key = ValueHandleKind.HASH.key(); + return getOrLoad(valueLookup, key, + () -> MethodType.methodType(int.class, valueClass()), + C -> substitutabilityHashCodeBuilder(valueClass(), FieldInfo.stream(valueFields()), C)); + } + + private static > void substitutabilityHashCodeBuilder(Class clazz, Stream fInfos, MethodHandleCodeBuilder C) { + C.withLocal("res", "I"); + C.const_(1).store("res"); + fInfos.forEach(fInfo -> { + String desc = BytecodeDescriptor.unparse(fInfo.getType()); + if (fInfo.getType().isPrimitive()) { + C.load(0).getfield(clazz, fInfo.getName(), desc); + C.invokestatic(Wrapper.asWrapperType(fInfo.getType()), "hashCode", "(" + desc + ")I", false); + } else if (MinimalValueTypes_1_0.isValueType(fInfo.getType())) { + //field is a value type - call subst handle recursively + C.load(0).getfield(clazz, fInfo.getName(), desc).dup().store(2); + valueHandleBuilder(fInfo.getType(), ValueHandleKind.HASH.key(), C) + .load(2) + .invokevirtual(MethodHandle.class, "invoke", + MethodType.methodType(int.class, fInfo.getType()).toMethodDescriptorString(), false); + } else { + C.load(0).getfield(clazz, fInfo.getName(), desc); + C.invokestatic(Objects.class, "hashCode", "(Ljava/lang/Object;)I", false); + } + C.load("res").const_(31).imul(); + C.iadd().store("res"); + }); + C.load("res").ireturn(); + } + + // ()Q + public MethodHandle findConstructor(Lookup lookup, MethodType type) throws NoSuchMethodException, IllegalAccessException { + return MethodHandles.filterReturnValue(lookup.findConstructor(boxClass(), type), unbox()); + } + + // (F1, ..., Fn)Q, fromDefault == true + // (Q, F1, ..., Fn)Q, fromDefault == false + public MethodHandle unreflectWithers(Lookup lookup, + boolean fromDefault, + Field... fields) throws NoSuchFieldException, IllegalAccessException { + // Allow access if the lookup class is the VCC or DVT and the lookup + // has private access + Class lc = lookup.lookupClass(); + if (!lookup.hasPrivateAccess() || (valueClass() != lc && boxClass() != lc)) { + throw new IllegalAccessException(String.format("Class %s does not have vwithfield access to fields of %s", + lc.getName(), boxClass().getName())); + } + + // Ensure fields are value component fields declared by the VCC + for (Field f : fields) { + if (!isValueField(f) || f.getDeclaringClass() != sourceClass()) { + throw new IllegalArgumentException( + String.format("Field %s is not a value component field declared in value capable class %s", f.getName(), sourceClass().getName())); + } + } + + ValueHandleKey key = ValueHandleKind.UNREFLECT_WITHERS.key(List.of(fromDefault, + FieldInfo.stream(fields).collect(Collectors.toList()))); + return getOrLoad(valueLookup, key, + () -> { + MethodType mt = MethodType.methodType( + valueClass(), + Stream.of(fields).map(Field::getType).toArray(Class[]::new)); + + if (!fromDefault) { + mt = mt.insertParameterTypes(0, valueClass()); + } + return mt; + }, + C -> { + int l = 0; + if (fromDefault) { + C.vdefault(valueClass()); + } else { + C.load(0); + l = 1; + } + + for (Field f : fields) { + String fType = BytecodeDescriptor.unparse(f.getType()); + C.load(l).vwithfield(valueClass(), f.getName(), fType); + l += Wrapper.forBasicType(f.getType()).stackSlots(); + } + C.vreturn(); + }); + } + + // (Q, T)Q + public MethodHandle findWither(Lookup lookup, String name, Class type) throws NoSuchFieldException, IllegalAccessException { + // Allow access if the lookup class is the VCC or DVT and the lookup + // has private access + Class lc = lookup.lookupClass(); + if (!lookup.hasPrivateAccess() || (valueClass() != lc && boxClass() != lc)) { + throw new IllegalAccessException(String.format("Class %s does not have vwithfield access to field %s.%s", + lc.getName(), boxClass().getName(), name)); + } + + // Check field exists on VCC + lookup.findGetter(boxClass(), name, type); + + ValueHandleKey key = ValueHandleKind.WITHER.key(new FieldInfo(name, type)); + return getOrLoad(valueLookup, key, + () -> MethodType.methodType(valueClass(), valueClass(), type), + C -> C.vload(0).load(1).vwithfield(valueClass(), name, BytecodeDescriptor.unparse(type)).vreturn()); + } + + public MethodHandle unbox() { + ValueHandleKey key = ValueHandleKind.UNBOX.key(); + return getOrLoad(boxLookup, key, + () -> MethodType.methodType(valueClass(), boxClass()), + C -> C.load(0).vunbox(valueClass()).vreturn()); + } + + public MethodHandle box() { + ValueHandleKey key = ValueHandleKind.BOX.key(); + return getOrLoad(boxLookup, key, + () -> MethodType.methodType(boxClass(), valueClass()), + C -> C.vload(0).vbox(boxClass()).areturn()); + } + + public MethodHandle newArray() { + ValueHandleKey key = ValueHandleKind.NEWARRAY.key(); + return getOrLoad(boxLookup, key, + () -> MethodType.methodType(arrayValueClass(), int.class), + C -> C.load(0).anewarray(valueClass()).areturn()); + } + + public MethodHandle arrayGetter() { + ValueHandleKey key = ValueHandleKind.VALOAD.key(); + return getOrLoad(boxLookup, key, + () -> MethodType.methodType(valueClass(), arrayValueClass(), int.class), + C -> C.load(0).load(1).vaload().vreturn()); + } + + public MethodHandle arraySetter() { + ValueHandleKey key = ValueHandleKind.VASTORE.key(); + return getOrLoad(boxLookup, key, + () -> MethodType.methodType(void.class, arrayValueClass(), int.class, valueClass()), + C -> C.load(0).load(1).load(2).vastore().return_()); + } + + public MethodHandle newMultiArray(int dims) { + Class arrayValueClass = arrayValueClass(dims); + ValueHandleKey key = ValueHandleKind.MULTINEWARRAY.key(dims); + return getOrLoad(boxLookup, key, + () -> { + Class[] params = new Class[dims]; + Arrays.fill(params, int.class); + return MethodType.methodType(arrayValueClass, params); + }, + C -> { + for (int i = 0 ; i < dims ; i++) { + C.load(i); + } + C.multianewarray(arrayValueClass, (byte)dims).areturn(); + }); + } + + public MethodHandle arrayLength() { + ValueHandleKey key = ValueHandleKind.ARRAYLENGTH.key(); + return getOrLoad(boxLookup, key, + () -> MethodType.methodType(int.class, arrayValueClass()), + C -> C.load(0).arraylength().ireturn()); + } + + public MethodHandle identity() { + ValueHandleKey key = ValueHandleKind.IDENTITY.key(); + return getOrLoad(boxLookup, key, + () -> MethodType.methodType(valueClass(), valueClass()), + C -> C.vload(0).vreturn()); + } + + public MethodHandle findGetter(Lookup lookup, String name, Class type) throws NoSuchFieldException, IllegalAccessException { + //force access-check + lookup.findGetter(boxClass(), name, type); + + ValueHandleKey key = ValueHandleKind.GETTER.key(new FieldInfo(name, type)); + String fieldType = BytecodeDescriptor.unparse(type); + return getOrLoad(boxLookup, key, + () -> MethodType.methodType(type, valueClass()), + C -> C.vload(0).getfield(valueClass(), name, fieldType).return_(fieldType)); + } + + private static > T valueHandleBuilder(Class dvt, ValueHandleKey key, MethodHandleCodeBuilder C) { + MethodType mt = key.kind.handleType(); + if (mt.parameterCount() > 0) { + throw new AssertionError("Non-nilary handle builders not supported yet"); + } + Class vtSupportClass = MinimalValueTypes_1_0.getIncubatorValueTypeClass(); + return C.vbox(MinimalValueTypes_1_0.getValueCapableClass(dvt)) + .invokevirtual(Object.class, "getClass", "()Ljava/lang/Class;", false) + .invokestatic(vtSupportClass, "forClass", + MethodType.methodType(vtSupportClass, Class.class).toMethodDescriptorString(), false) + .invokevirtual(vtSupportClass, key.kind.handleName(), key.kind.handleType().toMethodDescriptorString(), false); + } + + private MethodHandle getOrLoad(Lookup lookup, ValueHandleKey key, Supplier typeSupplier, Consumer> codeBuilder) { + MethodHandle result = handleMap.get(key); + if (result == null) { + String handleDebugName = sourceClass().getName() + "_" + key.kind.handleName(); + result = MethodHandleBuilder.loadCode(lookup, handleDebugName, typeSupplier.get(), codeBuilder); + handleMap.put(key, result); + } + return result; + } + + boolean isValueField(Field f) { + return (f.getModifiers() & (Modifier.FINAL | Modifier.STATIC)) == Modifier.FINAL; + } + + public Field[] valueFields() { + return Stream.of(sourceClass().getDeclaredFields()) + .filter(this::isValueField) + .toArray(Field[]::new); + } + + final static class FieldInfo { + + private final String name; + private final Class type; + + FieldInfo(String name, Class type) { + this.name = name; + this.type = type; + } + + String getName() { return name; } + Class getType() { return type; } + + @Override + public boolean equals(Object o) { + if (o instanceof FieldInfo) { + FieldInfo that = (FieldInfo)o; + return Objects.equals(name, that.name) && + Objects.equals(type, that.type); + } else { + return false; + } + } + + @Override + public int hashCode() { + return Objects.hash(name, type); + } + + private static Stream stream(Field[] fields) { + return Stream.of(fields).map(f -> new FieldInfo(f.getName(), f.getType())); + } + + private static Stream stream(String[] fieldNames, Class[] fieldTypes) { + return IntStream.range(0, fieldNames.length) + .mapToObj(i -> new FieldInfo(fieldNames[i], fieldTypes[i])); + } + } +} --- old/jdk/src/java.base/share/classes/jvm/internal/value/ValueCapableClass.java 2017-09-14 22:58:54.000000000 -0700 +++ /dev/null 2017-09-14 22:58:54.000000000 -0700 @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2016, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -package jvm.internal.value; - -import java.lang.annotation.*; - -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) -public @interface ValueCapableClass { -} --- /dev/null 2017-09-14 22:58:54.000000000 -0700 +++ new/jdk/src/jdk.incubator.mvt/share/classes/jdk/incubator/mvt/ValueCapableClass.java 2017-09-14 22:58:54.000000000 -0700 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2016, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package jdk.incubator.mvt; + +import java.lang.annotation.*; + +/** + * A class annotated {@code @ValueCapableClass} is a value-capable class. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +public @interface ValueCapableClass { +} --- /dev/null 2017-09-14 22:58:55.000000000 -0700 +++ new/jdk/src/jdk.incubator.mvt/share/classes/jdk/incubator/mvt/ValueType.java 2017-09-14 22:58:55.000000000 -0700 @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2017, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package jdk.incubator.mvt; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles.Lookup; +import java.lang.invoke.MethodType; +import java.lang.reflect.Field; + +import valhalla.shady.MinimalValueTypes_1_0; +import valhalla.shady.ValueTypeHolder; + +/** + * Value type reflection support. + */ +public class ValueType { + /** + * Returns a {@code ValueType} object representing the specified + * value-capable class. + * + * @param vcc Value-capable class + * @param Value type + * @return a {@code ValueType} object representing the specified + * value-capable class. + * + * @throws IllegalArgumentException if the specified {@code vcc} + * is not a value-capable class. + */ + public static ValueType forClass(Class vcc) { + return new ValueType<>(MinimalValueTypes_1_0.getValueFor(vcc)); + } + + /** + * Returns {@code true} if the specified class is value-capable class. + * + * @param c a Class + * @return true if the specified class is a value-capable class. + */ + public static boolean classHasValueType(Class c) { + if (!MinimalValueTypes_1_0.isValueCapable(c)) { + return false; + } + return MinimalValueTypes_1_0.getValueTypeClass(c) != null; + } + + private final ValueTypeHolder valueTypeHolder; + private ValueType(ValueTypeHolder vt) { + this.valueTypeHolder = vt; + } + + /** + * Returns the value-capable class of this value type. + * + * @return the value-capable class of this value type. + */ + public Class boxClass() { + return valueTypeHolder.boxClass(); + } + + /** + * Returns the derived value type of this value type. + * + * @return the derived value type of this value type. + */ + public Class valueClass() { + return valueTypeHolder.valueClass(); + } + + /** + * Returns an array class of this value type. + * + * @return an array class of this value type. + */ + public Class arrayValueClass() { + return arrayValueClass(1); + } + + /** + * Returns an array class of the specified dimension for this value type. + * + * @return an array class of the specified dimension for this value type. + */ + public Class arrayValueClass(int dims) { + String dimsStr = "[[[[[[[[[[[[[[[["; + if (dims < 1 || dims > 16) { + throw new IllegalArgumentException("cannot create array class for dimension > 16"); + } + String cn = dimsStr.substring(0, dims) + "Q" + valueClass().getName() + ";"; + return MinimalValueTypes_1_0.loadValueTypeClass(boxClass(), cn); + } + + /** + * Returns a string representation of this value type. + * + * @return a string representation of this value type. + */ + public String toString() { + return valueTypeHolder.toString(); + } + + public static ValueType make(Lookup lookup, + String name, + String[] fieldNames, + Class... fieldTypes) + throws ReflectiveOperationException + { + if (fieldNames.length != fieldTypes.length) { + throw new IllegalArgumentException("Field names length and field types length must match"); + } + if (!(fieldNames.length > 0)) { + throw new IllegalArgumentException("Field length must be greater than zero"); + } + Class vtClass = ValueTypeHolder.makeValueTypeClass(lookup, name, fieldNames, fieldTypes); + return forClass(vtClass); + } + + // ()Q + public MethodHandle findConstructor(Lookup lookup, MethodType type) + throws NoSuchMethodException, IllegalAccessException { + return valueTypeHolder.findConstructor(lookup, type); + } + + // (F1, ..., Fn)Q, fromDefault == true + // (Q, F1, ..., Fn)Q, fromDefault == false + public MethodHandle unreflectWithers(Lookup lookup, + boolean fromDefault, + Field... fields) + throws NoSuchFieldException, IllegalAccessException { + return valueTypeHolder.unreflectWithers(lookup, fromDefault, fields); + } + + // (Q, T)Q + public MethodHandle findWither(Lookup lookup, String name, Class type) + throws NoSuchFieldException, IllegalAccessException { + return valueTypeHolder.findWither(lookup, name, type); + } + + public MethodHandle unbox() { + return valueTypeHolder.unbox(); + } + + public MethodHandle box() { + return valueTypeHolder.box(); + } + + public MethodHandle newArray() { + return valueTypeHolder.newArray(); + } + + public MethodHandle arrayGetter() { + return valueTypeHolder.arrayGetter(); + } + + public MethodHandle arraySetter() { + return valueTypeHolder.arraySetter(); + } + + public MethodHandle newMultiArray(int dims) { + return valueTypeHolder.newMultiArray(dims); + } + + public MethodHandle arrayLength() { + return valueTypeHolder.arrayLength(); + } + + public MethodHandle identity() { + return valueTypeHolder.identity(); + } + + public MethodHandle findGetter(Lookup lookup, String name, Class type) + throws NoSuchFieldException, IllegalAccessException { + return valueTypeHolder.findGetter(lookup, name, type); + } + + public MethodHandle substitutabilityTest() { + return valueTypeHolder.substitutabilityTest(); + } + + public MethodHandle substitutabilityHashCode() { + return valueTypeHolder.substitutabilityHashCode(); + } + + public MethodHandle defaultValueConstant() { + return valueTypeHolder.defaultValueConstant(); + } + + public Field[] valueFields() { + return valueTypeHolder.valueFields(); + } +} --- /dev/null 2017-09-14 22:58:56.000000000 -0700 +++ new/jdk/src/jdk.incubator.mvt/share/classes/jdk/incubator/mvt/package-info.java 2017-09-14 22:58:55.000000000 -0700 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +/** + * {@Incubating} + * + *

Minimal Value Type Incubating API. + * + * @since 10 + */ +package jdk.incubator.mvt; --- /dev/null 2017-09-14 22:58:56.000000000 -0700 +++ new/jdk/src/jdk.incubator.mvt/share/classes/module-info.java 2017-09-14 22:58:56.000000000 -0700 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +/** + * Defines the experimental API for Minimal Value Type. + * + * {@Incubating} + * + * @moduleGraph + * @since 10 + */ +module jdk.incubator.mvt { + exports jdk.incubator.mvt; +} --- /dev/null 2017-09-14 22:58:57.000000000 -0700 +++ new/jdk/test/valhalla/mvt/TEST.properties 2017-09-14 22:58:57.000000000 -0700 @@ -0,0 +1 @@ +modules = jdk.incubator.mvt