< prev index next >

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

Print this page




  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package valhalla.shady;
  26 
  27 import jdk.experimental.bytecode.BasicClassBuilder;
  28 import jdk.internal.misc.Unsafe;
  29 import jdk.internal.misc.VM;
  30 import sun.security.action.GetPropertyAction;
  31 

  32 import java.io.BufferedOutputStream;
  33 import java.io.File;
  34 import java.io.IOException;
  35 import java.io.OutputStream;
  36 import java.nio.file.Files;
  37 import java.nio.file.Path;
  38 import java.nio.file.Paths;
  39 import java.security.ProtectionDomain;
  40 import java.util.Properties;

  41 
  42 import static jdk.internal.org.objectweb.asm.Opcodes.*;
  43 
  44 import jdk.internal.misc.JavaLangAccess;
  45 import jdk.internal.misc.SharedSecrets;
  46 public class MinimalValueTypes_1_0 {
  47 
  48     public static final int V53_1 = 1 << 16 | 53;
  49     public static final int ACC_VALUE = ACC_NATIVE;
  50     public static final String OBJECT_CLASS_DESC = "java/lang/Object";
  51     public static final String VALUE_CLASS_DESC = "java/lang/__Value";
  52 
  53     public static final String DERIVE_VALUE_TYPE_DESC = "Ljvm/internal/value/ValueCapableClass;";
  54     public static final String DERIVE_VT_CLASSNAME_POSTFIX = "$Value";
  55     public static final int    DERIVE_VT_CLASS_ACCESS = ACC_PUBLIC|ACC_SUPER|ACC_FINAL|ACC_VALUE|ACC_SYNTHETIC;
  56 
  57     public static final boolean DUMP_CLASS_FILES;
  58     private static final boolean VALUE_TYPE_ENABLED;
  59     private static final JavaLangAccess JLA;
  60 
  61     static {
  62         // Use same property as in j.l.invoke.MethodHandleStatics
  63         Properties props = GetPropertyAction.privilegedGetProperties();
  64         DUMP_CLASS_FILES = Boolean.parseBoolean(
  65             props.getProperty("java.lang.invoke.MethodHandle.DUMP_CLASS_FILES"));
  66 
  67         VALUE_TYPE_ENABLED = Boolean.parseBoolean(
  68             props.getProperty("valhalla.enableValueType"));
  69 
  70         JLA = SharedSecrets.getJavaLangAccess();
  71     }
  72 
  73     public static boolean isValueTypeEnabled() {
  74         return VALUE_TYPE_ENABLED;












  75     }
  76 
  77     public static String getValueTypeClassName(ValueTypeDesc valueTypeDesc) {
  78         return getValueTypeClassName(valueTypeDesc.getName());
  79     }
  80 
  81     public static String getValueTypeClassName(String vccName) {
  82         return vccName + DERIVE_VT_CLASSNAME_POSTFIX;

  83     }
  84 
  85     public static String getValueCapableClassName(String valName) {
  86         return valName.substring(0, valName.length() - DERIVE_VT_CLASSNAME_POSTFIX.length());



























  87     }
  88 
  89     public static boolean isValueType(Class<?> dvt) {
  90         return (dvt.getModifiers() & ACC_VALUE) != 0;
  91     }
  92 




  93     public static boolean isValueCapable(Class<?> vcc) {
  94         return vcc.getDeclaredAnnotation(jvm.internal.value.ValueCapableClass.class) != null;




  95     }
  96 
  97     public static Class<?> getValueCapableClass(Class<?> dvt) {
  98         if (!isValueType(dvt)) {
  99             throw new IllegalArgumentException(dvt + " is not a derived value type");
 100         }
 101 
 102         Class<?> c = Class.forName(dvt.getModule(), getValueCapableClassName(dvt.getName()));
 103         if (c == null || !isValueCapable(c)) {
 104             throw new InternalError(dvt + " not bound to ValueType");
 105         }
 106         return c;
 107     }
 108 
 109     public static Class<?> getValueTypeClass(Class<?> vcc) {
 110         if (!isValueCapable(vcc)) {
 111             throw new IllegalArgumentException(vcc + " is not a value capable class");
 112         }
 113         return loadValueTypeClass(vcc, getValueTypeClassName(vcc.getName()));
 114     }


 185                         if (!root.exists() && !root.mkdirs()) {
 186                             throw new IllegalStateException("Could not create dump file directory: " + root);
 187                         }
 188                         System.out.println("dump: " + dumpFile);
 189                         try (OutputStream os = Files.newOutputStream(dumpFile);
 190                              BufferedOutputStream bos = new BufferedOutputStream(os)) {
 191                             bos.write(classFile);
 192                         } catch (IOException ex) {
 193                             throw new InternalError(ex);
 194                         }
 195                         return null;
 196                     }
 197                 });
 198 
 199         }
 200     }
 201 
 202     private final native Class<?> getDerivedValueType(Class<?> ofClass);
 203 
 204     public static Class<?> getValueClass() {
 205         return VALUE_TYPE_ENABLED ? ValueClassHolder.CLASS_OBJECT : null;












 206     }
 207 
 208     public static String mangleValueClassName(String name) {
 209         return ";Q" + name + ";";
 210     }
 211 
 212     /*
 213      * A holder class that references __Value to be loaded only when MVT is enabled.
 214      *
 215      * This holder class would fail verification if loaded if MVT is not enabled.
 216      */
 217     private static class ValueClassHolder {
 218          static final Class<?> CLASS_OBJECT =
 219              (Class<?>)(Object)__Value.class; //hack around static type-system checks
























































 220     }
 221 }


  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package valhalla.shady;
  26 
  27 import jdk.experimental.bytecode.BasicClassBuilder;
  28 import jdk.internal.misc.Unsafe;
  29 import jdk.internal.misc.VM;
  30 import sun.security.action.GetPropertyAction;
  31 
  32 import java.lang.annotation.Annotation;
  33 import java.io.BufferedOutputStream;
  34 import java.io.File;
  35 import java.io.IOException;
  36 import java.io.OutputStream;
  37 import java.nio.file.Files;
  38 import java.nio.file.Path;
  39 import java.nio.file.Paths;
  40 import java.security.ProtectionDomain;
  41 import java.util.Properties;
  42 import java.util.concurrent.ConcurrentHashMap;
  43 
  44 import static jdk.internal.org.objectweb.asm.Opcodes.*;
  45 
  46 import jdk.internal.misc.JavaLangAccess;
  47 import jdk.internal.misc.SharedSecrets;
  48 public class MinimalValueTypes_1_0 {
  49 
  50     public static final int V53_1 = 1 << 16 | 53;
  51     public static final int ACC_VALUE = ACC_NATIVE;
  52     public static final String OBJECT_CLASS_DESC = "java/lang/Object";
  53     public static final String VALUE_CLASS_DESC = "java/lang/__Value";
  54 
  55     public static final String DERIVE_VALUE_TYPE_DESC = "Ljdk/incubator/mvt/ValueCapableClass;";
  56     public static final String DERIVE_VT_CLASSNAME_POSTFIX = "$Value";
  57     public static final int    DERIVE_VT_CLASS_ACCESS = ACC_PUBLIC|ACC_SUPER|ACC_FINAL|ACC_VALUE|ACC_SYNTHETIC;
  58 
  59     public static final boolean DUMP_CLASS_FILES;
  60     private static final boolean VALUE_TYPE_ENABLED;
  61     private static final JavaLangAccess JLA;
  62 
  63     static {
  64         // Use same property as in j.l.invoke.MethodHandleStatics
  65         Properties props = GetPropertyAction.privilegedGetProperties();
  66         DUMP_CLASS_FILES = Boolean.parseBoolean(
  67             props.getProperty("java.lang.invoke.MethodHandle.DUMP_CLASS_FILES"));
  68 
  69         VALUE_TYPE_ENABLED = Boolean.parseBoolean(
  70             props.getProperty("valhalla.enableValueType"));
  71 
  72         JLA = SharedSecrets.getJavaLangAccess();
  73     }
  74 
  75     private static final ConcurrentHashMap<Class<?>, ValueTypeHolder<?>> BOX_TO_VT
  76         = new ConcurrentHashMap<>();
  77 
  78     /**
  79      * Returns the {@code ValueTypeHolder} representing the value type
  80      * for the given value capable type.
  81      *
  82      * @throws UnsupportedOperationException if MVT is not enabled
  83      * @throws IllegalArgumentException if the given class is not value capable class
  84      */
  85     @SuppressWarnings("unchecked")
  86     public static <T> ValueTypeHolder<T> getValueFor(Class<T> vcc) {
  87         if (!MinimalValueTypes_1_0.isValueTypeEnabled()) {
  88             throw new UnsupportedOperationException("MVT is not enabled");
  89         }
  90 
  91         if (!MinimalValueTypes_1_0.isValueCapable(vcc)) {
  92             throw new IllegalArgumentException("Class " + vcc + " not a value capable class");
  93         }
  94 
  95         ValueTypeHolder<T> vt = (ValueTypeHolder<T>) BOX_TO_VT.get(vcc);
  96         if (vt != null) {
  97             return vt;
  98         }
  99 
 100         Class<T> valueClass = (Class<T>) MinimalValueTypes_1_0.getValueTypeClass(vcc);
 101         vt = new ValueTypeHolder<T>(vcc, valueClass);
 102         ValueTypeHolder<T> old = (ValueTypeHolder<T>) BOX_TO_VT.putIfAbsent(vcc, vt);
 103         if (old != null) {
 104             vt = old;
 105         }
 106         return vt;
 107     }
 108 
 109     /**
 110      * Returns the {@code ValueTypeHolder} representing the value type
 111      * for the given class is a derived value type; otherwise {@code null}.
 112      */
 113     @SuppressWarnings("unchecked")
 114     public static <T> ValueTypeHolder<T> findValueType(Class<T> c) {
 115         if (MinimalValueTypes_1_0.isValueType(c)) {
 116             return (ValueTypeHolder<T>) getValueFor(MinimalValueTypes_1_0.getValueCapableClass(c));
 117         } else {
 118             return null;
 119         }
 120     }
 121 
 122     /**
 123      * Returns true if MVT is enabled.
 124      *
 125      * jdk.incubator.mvt must be resolved in the boot layer.
 126      */
 127     public static boolean isValueTypeEnabled() {
 128         return VALUE_TYPE_ENABLED;
 129     }
 130 
 131     public static boolean isValueType(Class<?> dvt) {
 132         return (dvt.getModifiers() & ACC_VALUE) != 0;
 133     }
 134 
 135     /**
 136      * Returns true if the given class is a value-capable class, i.e.
 137      * annotated with @ValueCapableClass.
 138      */
 139     public static boolean isValueCapable(Class<?> vcc) {
 140         if (!isValueTypeEnabled()) {
 141             return false;
 142         }
 143 
 144         return ValueClassHelper.hasValueCapableAnnotation(vcc);
 145     }
 146 
 147     public static Class<?> getValueCapableClass(Class<?> dvt) {
 148         if (!isValueType(dvt)) {
 149             throw new IllegalArgumentException(dvt + " is not a derived value type");
 150         }
 151 
 152         Class<?> c = Class.forName(dvt.getModule(), getValueCapableClassName(dvt.getName()));
 153         if (c == null || !isValueCapable(c)) {
 154             throw new InternalError(dvt + " not bound to ValueType");
 155         }
 156         return c;
 157     }
 158 
 159     public static Class<?> getValueTypeClass(Class<?> vcc) {
 160         if (!isValueCapable(vcc)) {
 161             throw new IllegalArgumentException(vcc + " is not a value capable class");
 162         }
 163         return loadValueTypeClass(vcc, getValueTypeClassName(vcc.getName()));
 164     }


 235                         if (!root.exists() && !root.mkdirs()) {
 236                             throw new IllegalStateException("Could not create dump file directory: " + root);
 237                         }
 238                         System.out.println("dump: " + dumpFile);
 239                         try (OutputStream os = Files.newOutputStream(dumpFile);
 240                              BufferedOutputStream bos = new BufferedOutputStream(os)) {
 241                             bos.write(classFile);
 242                         } catch (IOException ex) {
 243                             throw new InternalError(ex);
 244                         }
 245                         return null;
 246                     }
 247                 });
 248 
 249         }
 250     }
 251 
 252     private final native Class<?> getDerivedValueType(Class<?> ofClass);
 253 
 254     public static Class<?> getValueClass() {
 255         return isValueTypeEnabled() ? ValueClassHelper.VALUE_CLASS : null;
 256     }
 257 
 258     public static String getValueTypeClassName(ValueTypeDesc valueTypeDesc) {
 259         return getValueTypeClassName(valueTypeDesc.getName());
 260     }
 261 
 262     public static String getValueTypeClassName(String vccName) {
 263         return vccName + DERIVE_VT_CLASSNAME_POSTFIX;
 264     }
 265 
 266     public static String getValueCapableClassName(String valName) {
 267         return valName.substring(0, valName.length() - DERIVE_VT_CLASSNAME_POSTFIX.length());
 268     }
 269 
 270     public static String mangleValueClassName(String name) {
 271         return ";Q" + name + ";";
 272     }
 273 
 274     /*
 275      * This helper class should only be loaded when MVT is enabled.
 276      * Otherwise, it will load __Value but if MVT is not enabled and
 277      * that would fail verification.
 278      */
 279     private static class ValueClassHelper {
 280         static final Class<?> VALUE_CLASS =
 281              (Class<?>)(Object)__Value.class; //hack around static type-system checks
 282 
 283         static volatile Class<? extends Annotation> annotationClass;
 284         static volatile Class<?> valueTypeClass;
 285 
 286         static boolean hasValueCapableAnnotation(Class<?> c) {
 287             if (!VM.isModuleSystemInited()) {
 288                 return false;
 289             }
 290             Class<? extends Annotation> annClass = annotationClass;
 291             if (annClass == null) {
 292                 annotationClass = annClass = loadValueCapableAnnotation();
 293             }
 294             return annClass != null &&
 295                     c.getDeclaredAnnotation(annClass) != null;
 296         }
 297 
 298         /*
 299          * Returns jdk.incubator.mvt.ValueCapableClass annotation class
 300          */
 301         static Class<? extends Annotation> loadValueCapableAnnotation() {
 302             Module module = ModuleLayer.boot().findModule("jdk.incubator.mvt")
 303                                        .orElse(null);
 304             if (module == null)
 305                 return null;
 306 
 307             @SuppressWarnings("unchecked")
 308             Class<? extends Annotation> c = (Class<? extends Annotation>)
 309                     Class.forName(module, "jdk.incubator.mvt.ValueCapableClass");
 310             return c;
 311         }
 312 
 313         /*
 314          * Returns jdk.incubator.mvt.ValueType class
 315          */
 316         static Class<?> incubatorValueTypeClass() {
 317             Class<?> c = valueTypeClass;
 318             if (c == null) {
 319                 Module module = ModuleLayer.boot().findModule("jdk.incubator.mvt")
 320                                            .orElse(null);
 321                 if (module != null) {
 322                     valueTypeClass = c =
 323                         Class.forName(module, "jdk.incubator.mvt.ValueType");
 324                 }
 325             }
 326             return valueTypeClass;
 327         }
 328     }
 329 
 330     /*
 331      * Returns jdk.incubator.mvt.ValueType class from jdk.incubator.mvt module
 332      */
 333     static Class<?> getIncubatorValueTypeClass() {
 334         if (!isValueTypeEnabled()) {
 335             throw new UnsupportedOperationException("MVT is not enabled");
 336         }
 337         return ValueClassHelper.incubatorValueTypeClass();
 338     }
 339 }
< prev index next >