--- old/jdk/src/java.base/share/classes/valhalla/shady/MinimalValueTypes_1_0.java 2017-09-15 12:05:28.000000000 -0700 +++ new/jdk/src/java.base/share/classes/valhalla/shady/MinimalValueTypes_1_0.java 2017-09-15 12:05:28.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,68 @@ } /* - * 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; + } + + /* + * Returns jdk.incubator.mvt.ValueCapableClass annotation class + */ + static Class loadValueCapableAnnotation() { + Module module = ModuleLayer.boot().findModule("jdk.incubator.mvt") + .orElse(null); + if (module == null) + return null; + + @SuppressWarnings("unchecked") + Class c = (Class) + Class.forName(module, "jdk.incubator.mvt.ValueCapableClass"); + return c; + } + + /* + * Returns jdk.incubator.mvt.ValueType class + */ + static Class incubatorValueTypeClass() { + Class c = valueTypeClass; + if (c == null) { + Module module = ModuleLayer.boot().findModule("jdk.incubator.mvt") + .orElse(null); + if (module != null) { + valueTypeClass = c = + Class.forName(module, "jdk.incubator.mvt.ValueType"); + } + } + return valueTypeClass; + } + } + + /* + * Returns jdk.incubator.mvt.ValueType class from jdk.incubator.mvt module + */ + static Class getIncubatorValueTypeClass() { + if (!isValueTypeEnabled()) { + throw new UnsupportedOperationException("MVT is not enabled"); + } + return ValueClassHelper.incubatorValueTypeClass(); } }