< prev index next >

jdk/src/java.base/share/classes/valhalla/shady/MinimalValueTypes_1_0.java

Print this page

        

@@ -27,19 +27,21 @@
 import jdk.experimental.bytecode.BasicClassBuilder;
 import jdk.internal.misc.Unsafe;
 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;
 import java.io.OutputStream;
 import java.nio.file.Files;
 import java.nio.file.Path;
 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.*;
 
 import jdk.internal.misc.JavaLangAccess;
 import jdk.internal.misc.SharedSecrets;

@@ -48,11 +50,11 @@
     public static final int V53_1 = 1 << 16 | 53;
     public static final int ACC_VALUE = ACC_NATIVE;
     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;
 
     public static final boolean DUMP_CLASS_FILES;
     private static final boolean VALUE_TYPE_ENABLED;

@@ -68,32 +70,80 @@
             props.getProperty("valhalla.enableValueType"));
 
         JLA = SharedSecrets.getJavaLangAccess();
     }
 
-    public static boolean isValueTypeEnabled() {
-        return VALUE_TYPE_ENABLED;
+    private static final ConcurrentHashMap<Class<?>, ValueTypeHolder<?>> BOX_TO_VT
+        = new ConcurrentHashMap<>();
+
+    /**
+     * 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 <T> ValueTypeHolder<T> getValueFor(Class<T> vcc) {
+        if (!MinimalValueTypes_1_0.isValueTypeEnabled()) {
+            throw new UnsupportedOperationException("MVT is not enabled");
     }
 
-    public static String getValueTypeClassName(ValueTypeDesc valueTypeDesc) {
-        return getValueTypeClassName(valueTypeDesc.getName());
+        if (!MinimalValueTypes_1_0.isValueCapable(vcc)) {
+            throw new IllegalArgumentException("Class " + vcc + " not a value capable class");
     }
 
-    public static String getValueTypeClassName(String vccName) {
-        return vccName + DERIVE_VT_CLASSNAME_POSTFIX;
+        ValueTypeHolder<T> vt = (ValueTypeHolder<T>) BOX_TO_VT.get(vcc);
+        if (vt != null) {
+            return vt;
     }
 
-    public static String getValueCapableClassName(String valName) {
-        return valName.substring(0, valName.length() - DERIVE_VT_CLASSNAME_POSTFIX.length());
+        Class<T> valueClass = (Class<T>) MinimalValueTypes_1_0.getValueTypeClass(vcc);
+        vt = new ValueTypeHolder<T>(vcc, valueClass);
+        ValueTypeHolder<T> old = (ValueTypeHolder<T>) BOX_TO_VT.putIfAbsent(vcc, vt);
+        if (old != null) {
+            vt = old;
+        }
+        return vt;
+    }
+
+    /**
+     * Returns the {@code ValueTypeHolder} representing the value type
+     * for the given class is a derived value type; otherwise {@code null}.
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> ValueTypeHolder<T> findValueType(Class<T> c) {
+        if (MinimalValueTypes_1_0.isValueType(c)) {
+            return (ValueTypeHolder<T>) getValueFor(MinimalValueTypes_1_0.getValueCapableClass(c));
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * 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) {
         if (!isValueType(dvt)) {
             throw new IllegalArgumentException(dvt + " is not a derived value type");

@@ -200,22 +250,90 @@
     }
 
     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) {
         return ";Q" + name + ";";
     }
 
     /*
-     * 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<? extends Annotation> annotationClass;
+        static volatile Class<?> valueTypeClass;
+
+        static boolean hasValueCapableAnnotation(Class<?> c) {
+            if (!VM.isModuleSystemInited()) {
+                return false;
+            }
+            Class<? extends Annotation> annClass = annotationClass;
+            if (annClass == null) {
+                annotationClass = annClass = loadValueCapableAnnotation();
+            }
+            return annClass != null &&
+                    c.getDeclaredAnnotation(annClass) != null;
+        }
+
+        /*
+         * Returns jdk.incubator.mvt.ValueCapableClass annotation class
+         */
+        static Class<? extends Annotation> loadValueCapableAnnotation() {
+            Module module = ModuleLayer.boot().findModule("jdk.incubator.mvt")
+                                       .orElse(null);
+            if (module == null)
+                return null;
+
+            @SuppressWarnings("unchecked")
+            Class<? extends Annotation> c = (Class<? extends Annotation>)
+                    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();
     }
 }
< prev index next >