changeset 51186:8bfc38cd76fd condy-folding

manual merge with jep-334 branch
author vromero
date Thu, 14 Jun 2018 13:27:14 -0700
parents d456e9c21348 33043a17cb8e
children 86d506754fe0
files src/java.base/share/classes/java/lang/constant/ClassDesc.java src/java.base/share/classes/java/lang/constant/ConstantClassDesc.java src/java.base/share/classes/java/lang/constant/ConstantDesc.java src/java.base/share/classes/java/lang/constant/ConstantDescs.java src/java.base/share/classes/java/lang/constant/ConstantMethodHandleDesc.java src/java.base/share/classes/java/lang/constant/ConstantMethodTypeDesc.java src/java.base/share/classes/java/lang/constant/DirectMethodHandleDesc.java src/java.base/share/classes/java/lang/constant/DynamicCallSiteDesc.java src/java.base/share/classes/java/lang/constant/DynamicConstantDesc.java src/java.base/share/classes/java/lang/constant/MethodHandleDesc.java src/java.base/share/classes/java/lang/constant/MethodTypeDesc.java src/java.base/share/classes/java/lang/constant/MethodTypeDescImpl.java src/java.base/share/classes/java/lang/constant/PrimitiveClassDesc.java src/java.base/share/classes/java/lang/constant/PrimitiveClassDescImpl.java src/java.base/share/classes/java/lang/constant/ReferenceClassDescImpl.java src/java.base/share/classes/java/lang/constant/package-info.java src/java.base/share/classes/java/lang/invoke/MethodHandle.java src/java.base/share/classes/java/lang/invoke/VarHandle.java test/jdk/java/lang/constant/CondyRefTest.java test/jdk/java/lang/constant/ConstantUtilsTest.java test/jdk/java/lang/constant/MethodHandleRefTest.java
diffstat 23 files changed, 938 insertions(+), 867 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/java/lang/constant/ClassDesc.java	Fri Jun 08 15:38:32 2018 -0700
+++ b/src/java.base/share/classes/java/lang/constant/ClassDesc.java	Thu Jun 14 13:27:14 2018 -0700
@@ -26,7 +26,7 @@
 
 import jdk.internal.lang.annotation.Foldable;
 import java.lang.invoke.FieldTypeDescriptor;
-
+import java.lang.invoke.MethodHandles;
 import java.util.stream.Stream;
 
 import sun.invoke.util.Wrapper;
@@ -50,6 +50,11 @@
  * {@linkplain ClassDesc} for the component type and then call the {@link #arrayType()}
  * or {@link #arrayType(int)} methods.
  *
+ * @apiNote In the future, if the Java language permits, {@linkplain ClassDesc}
+ * may become a {@code sealed} interface, which would prohibit subclassing except
+ * by explicitly permitted types.  Non-platform classes should not implement
+ * {@linkplain ClassDesc} directly.
+ *
  * @see ConstantDescs
  */
 public interface ClassDesc
@@ -112,8 +117,8 @@
     static ClassDesc ofDescriptor(String descriptor) {
         requireNonNull(descriptor);
         return (descriptor.length() == 1)
-               ? new PrimitiveClassDesc(descriptor)
-               : new ConstantClassDesc(descriptor);
+               ? new PrimitiveClassDescImpl(descriptor)
+               : new ReferenceClassDescImpl(descriptor);
     }
 
     /**
@@ -261,6 +266,22 @@
     }
 
     /**
+     * Constant bootstrap method for representing a {@linkplain ClassDesc} in
+     * the constant pool of a classfile.
+     *
+     * @param lookup ignored
+     * @param name ignored
+     * @param clazz ignored
+     * @param descriptor a field descriptor string for the class, as per JVMS 4.3.2
+     * @return the {@linkplain ClassDesc}
+     * @jvms 4.3.2 Field Descriptors
+     */
+    public static ClassDesc constantBootstrap(MethodHandles.Lookup lookup, String name, Class<ClassDesc> clazz,
+                                              String descriptor) {
+        return ClassDesc.ofDescriptor(descriptor);
+    }
+
+    /**
      * Return a field type descriptor string for this type, as per JVMS 4.3.2
      *
      * @return the descriptor string
--- a/src/java.base/share/classes/java/lang/constant/ConstantClassDesc.java	Fri Jun 08 15:38:32 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,127 +0,0 @@
-/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  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 java.lang.constant;
-
-import java.lang.invoke.MethodHandles;
-import java.util.Objects;
-import java.util.Optional;
-
-import static java.lang.constant.ConstantDescs.BSM_CLASSDESC;
-import static java.lang.constant.ConstantDescs.CR_ClassDesc;
-import static java.lang.constant.ConstantUtils.dropFirstAndLastChar;
-import static java.lang.constant.ConstantUtils.internalToBinary;
-import static java.util.Objects.requireNonNull;
-
-/**
- * A <a href="package-summary.html#nominal">nominal descriptor</a> for a class,
- * interface, or array type.  A {@linkplain ConstantClassDesc} corresponds to a
- * {@code Constant_Class_info} entry in the constant pool of a classfile.
- */
-public final class ConstantClassDesc implements ClassDesc {
-    private final String descriptor;
-
-    /**
-     * Create a {@linkplain ClassDesc} from a descriptor string for a class or
-     * interface type
-     *
-     * @param descriptor a field descriptor string for a class or interface type,
-     *                   as per JVMS 4.3.2
-     * @throws IllegalArgumentException if the descriptor string is not a valid
-     * field descriptor string, or does not describe a class or interface type
-     * @jvms 4.3.2 Field Descriptors
-     */
-    ConstantClassDesc(String descriptor) {
-        requireNonNull(descriptor);
-        int len = ConstantUtils.matchSig(descriptor, 0, descriptor.length());
-        if (len == 0 || len == 1
-            || len != descriptor.length())
-            throw new IllegalArgumentException(String.format("not a valid reference type descriptor: %s", descriptor));
-        this.descriptor = descriptor;
-    }
-
-    @Override
-    public String descriptorString() {
-        return descriptor;
-    }
-
-    @Override
-    public Class<?> resolveConstantDesc(MethodHandles.Lookup lookup)
-            throws ReflectiveOperationException {
-        ClassDesc c = this;
-        int depth = ConstantUtils.arrayDepth(descriptorString());
-        for (int i=0; i<depth; i++)
-            c = c.componentType();
-
-        if (c.isPrimitive())
-            return lookup.findClass(descriptorString());
-        else {
-            Class<?> clazz = lookup.findClass(internalToBinary(dropFirstAndLastChar(c.descriptorString())));
-            for (int i = 0; i < depth; i++)
-                clazz = clazz.arrayType();
-            return clazz;
-        }
-    }
-
-    @Override
-    public Optional<? extends ConstantDesc<ConstantDesc<Class<?>>>> describeConstable() {
-        return Optional.of(DynamicConstantDesc.<ConstantDesc<Class<?>>>of(BSM_CLASSDESC, CR_ClassDesc)
-                                   .withArgs(descriptor));
-    }
-
-    /**
-     * Constant bootstrap method for representing a {@linkplain ClassDesc} in
-     * the constant pool of a classfile.
-     *
-     * @param lookup ignored
-     * @param name ignored
-     * @param clazz ignored
-     * @param descriptor a field descriptor string for the class, as per JVMS 4.3.2
-     * @return the {@linkplain ClassDesc}
-     * @jvms 4.3.2 Field Descriptors
-     */
-    public static ClassDesc constantBootstrap(MethodHandles.Lookup lookup, String name, Class<ClassDesc> clazz,
-                                              String descriptor) {
-        return ClassDesc.ofDescriptor(descriptor);
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        ClassDesc constant = (ClassDesc) o;
-        return descriptor.equals(constant.descriptorString());
-    }
-
-    @Override
-    public int hashCode() {
-        return descriptor.hashCode();
-    }
-
-    @Override
-    public String toString() {
-        return String.format("ClassDesc[%s]", displayName());
-    }
-}
--- a/src/java.base/share/classes/java/lang/constant/ConstantDesc.java	Fri Jun 08 15:38:32 2018 -0700
+++ b/src/java.base/share/classes/java/lang/constant/ConstantDesc.java	Thu Jun 14 13:27:14 2018 -0700
@@ -75,9 +75,9 @@
  * @apiNote In the future, if the Java language permits, {@linkplain ConstantDesc}
  * may become a {@code sealed} interface, which would prohibit subclassing except by
  * explicitly permitted types.  Clients can assume that the following
- * set of concrete subtypes is exhaustive: {@link String}, {@link Integer},
- * {@link Long}, {@link Float}, {@link Double}, {@link ConstantClassDesc},
- * {@link ConstantMethodTypeDesc}, {@link ConstantMethodHandleDesc}, and
+ * set of subtypes is exhaustive: {@link String}, {@link Integer},
+ * {@link Long}, {@link Float}, {@link Double}, {@link ClassDesc},
+ * {@link MethodTypeDesc}, {@link MethodHandleDesc}, and
  * {@link DynamicConstantDesc}; this list may be extended to reflect future
  * changes to the constant pool format as defined in JVMS 4.4.
  *
--- a/src/java.base/share/classes/java/lang/constant/ConstantDescs.java	Fri Jun 08 15:38:32 2018 -0700
+++ b/src/java.base/share/classes/java/lang/constant/ConstantDescs.java	Thu Jun 14 13:27:14 2018 -0700
@@ -40,7 +40,7 @@
 import java.util.Map;
 import java.util.Set;
 
-import static java.lang.constant.MethodHandleDesc.Kind.STATIC;
+import static java.lang.constant.DirectMethodHandleDesc.Kind.STATIC;
 
 /**
  * Predefined values of <a href="package-summary.html#nominal">nominal descriptor</a>
@@ -182,26 +182,19 @@
     @Foldable
     public static final ClassDesc CR_MethodTypeDesc = ClassDesc.of("java.lang.constant.MethodTypeDesc");
 
-    /** {@link ClassDesc} representing {@link ConstantClassDesc} */
-    public static final ClassDesc CR_ConstantClassDesc = ClassDesc.of("java.lang.constant.ConstantClassDesc");
-
-    /** {@link ClassDesc} representing {@link ConstantMethodTypeDesc} */
-    @Foldable
-    public static final ClassDesc CR_ConstantMethodTypeDesc = ClassDesc.of("java.lang.constant.ConstantMethodTypeDesc");
-
     /** {@link ClassDesc} representing {@link MethodHandleDesc} */
     @Foldable
     public static final ClassDesc CR_MethodHandleDesc = ClassDesc.of("java.lang.constant.MethodHandleDesc");
 
-    /** {@link ClassDesc} representing {@link ConstantMethodHandleDesc} */
+    /** {@link ClassDesc} representing {@link DirectMethodHandleDescImpl} */
     @Foldable
-    public static final ClassDesc CR_ConstantMethodHandleDesc = ClassDesc.of("java.lang.constant.ConstantMethodHandleDesc");
+    public static final ClassDesc CR_DirectMethodHandleDesc = ClassDesc.of("java.lang.constant.DirectMethodHandleDesc");
 
     /** {@link ClassDesc} representing {@link VarHandleDesc} */
     @Foldable
     public static final ClassDesc CR_VarHandleDesc = CR_VarHandle.inner("VarHandleDesc");
 
-    /** {@link ClassDesc} representing {@link MethodHandleDesc.Kind} */
+    /** {@link ClassDesc} representing {@link DirectMethodHandleDesc.Kind} */
     @Foldable
     public static final ClassDesc CR_MethodHandleDesc_Kind = CR_MethodHandleDesc.inner("Kind");
 
@@ -231,43 +224,43 @@
 
     /** {@link MethodHandleDesc} representing {@link ConstantBootstraps#primitiveClass(Lookup, String, Class)} */
     @Foldable
-    public static final ConstantMethodHandleDesc BSM_PRIMITIVE_CLASS
+    public static final DirectMethodHandleDesc BSM_PRIMITIVE_CLASS
             = ofConstantBootstrap(CR_ConstantBootstraps, "primitiveClass",
                                   CR_Class);
 
     /** {@link MethodHandleDesc} representing {@link ConstantBootstraps#enumConstant(Lookup, String, Class)} */
     @Foldable
-    public static final ConstantMethodHandleDesc BSM_ENUM_CONSTANT
+    public static final DirectMethodHandleDesc BSM_ENUM_CONSTANT
             = ofConstantBootstrap(CR_ConstantBootstraps, "enumConstant",
                                   CR_Enum);
 
     /** {@link MethodHandleDesc} representing {@link ConstantBootstraps#nullConstant(Lookup, String, Class)} */
     @Foldable
-    public static final ConstantMethodHandleDesc BSM_NULL_CONSTANT
+    public static final DirectMethodHandleDesc BSM_NULL_CONSTANT
             = ofConstantBootstrap(CR_ConstantBootstraps, "nullConstant",
                                   ConstantDescs.CR_Object);
 
     /** {@link MethodHandleDesc} representing {@link ConstantBootstraps#fieldVarHandle(Lookup, String, Class, Class, Class)} */
     @Foldable
-    public static final ConstantMethodHandleDesc BSM_VARHANDLE_FIELD
+    public static final DirectMethodHandleDesc BSM_VARHANDLE_FIELD
             = ofConstantBootstrap(CR_ConstantBootstraps, "fieldVarHandle",
                                   CR_VarHandle, CR_Class, CR_Class);
 
     /** {@link MethodHandleDesc} representing {@link ConstantBootstraps#staticFieldVarHandle(Lookup, String, Class, Class, Class)} */
     @Foldable
-    public static final ConstantMethodHandleDesc BSM_VARHANDLE_STATIC_FIELD
+    public static final DirectMethodHandleDesc BSM_VARHANDLE_STATIC_FIELD
             = ofConstantBootstrap(CR_ConstantBootstraps, "staticFieldVarHandle",
                                   CR_VarHandle, CR_Class, CR_Class);
 
     /** {@link MethodHandleDesc} representing {@link ConstantBootstraps#arrayVarHandle(Lookup, String, Class, Class)} */
     @Foldable
-    public static final ConstantMethodHandleDesc BSM_VARHANDLE_ARRAY
+    public static final DirectMethodHandleDesc BSM_VARHANDLE_ARRAY
             = ofConstantBootstrap(CR_ConstantBootstraps, "arrayVarHandle",
                                   CR_VarHandle, CR_Class);
 
     /** {@link MethodHandleDesc} representing {@link ConstantBootstraps#invoke(Lookup, String, Class, MethodHandle, Object...)} */
     @Foldable
-    public static final ConstantMethodHandleDesc BSM_INVOKE
+    public static final DirectMethodHandleDesc BSM_INVOKE
             = ofConstantBootstrap(CR_ConstantBootstraps, "invoke",
                                   CR_Object, CR_MethodHandle, CR_Object.arrayType());
 
@@ -314,70 +307,70 @@
                                      ConstantDescs.CR_Object);
 
     // Used by XxxDesc classes, but need to be here to avoid bootstrap cycles
-    static final ConstantMethodHandleDesc MHR_METHODTYPEDESC_FACTORY
-            = MethodHandleDesc.of(MethodHandleDesc.Kind.STATIC, CR_MethodTypeDesc, "ofDescriptor",
+    static final DirectMethodHandleDesc MHR_METHODTYPEDESC_FACTORY
+            = MethodHandleDesc.of(DirectMethodHandleDesc.Kind.STATIC, CR_MethodTypeDesc, "ofDescriptor",
                                   CR_MethodTypeDesc, CR_String);
 
-    static final ConstantMethodHandleDesc MHR_CLASSDESC_FACTORY
-            = MethodHandleDesc.of(MethodHandleDesc.Kind.STATIC, CR_ClassDesc, "ofDescriptor",
+    static final DirectMethodHandleDesc MHR_CLASSDESC_FACTORY
+            = MethodHandleDesc.of(DirectMethodHandleDesc.Kind.STATIC, CR_ClassDesc, "ofDescriptor",
                                   CR_ClassDesc, CR_String);
 
-    static final ConstantMethodHandleDesc MHR_METHODHANDLEDESC_FACTORY
-            = MethodHandleDesc.of(MethodHandleDesc.Kind.STATIC, CR_MethodHandleDesc, "of",
+    static final DirectMethodHandleDesc MHR_METHODHANDLEDESC_FACTORY
+            = MethodHandleDesc.of(DirectMethodHandleDesc.Kind.STATIC, CR_MethodHandleDesc, "of",
                                   CR_MethodHandleDesc, CR_MethodHandleDesc_Kind, CR_ClassDesc, CR_String, CR_MethodTypeDesc);
 
-    static final ConstantMethodHandleDesc MHR_METHODHANDLE_ASTYPE
-            = MethodHandleDesc.of(MethodHandleDesc.Kind.VIRTUAL, CR_MethodHandle, "asType",
+    static final DirectMethodHandleDesc MHR_METHODHANDLE_ASTYPE
+            = MethodHandleDesc.of(DirectMethodHandleDesc.Kind.VIRTUAL, CR_MethodHandle, "asType",
                                   CR_MethodHandle, CR_MethodType);
 
-    static final ConstantMethodHandleDesc MHR_METHODHANDLEDESC_ASTYPE
-            = MethodHandleDesc.of(MethodHandleDesc.Kind.VIRTUAL, CR_MethodHandleDesc, "asType",
+    static final DirectMethodHandleDesc MHR_METHODHANDLEDESC_ASTYPE
+            = MethodHandleDesc.of(DirectMethodHandleDesc.Kind.VIRTUAL, CR_MethodHandleDesc, "asType",
                                   CR_MethodHandleDesc, CR_MethodTypeDesc);
 
-    static final ConstantMethodHandleDesc MHR_DYNAMICCONSTANTDESC_FACTORY
-            = MethodHandleDesc.of(MethodHandleDesc.Kind.STATIC, CR_DynamicConstantDesc, "of",
+    static final DirectMethodHandleDesc MHR_DYNAMICCONSTANTDESC_FACTORY
+            = MethodHandleDesc.of(DirectMethodHandleDesc.Kind.STATIC, CR_DynamicConstantDesc, "of",
                                   CR_DynamicConstantDesc, CR_MethodHandleDesc, CR_String, CR_ClassDesc);
 
-    static final ConstantMethodHandleDesc MHR_DYNAMICCONSTANTDESC_WITHARGS
-            = MethodHandleDesc.of(MethodHandleDesc.Kind.VIRTUAL, CR_DynamicConstantDesc, "withArgs",
+    static final DirectMethodHandleDesc MHR_DYNAMICCONSTANTDESC_WITHARGS
+            = MethodHandleDesc.of(DirectMethodHandleDesc.Kind.VIRTUAL, CR_DynamicConstantDesc, "withArgs",
                                   CR_DynamicConstantDesc, CR_ConstantDesc.arrayType());
 
-    static final ConstantMethodHandleDesc MHR_ENUMDESC_FACTORY
-            = MethodHandleDesc.of(MethodHandleDesc.Kind.STATIC, CR_EnumDesc, "of",
+    static final DirectMethodHandleDesc MHR_ENUMDESC_FACTORY
+            = MethodHandleDesc.of(DirectMethodHandleDesc.Kind.STATIC, CR_EnumDesc, "of",
                                   CR_EnumDesc, CR_ClassDesc, CR_String);
 
-    /** {@link MethodHandleDesc} representing {@link VarHandleDesc#ofField(Lookup, String, Class, Class, String, Class)} */
-    public static final ConstantMethodHandleDesc MHR_VARHANDLEDESC_OFFIELD
-            = MethodHandleDesc.of(MethodHandleDesc.Kind.STATIC, CR_VarHandleDesc, "ofField",
+    /** {@link MethodHandleDesc} representing {@link VarHandleDesc#ofField(ClassDesc, String, ClassDesc)} */
+    public static final DirectMethodHandleDesc MHR_VARHANDLEDESC_OFFIELD
+            = MethodHandleDesc.of(DirectMethodHandleDesc.Kind.STATIC, CR_VarHandleDesc, "ofField",
                                   CR_VarHandleDesc, CR_ClassDesc, CR_String, CR_ClassDesc);
-    /** {@link MethodHandleDesc} representing {@link VarHandleDesc#ofStaticField(Lookup, String, Class, Class, String, Class)} */
-    public static final ConstantMethodHandleDesc MHR_VARHANDLEDESC_OFSTATIC
-            = MethodHandleDesc.of(MethodHandleDesc.Kind.STATIC, CR_VarHandleDesc, "ofStaticField",
+    /** {@link MethodHandleDesc} representing {@link VarHandleDesc#ofStaticField(ClassDesc, String, ClassDesc)} */
+    public static final DirectMethodHandleDesc MHR_VARHANDLEDESC_OFSTATIC
+            = MethodHandleDesc.of(DirectMethodHandleDesc.Kind.STATIC, CR_VarHandleDesc, "ofStaticField",
                                   CR_VarHandleDesc, CR_ClassDesc, CR_String, CR_ClassDesc);
 
-    /** {@link MethodHandleDesc} representing {@link VarHandleDesc#ofArray(Lookup, String, Class, Class, Class)} */
-    public static final ConstantMethodHandleDesc MHR_VARHANDLEDESC_OFARRAY
-            = MethodHandleDesc.of(MethodHandleDesc.Kind.STATIC, CR_VarHandleDesc, "ofArray",
+    /** {@link MethodHandleDesc} representing {@link VarHandleDesc#ofArray(ClassDesc)} */
+    public static final DirectMethodHandleDesc MHR_VARHANDLEDESC_OFARRAY
+            = MethodHandleDesc.of(DirectMethodHandleDesc.Kind.STATIC, CR_VarHandleDesc, "ofArray",
                                   CR_VarHandleDesc, CR_ClassDesc);
 
-    static final ConstantMethodHandleDesc BSM_CLASSDESC
-            = ConstantDescs.ofConstantBootstrap(CR_ConstantClassDesc,
+    static final DirectMethodHandleDesc BSM_CLASSDESC
+            = ConstantDescs.ofConstantBootstrap(CR_ClassDesc,
                                                 "constantBootstrap", CR_ClassDesc, CR_String);
 
-    static final ConstantMethodHandleDesc BSM_METHODTYPEDESC
-            = ConstantDescs.ofConstantBootstrap(CR_ConstantMethodTypeDesc,
-                                                "constantBootstrap", CR_ConstantMethodTypeDesc, CR_String);
+    static final DirectMethodHandleDesc BSM_METHODTYPEDESC
+            = ConstantDescs.ofConstantBootstrap(CR_MethodTypeDesc,
+                                                "constantBootstrap", CR_MethodTypeDesc, CR_String);
 
-    static final ConstantMethodHandleDesc BSM_METHODHANDLEDESC
-            = ConstantDescs.ofConstantBootstrap(CR_ConstantMethodHandleDesc,
-                                                "constantBootstrap", CR_ConstantMethodHandleDesc,
+    static final DirectMethodHandleDesc BSM_METHODHANDLEDESC
+            = ConstantDescs.ofConstantBootstrap(CR_DirectMethodHandleDesc,
+                                                "constantBootstrap", CR_DirectMethodHandleDesc,
                                                 CR_String, CR_String, CR_String, CR_String);
 
     /** {@link MethodHandleDesc} representing {@link EnumDesc#constantBootstrap(Lookup, String, Class, String, String)} */
-    public static final ConstantMethodHandleDesc BSM_ENUMDESC
+    public static final DirectMethodHandleDesc BSM_ENUMDESC
             = ConstantDescs.ofConstantBootstrap(CR_EnumDesc, "constantBootstrap", CR_EnumDesc, CR_String, CR_String);
 
-    static final ConstantMethodHandleDesc BSM_DYNAMICCONSTANTDESC
+    static final DirectMethodHandleDesc BSM_DYNAMICCONSTANTDESC
             = ConstantDescs.ofConstantBootstrap(CR_DynamicConstantDesc,
                                                 "constantBootstrap",
                                                 CR_DynamicConstantDesc,
@@ -398,10 +391,10 @@
      * @jvms 4.2.2 Unqualified Names
      */
     @Foldable
-    public static ConstantMethodHandleDesc ofCallsiteBootstrap(ClassDesc clazz,
-                                                               String name,
-                                                               ClassDesc returnType,
-                                                               ClassDesc... paramTypes) {
+    public static DirectMethodHandleDesc ofCallsiteBootstrap(ClassDesc clazz,
+                                                             String name,
+                                                             ClassDesc returnType,
+                                                             ClassDesc... paramTypes) {
         return MethodHandleDesc.of(STATIC, clazz, name, MethodTypeDesc.of(returnType, paramTypes).insertParameterTypes(0, INDY_BOOTSTRAP_ARGS));
     }
 
@@ -419,10 +412,10 @@
      * @jvms 4.2.2 Unqualified Names
      */
     @Foldable
-    public static ConstantMethodHandleDesc ofConstantBootstrap(ClassDesc clazz,
-                                                               String name,
-                                                               ClassDesc returnType,
-                                                               ClassDesc... paramTypes) {
+    public static DirectMethodHandleDesc ofConstantBootstrap(ClassDesc clazz,
+                                                             String name,
+                                                             ClassDesc returnType,
+                                                             ClassDesc... paramTypes) {
         return MethodHandleDesc.of(STATIC, clazz, name, MethodTypeDesc.of(returnType, paramTypes).insertParameterTypes(0, CONDY_BOOTSTRAP_ARGS));
     }
 }
--- a/src/java.base/share/classes/java/lang/constant/ConstantMethodHandleDesc.java	Fri Jun 08 15:38:32 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,249 +0,0 @@
-/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  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 java.lang.constant;
-
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandleInfo;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-import java.util.Objects;
-import java.util.Optional;
-
-import jdk.internal.lang.annotation.Foldable;
-
-import static java.lang.constant.ConstantDescs.BSM_METHODHANDLEDESC;
-import static java.lang.constant.ConstantDescs.CR_ConstantMethodHandleDesc;
-import static java.lang.constant.ConstantUtils.validateClassOrInterface;
-import static java.lang.constant.ConstantUtils.validateMemberName;
-import static java.lang.constant.MethodHandleDesc.Kind.CONSTRUCTOR;
-import static java.util.Objects.requireNonNull;
-
-/**
- * A <a href="package-summary.html#nominal">nominal descriptor</a> for a direct
- * {@link MethodHandle}.  A {@linkplain ConstantMethodHandleDesc} corresponds to
- * a {@code Constant_MethodHandle_info} entry in the constant pool of a classfile.
- */
-public final class ConstantMethodHandleDesc implements MethodHandleDesc {
-
-    private final Kind kind;
-    private final ClassDesc owner;
-    private final String name;
-    private final MethodTypeDesc type;
-
-    /**
-     * Construct a {@linkplain ConstantMethodHandleDesc} for a method or field
-     * from a kind, owner, name, and type
-     *
-     * @param kind the kind of the method handle
-     * @param owner the declaring class or interface for the method
-     * @param name the name of the method (ignored if {@code kind} is
-     * {@code CONSTRUCTOR}), as per JVMS 4.2.2
-     * @param type the type of the method
-     * @throws NullPointerException if any non-ignored argument is null
-     * @throws IllegalArgumentException if {@code kind} describes a field accessor,
-     * and {@code type} is not consistent with that kind of field accessor, or if
-     * {@code kind} describes a constructor, and the return type of {@code type}
-     * is not {@code void}
-     * @jvms 4.2.2 Unqualified Names
-     */
-    ConstantMethodHandleDesc(Kind kind, ClassDesc owner, String name, MethodTypeDesc type) {
-        if (kind == CONSTRUCTOR)
-            name = "<init>";
-
-        requireNonNull(kind);
-        validateClassOrInterface(requireNonNull(owner));
-        validateMemberName(requireNonNull(name));
-        requireNonNull(type);
-
-        switch (kind) {
-            case CONSTRUCTOR: validateConstructor(type); break;
-            case GETTER: validateFieldType(type, false, true); break;
-            case SETTER: validateFieldType(type, true, true); break;
-            case STATIC_GETTER: validateFieldType(type, false, false); break;
-            case STATIC_SETTER: validateFieldType(type, true, false); break;
-        }
-
-        this.kind = kind;
-        this.owner = owner;
-        this.name = name;
-        this.type = type;
-    }
-
-    private static void validateFieldType(MethodTypeDesc type, boolean isSetter, boolean isVirtual) {
-        boolean isVoid = type.returnType().descriptorString().equals("V");
-        int expectedParams = (isSetter ? 1 : 0) + (isVirtual ? 1 : 0);
-        if (isVoid != isSetter
-            || type.parameterCount() != expectedParams
-            || (isVirtual && type.parameterType(0).isPrimitive())) {
-            String expectedType = String.format("(%s%s)%s", (isVirtual ? "R" : ""),
-                                                (isSetter ? "T" : ""), (isSetter ? "V" : "T"));
-            throw new IllegalArgumentException(String.format("Expected type of %s for getter, found %s", expectedType, type));
-        }
-    }
-
-    private static void validateConstructor(MethodTypeDesc type) {
-        if (!type.returnType().descriptorString().equals("V")) {
-            throw new IllegalArgumentException(String.format("Expected type of (T*)V for constructor, found %s", type));
-        }
-    }
-
-    /**
-     * Return the {@code kind} of the method handle described by this nominal
-     * descriptor.
-     *
-     * @return the {@link Kind}
-     */
-    @Foldable
-    public Kind kind() { return kind; }
-
-    /**
-     * Return the {@code refKind} of the method handle described by this nominal
-     * reference, as defined by {@link MethodHandleInfo}.
-     *
-     * @return the reference kind
-     */
-    @Foldable
-    public int refKind() { return kind.refKind; }
-
-    /**
-     * Indicates if the method is declared by an interface
-     *
-     * @return true if the method is declared by an interface
-     */
-    public boolean isOwnerInterface() { return kind.isInterface; }
-
-    /**
-     * Return a {@link ClassDesc} describing the class declaring the
-     * method or field described by this nominal descriptor.
-     *
-     * @return the class declaring the method or field
-     */
-    @Foldable
-    public ClassDesc owner() {
-        return owner;
-    }
-
-    /**
-     * Return the name of the method or field described by this nominal descriptor.
-     *
-     * @return the name of the method or field
-     */
-    @Foldable
-    public String methodName() {
-        return name;
-    }
-
-    /**
-     * Return a {@link MethodTypeDesc} describing the invocation type of the
-     * method handle described by this nominal descriptor
-     *
-     * @return the method type
-     */
-    @Foldable
-    public MethodTypeDesc methodType() {
-        return type;
-    }
-
-    public MethodHandle resolveConstantDesc(MethodHandles.Lookup lookup)
-            throws ReflectiveOperationException {
-        Class<?> resolvedOwner = owner.resolveConstantDesc(lookup);
-        MethodType resolvedType = this.type.resolveConstantDesc(lookup);
-        switch (kind) {
-            case STATIC:
-            case INTERFACE_STATIC:
-                return lookup.findStatic(resolvedOwner, name, resolvedType);
-            case INTERFACE_VIRTUAL:
-            case VIRTUAL:
-                return lookup.findVirtual(resolvedOwner, name, resolvedType);
-            case SPECIAL:
-            case INTERFACE_SPECIAL:
-                return lookup.findSpecial(resolvedOwner, name, resolvedType, lookup.lookupClass());
-            case CONSTRUCTOR:
-                return lookup.findConstructor(resolvedOwner, resolvedType);
-            case GETTER:
-                return lookup.findGetter(resolvedOwner, name, resolvedType.returnType());
-            case STATIC_GETTER:
-                return lookup.findStaticGetter(resolvedOwner, name, resolvedType.returnType());
-            case SETTER:
-                return lookup.findSetter(resolvedOwner, name, resolvedType.parameterType(1));
-            case STATIC_SETTER:
-                return lookup.findStaticSetter(resolvedOwner, name, resolvedType.parameterType(0));
-            default:
-                throw new IllegalStateException(kind.name());
-        }
-    }
-
-    @Override
-    public Optional<? extends ConstantDesc<ConstantDesc<MethodHandle>>> describeConstable() {
-        return Optional.of(DynamicConstantDesc.<ConstantDesc<MethodHandle>>of(BSM_METHODHANDLEDESC, CR_ConstantMethodHandleDesc)
-                                              .withArgs(kind.toString(), owner.descriptorString(), name, type.descriptorString()));
-    }
-
-    /**
-     * Constant bootstrap method for representing a {@linkplain MethodHandleDesc} in
-     * the constant pool of a classfile.
-     *
-     * @param lookup ignored
-     * @param name ignored
-     * @param clazz ignored
-     * @param bsmKindName The name of an {@code enum} constant from {@link Kind}
-     * @param memberOwner A field type descriptor for the class declaring the
-     *                 method, field, or constructor, as per JVMS 4.3.2
-     * @param memberName The name of the method or field, as per JVMS 4.2.2
-     * @param memberType A method type descriptor for the method handle being
-     *                described, as per JVMS 4.3.3
-     * @return the {@linkplain MethodHandleDesc}
-     * @jvms 4.2.2 Unqualified Names
-     * @jvms 4.3.2 Field Descriptors
-     * @jvms 4.3.3 Method Descriptors
-     */
-    public static ConstantMethodHandleDesc constantBootstrap(MethodHandles.Lookup lookup, String name, Class<ClassDesc> clazz,
-                                                     String bsmKindName, String memberOwner, String memberName, String memberType) {
-        return MethodHandleDesc.of(MethodHandleDesc.Kind.valueOf(bsmKindName),
-                                   ClassDesc.ofDescriptor(memberOwner), memberName,
-                                   MethodTypeDesc.ofDescriptor(memberType));
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-        ConstantMethodHandleDesc desc = (ConstantMethodHandleDesc) o;
-        return kind == desc.kind &&
-               Objects.equals(owner, desc.owner) &&
-               Objects.equals(name, desc.name) &&
-               Objects.equals(type, desc.type);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(kind, owner, name, type);
-    }
-
-    @Override
-    public String toString() {
-        return String.format("MethodHandleDesc[%s/%s::%s%s]", kind, owner.displayName(), name, type.displayDescriptor());
-    }
-}
--- a/src/java.base/share/classes/java/lang/constant/ConstantMethodTypeDesc.java	Fri Jun 08 15:38:32 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,197 +0,0 @@
-/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  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 java.lang.constant;
-
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Optional;
-
-import jdk.internal.lang.annotation.Foldable;
-
-import static java.lang.constant.ConstantDescs.BSM_METHODTYPEDESC;
-import static java.lang.constant.ConstantDescs.CR_ConstantMethodTypeDesc;
-import static java.util.Objects.requireNonNull;
-
-/**
- * A <a href="package-summary.html#nominal">nominal descriptor</a> for a
- * {@link MethodType}.  A {@linkplain ConstantMethodTypeDesc} corresponds to a
- * {@code Constant_MethodType_info} entry in the constant pool of a classfile.
- */
-public final class ConstantMethodTypeDesc implements MethodTypeDesc {
-    private final ClassDesc returnType;
-    private final ClassDesc[] argTypes;
-
-    /**
-     * Construct a {@linkplain MethodTypeDesc} with the specified return type
-     * and parameter types
-     *
-     * @param returnType a {@link ClassDesc} describing the return type
-     * @param argTypes {@link ClassDesc}s describing the parameter types
-     */
-    ConstantMethodTypeDesc(ClassDesc returnType, ClassDesc[] argTypes) {
-        this.returnType = requireNonNull(returnType);
-        this.argTypes = requireNonNull(argTypes);
-
-        for (ClassDesc cr : argTypes)
-            if (cr.isPrimitive() && cr.descriptorString().equals("V"))
-                throw new IllegalArgumentException("Void parameters not permitted");
-    }
-
-    /**
-     * Create a {@linkplain ConstantMethodTypeDesc} given a method descriptor string.
-     *
-     * @param descriptor the method descriptor string, as per JVMS 4.3.3
-     * @return a {@linkplain ConstantMethodTypeDesc} describing the desired method type
-     * @throws IllegalArgumentException if the descriptor string is not a valid
-     * method descriptor
-     * @jvms 4.3.3 Method Descriptors
-     */
-    @Foldable
-    static ConstantMethodTypeDesc ofDescriptor(String descriptor) {
-        requireNonNull(descriptor);
-        List<String> types = ConstantUtils.parseMethodDescriptor(descriptor);
-        ClassDesc[] paramTypes = types.stream().skip(1).map(ClassDesc::ofDescriptor).toArray(ClassDesc[]::new);
-        return new ConstantMethodTypeDesc(ClassDesc.ofDescriptor(types.get(0)), paramTypes);
-    }
-
-    @Foldable
-    @Override
-    public ClassDesc returnType() {
-        return returnType;
-    }
-
-    @Foldable
-    @Override
-    public int parameterCount() {
-        return argTypes.length;
-    }
-
-    @Foldable
-    @Override
-    public ClassDesc parameterType(int index) {
-        return argTypes[index];
-    }
-
-    @Override
-    public List<ClassDesc> parameterList() {
-        return List.of(argTypes);
-    }
-
-    @Override
-    public ClassDesc[] parameterArray() {
-        return argTypes.clone();
-    }
-
-    @Foldable
-    @Override
-    public MethodTypeDesc changeReturnType(ClassDesc returnType) {
-        return MethodTypeDesc.of(returnType, argTypes);
-    }
-
-    @Foldable
-    @Override
-    public MethodTypeDesc changeParameterType(int index, ClassDesc paramType) {
-        ClassDesc[] newArgs = argTypes.clone();
-        newArgs[index] = paramType;
-        return MethodTypeDesc.of(returnType, newArgs);
-    }
-
-    @Foldable
-    @Override
-    public MethodTypeDesc dropParameterTypes(int start, int end) {
-        if (start < 0 || start >= argTypes.length || end < 0 || end > argTypes.length)
-            throw new IndexOutOfBoundsException();
-        else if (start > end)
-            throw new IllegalArgumentException(String.format("Range (%d, %d) not valid for size %d", start, end, argTypes.length));
-        ClassDesc[] newArgs = new ClassDesc[argTypes.length - (end - start)];
-        System.arraycopy(argTypes, 0, newArgs, 0, start);
-        System.arraycopy(argTypes, end, newArgs, start, argTypes.length - end);
-        return MethodTypeDesc.of(returnType, newArgs);
-    }
-
-    @Foldable
-    @Override
-    public MethodTypeDesc insertParameterTypes(int pos, ClassDesc... paramTypes) {
-        if (pos < 0 || pos > argTypes.length)
-            throw new IndexOutOfBoundsException(pos);
-        ClassDesc[] newArgs = new ClassDesc[argTypes.length + paramTypes.length];
-        System.arraycopy(argTypes, 0, newArgs, 0, pos);
-        System.arraycopy(paramTypes, 0, newArgs, pos, paramTypes.length);
-        System.arraycopy(argTypes, pos, newArgs, pos+paramTypes.length, argTypes.length - pos);
-        return MethodTypeDesc.of(returnType, newArgs);
-    }
-
-    @Override
-    public MethodType resolveConstantDesc(MethodHandles.Lookup lookup) {
-        return MethodType.fromMethodDescriptorString(descriptorString(), lookup.lookupClass().getClassLoader());
-    }
-
-    @Override
-    public Optional<? extends ConstantDesc<ConstantDesc<MethodType>>> describeConstable() {
-        return Optional.of(DynamicConstantDesc.<ConstantDesc<MethodType>>of(BSM_METHODTYPEDESC, CR_ConstantMethodTypeDesc)
-                                   .withArgs(descriptorString()));
-    }
-
-    /**
-     * Constant bootstrap method for representing a {@linkplain MethodTypeDesc} in
-     * the constant pool of a classfile.
-     *
-     * @param lookup ignored
-     * @param name ignored
-     * @param clazz ignored
-     * @param descriptor a method descriptor string for the method type, as per JVMS 4.3.3
-     * @return the {@linkplain MethodTypeDesc}
-     * @jvms 4.3.3 Method Descriptors
-     */
-    public static ConstantMethodTypeDesc constantBootstrap(MethodHandles.Lookup lookup, String name, Class<ClassDesc> clazz,
-                                                   String descriptor) {
-        return (ConstantMethodTypeDesc)MethodTypeDesc.ofDescriptor(descriptor);
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        ConstantMethodTypeDesc constant = (ConstantMethodTypeDesc) o;
-
-        return returnType.equals(constant.returnType)
-               && Arrays.equals(argTypes, constant.argTypes);
-    }
-
-    @Override
-    public int hashCode() {
-        int result = returnType.hashCode();
-        result = 31 * result + Arrays.hashCode(argTypes);
-        return result;
-    }
-
-    @Override
-    public String toString() {
-        return String.format("MethodTypeDesc[%s]", displayDescriptor());
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/constant/DirectMethodHandleDesc.java	Thu Jun 14 13:27:14 2018 -0700
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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 java.lang.constant;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandleInfo;
+import java.lang.invoke.MethodHandles;
+
+import jdk.internal.lang.annotation.Foldable;
+
+import static java.lang.invoke.MethodHandleInfo.REF_getField;
+import static java.lang.invoke.MethodHandleInfo.REF_getStatic;
+import static java.lang.invoke.MethodHandleInfo.REF_invokeInterface;
+import static java.lang.invoke.MethodHandleInfo.REF_invokeSpecial;
+import static java.lang.invoke.MethodHandleInfo.REF_invokeStatic;
+import static java.lang.invoke.MethodHandleInfo.REF_invokeVirtual;
+import static java.lang.invoke.MethodHandleInfo.REF_newInvokeSpecial;
+import static java.lang.invoke.MethodHandleInfo.REF_putField;
+import static java.lang.invoke.MethodHandleInfo.REF_putStatic;
+
+/**
+ * A <a href="package-summary.html#nominal">nominal descriptor</a> for a direct
+ * {@link MethodHandle}.  A {@linkplain DirectMethodHandleDescImpl} corresponds to
+ * a {@code Constant_MethodHandle_info} entry in the constant pool of a classfile.
+ *
+ * @apiNote In the future, if the Java language permits, {@linkplain DirectMethodHandleDesc}
+ * may become a {@code sealed} interface, which would prohibit subclassing except
+ * by explicitly permitted types.  Non-platform classes should not implement
+ * {@linkplain DirectMethodHandleDesc} directly.
+ */
+public interface DirectMethodHandleDesc extends MethodHandleDesc {
+    /**
+     * Kinds of method handles that can be described with {@linkplain DirectMethodHandleDesc}.
+     */
+    enum Kind {
+        /** A method handle for a method invoked as with {@code invokestatic} */
+        STATIC(REF_invokeStatic),
+        /** A method handle for a method invoked as with {@code invokestatic} */
+        INTERFACE_STATIC(REF_invokeStatic, true),
+        /** A method handle for a method invoked as with {@code invokevirtual} */
+        VIRTUAL(REF_invokeVirtual),
+        /** A method handle for a method invoked as with {@code invokeinterface} */
+        INTERFACE_VIRTUAL(REF_invokeInterface, true),
+        /** A method handle for a method invoked as with {@code invokespecial} */
+        SPECIAL(REF_invokeSpecial),
+        /** A method handle for an interface method invoked as with {@code invokespecial} */
+        INTERFACE_SPECIAL(REF_invokeSpecial, true),
+        /** A method handle for a constructor */
+        CONSTRUCTOR(REF_newInvokeSpecial),
+        /** A method handle for a read accessor for an instance field  */
+        GETTER(REF_getField),
+        /** A method handle for a write accessor for an instance field  */
+        SETTER(REF_putField),
+        /** A method handle for a read accessor for a static field  */
+        STATIC_GETTER(REF_getStatic),
+        /** A method handle for a write accessor for a static field  */
+        STATIC_SETTER(REF_putStatic);
+
+        /** The corresponding {@code refKind} value for this kind of method handle,
+         * as defined by {@link MethodHandleInfo}
+         */
+        public final int refKind;
+
+        /** Is this an interface
+         */
+        public final boolean isInterface;
+        Kind(int refKind) {
+            this(refKind, false);
+        }
+
+        Kind(int refKind, boolean isInterface) { this.refKind = refKind; this.isInterface = isInterface; }
+    }
+    /**
+     * Return the {@code kind} of the method handle described by this nominal
+     * descriptor.
+     *
+     * @return the {@link Kind}
+     */
+    @Foldable
+    Kind kind();
+
+    /**
+     * Return the {@code refKind} of the method handle described by this nominal
+     * reference, as defined by {@link MethodHandleInfo}.
+     *
+     * @return the reference kind
+     */
+    @Foldable
+    int refKind();
+
+    /**
+     * Indicates if the method is declared by an interface
+     *
+     * @return true if the method is declared by an interface
+     */
+    boolean isOwnerInterface();
+
+    /**
+     * Return a {@link ClassDesc} describing the class declaring the
+     * method or field described by this nominal descriptor.
+     *
+     * @return the class declaring the method or field
+     */
+    @Foldable
+    ClassDesc owner();
+
+    /**
+     * Return the name of the method or field described by this nominal descriptor.
+     *
+     * @return the name of the method or field
+     */
+    @Foldable
+    String methodName();
+
+    /**
+     * Return a {@link MethodTypeDesc} describing the invocation type of the
+     * method handle described by this nominal descriptor
+     *
+     * @return the method type
+     */
+    @Foldable
+    MethodTypeDesc methodType();
+
+    /**
+     * Constant bootstrap method for representing a {@linkplain DirectMethodHandleDesc} in
+     * the constant pool of a classfile.
+     *
+     * @param lookup ignored
+     * @param name ignored
+     * @param clazz ignored
+     * @param bsmKindName The name of an {@code enum} constant from {@link Kind}
+     * @param memberOwner A field type descriptor for the class declaring the
+     *                 method, field, or constructor, as per JVMS 4.3.2
+     * @param memberName The name of the method or field, as per JVMS 4.2.2
+     * @param memberType A method type descriptor for the method handle being
+     *                described, as per JVMS 4.3.3
+     * @return the {@linkplain MethodHandleDesc}
+     * @jvms 4.2.2 Unqualified Names
+     * @jvms 4.3.2 Field Descriptors
+     * @jvms 4.3.3 Method Descriptors
+     */
+    static DirectMethodHandleDesc constantBootstrap(MethodHandles.Lookup lookup, String name, Class<ClassDesc> clazz,
+                                                    String bsmKindName, String memberOwner, String memberName, String memberType) {
+        return MethodHandleDesc.of(Kind.valueOf(bsmKindName),
+                                   ClassDesc.ofDescriptor(memberOwner), memberName,
+                                   MethodTypeDesc.ofDescriptor(memberType));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/constant/DirectMethodHandleDescImpl.java	Thu Jun 14 13:27:14 2018 -0700
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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 java.lang.constant;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.Objects;
+import java.util.Optional;
+
+import static java.lang.constant.ConstantDescs.BSM_METHODHANDLEDESC;
+import static java.lang.constant.ConstantDescs.CR_DirectMethodHandleDesc;
+import static java.lang.constant.ConstantUtils.validateClassOrInterface;
+import static java.lang.constant.ConstantUtils.validateMemberName;
+import static java.lang.constant.DirectMethodHandleDesc.Kind.CONSTRUCTOR;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * A <a href="package-summary.html#nominal">nominal descriptor</a> for a direct
+ * {@link MethodHandle}.  A {@linkplain DirectMethodHandleDescImpl} corresponds to
+ * a {@code Constant_MethodHandle_info} entry in the constant pool of a classfile.
+ */
+final class DirectMethodHandleDescImpl implements DirectMethodHandleDesc {
+
+    private final Kind kind;
+    private final ClassDesc owner;
+    private final String name;
+    private final MethodTypeDesc type;
+
+    /**
+     * Construct a {@linkplain DirectMethodHandleDescImpl} for a method or field
+     * from a kind, owner, name, and type
+     *
+     * @param kind the kind of the method handle
+     * @param owner the declaring class or interface for the method
+     * @param name the name of the method (ignored if {@code kind} is
+     * {@code CONSTRUCTOR}), as per JVMS 4.2.2
+     * @param type the type of the method
+     * @throws NullPointerException if any non-ignored argument is null
+     * @throws IllegalArgumentException if {@code kind} describes a field accessor,
+     * and {@code type} is not consistent with that kind of field accessor, or if
+     * {@code kind} describes a constructor, and the return type of {@code type}
+     * is not {@code void}
+     * @jvms 4.2.2 Unqualified Names
+     */
+    DirectMethodHandleDescImpl(Kind kind, ClassDesc owner, String name, MethodTypeDesc type) {
+        if (kind == CONSTRUCTOR)
+            name = "<init>";
+
+        requireNonNull(kind);
+        validateClassOrInterface(requireNonNull(owner));
+        validateMemberName(requireNonNull(name));
+        requireNonNull(type);
+
+        switch (kind) {
+            case CONSTRUCTOR: validateConstructor(type); break;
+            case GETTER: validateFieldType(type, false, true); break;
+            case SETTER: validateFieldType(type, true, true); break;
+            case STATIC_GETTER: validateFieldType(type, false, false); break;
+            case STATIC_SETTER: validateFieldType(type, true, false); break;
+        }
+
+        this.kind = kind;
+        this.owner = owner;
+        this.name = name;
+        this.type = type;
+    }
+
+    private static void validateFieldType(MethodTypeDesc type, boolean isSetter, boolean isVirtual) {
+        boolean isVoid = type.returnType().descriptorString().equals("V");
+        int expectedParams = (isSetter ? 1 : 0) + (isVirtual ? 1 : 0);
+        if (isVoid != isSetter
+            || type.parameterCount() != expectedParams
+            || (isVirtual && type.parameterType(0).isPrimitive())) {
+            String expectedType = String.format("(%s%s)%s", (isVirtual ? "R" : ""),
+                                                (isSetter ? "T" : ""), (isSetter ? "V" : "T"));
+            throw new IllegalArgumentException(String.format("Expected type of %s for getter, found %s", expectedType, type));
+        }
+    }
+
+    private static void validateConstructor(MethodTypeDesc type) {
+        if (!type.returnType().descriptorString().equals("V")) {
+            throw new IllegalArgumentException(String.format("Expected type of (T*)V for constructor, found %s", type));
+        }
+    }
+
+    @Override
+    public Kind kind() { return kind; }
+
+    @Override
+    public int refKind() { return kind.refKind; }
+
+    @Override
+    public boolean isOwnerInterface() { return kind.isInterface; }
+
+    @Override
+    public ClassDesc owner() {
+        return owner;
+    }
+
+    @Override
+    public String methodName() {
+        return name;
+    }
+
+    @Override
+    public MethodTypeDesc methodType() {
+        return type;
+    }
+
+    public MethodHandle resolveConstantDesc(MethodHandles.Lookup lookup)
+            throws ReflectiveOperationException {
+        Class<?> resolvedOwner = owner.resolveConstantDesc(lookup);
+        MethodType resolvedType = this.type.resolveConstantDesc(lookup);
+        switch (kind) {
+            case STATIC:
+            case INTERFACE_STATIC:
+                return lookup.findStatic(resolvedOwner, name, resolvedType);
+            case INTERFACE_VIRTUAL:
+            case VIRTUAL:
+                return lookup.findVirtual(resolvedOwner, name, resolvedType);
+            case SPECIAL:
+            case INTERFACE_SPECIAL:
+                return lookup.findSpecial(resolvedOwner, name, resolvedType, lookup.lookupClass());
+            case CONSTRUCTOR:
+                return lookup.findConstructor(resolvedOwner, resolvedType);
+            case GETTER:
+                return lookup.findGetter(resolvedOwner, name, resolvedType.returnType());
+            case STATIC_GETTER:
+                return lookup.findStaticGetter(resolvedOwner, name, resolvedType.returnType());
+            case SETTER:
+                return lookup.findSetter(resolvedOwner, name, resolvedType.parameterType(1));
+            case STATIC_SETTER:
+                return lookup.findStaticSetter(resolvedOwner, name, resolvedType.parameterType(0));
+            default:
+                throw new IllegalStateException(kind.name());
+        }
+    }
+
+    @Override
+    public Optional<? extends ConstantDesc<ConstantDesc<MethodHandle>>> describeConstable() {
+        return Optional.of(DynamicConstantDesc.<ConstantDesc<MethodHandle>>of(BSM_METHODHANDLEDESC, CR_DirectMethodHandleDesc)
+                                              .withArgs(kind.toString(), owner.descriptorString(), name, type.descriptorString()));
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        DirectMethodHandleDescImpl desc = (DirectMethodHandleDescImpl) o;
+        return kind == desc.kind &&
+               Objects.equals(owner, desc.owner) &&
+               Objects.equals(name, desc.name) &&
+               Objects.equals(type, desc.type);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(kind, owner, name, type);
+    }
+
+    @Override
+    public String toString() {
+        return String.format("MethodHandleDesc[%s/%s::%s%s]", kind, owner.displayName(), name, type.displayDescriptor());
+    }
+}
--- a/src/java.base/share/classes/java/lang/constant/DynamicCallSiteDesc.java	Fri Jun 08 15:38:32 2018 -0700
+++ b/src/java.base/share/classes/java/lang/constant/DynamicCallSiteDesc.java	Thu Jun 14 13:27:14 2018 -0700
@@ -48,7 +48,7 @@
  */
 public class DynamicCallSiteDesc {
 
-    private final ConstantMethodHandleDesc bootstrapMethod;
+    private final DirectMethodHandleDesc bootstrapMethod;
     private final ConstantDesc<?>[] bootstrapArgs;
     private final String invocationName;
     private final MethodTypeDesc invocationType;
@@ -56,7 +56,7 @@
     /**
      * Create a nominal descriptor for an {@code invokedynamic} call site.
      *
-     * @param bootstrapMethod a {@link ConstantMethodHandleDesc} describing the
+     * @param bootstrapMethod a {@link DirectMethodHandleDescImpl} describing the
      *                        bootstrap method for the {@code invokedynamic}
      * @param invocationName The name that would appear in the {@code NameAndType}
      *                       operand of the {@code invokedynamic}, as per
@@ -72,7 +72,7 @@
      * format
      * @jvms 4.2.2 Unqualified Names
      */
-    private DynamicCallSiteDesc(ConstantMethodHandleDesc bootstrapMethod,
+    private DynamicCallSiteDesc(DirectMethodHandleDesc bootstrapMethod,
                                 String invocationName,
                                 MethodTypeDesc invocationType,
                                 ConstantDesc<?>[] bootstrapArgs) {
@@ -87,7 +87,7 @@
     /**
      * Create a nominal descriptor for an {@code invokedynamic} call site.
      *
-     * @param bootstrapMethod a {@link ConstantMethodHandleDesc} describing the
+     * @param bootstrapMethod a {@link DirectMethodHandleDescImpl} describing the
      *                        bootstrap method for the {@code invokedynamic}
      * @param invocationName The name that would appear in the {@code NameAndType}
      *                       operand of the {@code invokedynamic}, as per
@@ -105,7 +105,7 @@
      * @jvms 4.2.2 Unqualified Names
      */
     @Foldable
-    public static DynamicCallSiteDesc of(ConstantMethodHandleDesc bootstrapMethod,
+    public static DynamicCallSiteDesc of(DirectMethodHandleDesc bootstrapMethod,
                                          String invocationName,
                                          MethodTypeDesc invocationType,
                                          ConstantDesc<?>... bootstrapArgs) {
@@ -125,7 +125,7 @@
      * @throws NullPointerException if any parameter is null
      */
     @Foldable
-    public static DynamicCallSiteDesc of(ConstantMethodHandleDesc bootstrapMethod,
+    public static DynamicCallSiteDesc of(DirectMethodHandleDesc bootstrapMethod,
                                          String invocationName,
                                          MethodTypeDesc invocationType) {
         return new DynamicCallSiteDesc(bootstrapMethod, invocationName, invocationType, EMPTY_CONSTANTDESC);
@@ -136,7 +136,7 @@
      * bootstrap method has no static arguments and for which the name parameter
      * is {@link ConstantDescs#DEFAULT_NAME}.
      *
-     * @param bootstrapMethod a {@link ConstantMethodHandleDesc} describing the
+     * @param bootstrapMethod a {@link DirectMethodHandleDescImpl} describing the
      *                        bootstrap method for the {@code invokedynamic}
      * @param invocationType a {@link MethodTypeDesc} describing the invocation
      *                       type that would appear in the {@code NameAndType}
@@ -147,7 +147,7 @@
      * format
      */
     @Foldable
-    public static DynamicCallSiteDesc of(ConstantMethodHandleDesc bootstrapMethod,
+    public static DynamicCallSiteDesc of(DirectMethodHandleDesc bootstrapMethod,
                                          MethodTypeDesc invocationType) {
         return of(bootstrapMethod, ConstantDescs.DEFAULT_NAME, invocationType);
     }
--- a/src/java.base/share/classes/java/lang/constant/DynamicConstantDesc.java	Fri Jun 08 15:38:32 2018 -0700
+++ b/src/java.base/share/classes/java/lang/constant/DynamicConstantDesc.java	Thu Jun 14 13:27:14 2018 -0700
@@ -60,7 +60,7 @@
 public abstract class DynamicConstantDesc<T>
         implements ConstantDesc<T>, Constable<ConstantDesc<T>> {
 
-    private final ConstantMethodHandleDesc bootstrapMethod;
+    private final DirectMethodHandleDesc bootstrapMethod;
     private final ConstantDesc<?>[] bootstrapArgs;
     private final String constantName;
     private final ClassDesc constantType;
@@ -77,12 +77,12 @@
     /**
      * Create a nominal descriptor for a dynamic constant.
      *
-     * @param bootstrapMethod a {@link ConstantMethodHandleDesc} describing the
+     * @param bootstrapMethod a {@link DirectMethodHandleDescImpl} describing the
      *                        bootstrap method for the constant
      * @param constantName The name that would appear in the {@code NameAndType}
      *                     operand of the {@code LDC} for this constant, as per
      *                     JVMS 4.2.2
-     * @param constantType a {@link ConstantMethodHandleDesc} describing the type
+     * @param constantType a {@link DirectMethodHandleDescImpl} describing the type
      *                     that would appear in the {@code NameAndType} operand
      *                     of the {@code LDC} for this constant
      * @param bootstrapArgs {@link ConstantDesc}s describing the static arguments
@@ -93,7 +93,7 @@
      * format
      * @jvms 4.2.2 Unqualified Names
      */
-    protected DynamicConstantDesc(ConstantMethodHandleDesc bootstrapMethod,
+    protected DynamicConstantDesc(DirectMethodHandleDesc bootstrapMethod,
                                   String constantName,
                                   ClassDesc constantType,
                                   ConstantDesc<?>... bootstrapArgs) {
@@ -134,17 +134,17 @@
      *
      * <p>Bytecode-reading APIs that process the constant pool and wish to expose
      * entries as {@link ConstantDesc} to their callers should generally use this
-     * method in preference to {@link #of(ConstantMethodHandleDesc, String, ClassDesc, ConstantDesc[])}
+     * method in preference to {@link #of(DirectMethodHandleDesc, String, ClassDesc, ConstantDesc[])}
      * because this may result in a more specific type that can be provided to
      * callers.
      *
      * @param <T> the type of the dynamic constant
-     * @param bootstrapMethod a {@link ConstantMethodHandleDesc} describing the
+     * @param bootstrapMethod a {@link DirectMethodHandleDescImpl} describing the
      *                        bootstrap method for the constant
      * @param constantName The name that would appear in the {@code NameAndType}
      *                     operand of the {@code LDC} for this constant, as per
      *                     JVMS 4.2.2
-     * @param constantType a {@link ConstantMethodHandleDesc} describing the type
+     * @param constantType a {@link DirectMethodHandleDescImpl} describing the type
      *                     that would appear in the {@code NameAndType} operand
      *                     of the {@code LDC} for this constant
      * @param bootstrapArgs {@link ConstantDesc}s describing the static arguments
@@ -157,7 +157,7 @@
      * @jvms 4.2.2 Unqualified Names
      */
     @Foldable
-    public static<T> ConstantDesc<T> ofCanonical(ConstantMethodHandleDesc bootstrapMethod,
+    public static<T> ConstantDesc<T> ofCanonical(DirectMethodHandleDesc bootstrapMethod,
                                                  String constantName,
                                                  ClassDesc constantType,
                                                  ConstantDesc<?>[] bootstrapArgs) {
@@ -169,12 +169,12 @@
      * Return a nominal descriptor for a dynamic constant.
      *
      * @param <T> the type of the dynamic constant
-     * @param bootstrapMethod a {@link ConstantMethodHandleDesc} describing the
+     * @param bootstrapMethod a {@link DirectMethodHandleDescImpl} describing the
      *                        bootstrap method for the constant
      * @param constantName The name that would appear in the {@code NameAndType}
      *                     operand of the {@code LDC} for this constant, as per
      *                     JVMS 4.2.2
-     * @param constantType a {@link ConstantMethodHandleDesc} describing the type
+     * @param constantType a {@link DirectMethodHandleDescImpl} describing the type
      *                     that would appear in the {@code NameAndType} operand
      *                     of the {@code LDC} for this constant
      * @param bootstrapArgs {@link ConstantDesc}s describing the static arguments
@@ -187,7 +187,7 @@
      * @jvms 4.2.2 Unqualified Names
      */
     @Foldable
-    public static<T> DynamicConstantDesc<T> of(ConstantMethodHandleDesc bootstrapMethod,
+    public static<T> DynamicConstantDesc<T> of(DirectMethodHandleDesc bootstrapMethod,
                                                String constantName,
                                                ClassDesc constantType,
                                                ConstantDesc<?>[] bootstrapArgs) {
@@ -199,12 +199,12 @@
      * no static arguments.
      *
      * @param <T> the type of the dynamic constant
-     * @param bootstrapMethod a {@link ConstantMethodHandleDesc} describing the
+     * @param bootstrapMethod a {@link DirectMethodHandleDescImpl} describing the
      *                        bootstrap method for the constant
      * @param constantName The name that would appear in the {@code NameAndType}
      *                     operand of the {@code LDC} for this constant, as per
      *                     JVMS 4.2.2
-     * @param constantType a {@link ConstantMethodHandleDesc} describing the type
+     * @param constantType a {@link DirectMethodHandleDescImpl} describing the type
      *                     that would appear in the {@code NameAndType} operand
      *                     of the {@code LDC} for this constant
      * @return the nominal descriptor
@@ -214,7 +214,7 @@
      * @jvms 4.2.2 Unqualified Names
      */
     @Foldable
-    public static<T> DynamicConstantDesc<T> of(ConstantMethodHandleDesc bootstrapMethod,
+    public static<T> DynamicConstantDesc<T> of(DirectMethodHandleDesc bootstrapMethod,
                                                String constantName,
                                                ClassDesc constantType) {
         return DynamicConstantDesc.of(bootstrapMethod, constantName, constantType, ConstantUtils.EMPTY_CONSTANTDESC);
@@ -226,16 +226,16 @@
      * is {@link ConstantDescs#DEFAULT_NAME}.
      *
      * @param <T> the type of the dynamic constant
-     * @param bootstrapMethod a {@link ConstantMethodHandleDesc} describing the
+     * @param bootstrapMethod a {@link DirectMethodHandleDescImpl} describing the
      *                        bootstrap method for the constant
-     * @param constantType a {@link ConstantMethodHandleDesc} describing the type
+     * @param constantType a {@link DirectMethodHandleDescImpl} describing the type
      *                     that would appear in the {@code NameAndType} operand
      *                     of the {@code LDC} for this constant
      * @return the nominal descriptor
      * @throws NullPointerException if any argument is null
      */
     @Foldable
-    public static<T> DynamicConstantDesc<T> of(ConstantMethodHandleDesc bootstrapMethod,
+    public static<T> DynamicConstantDesc<T> of(DirectMethodHandleDesc bootstrapMethod,
                                                ClassDesc constantType) {
         return of(bootstrapMethod, ConstantDescs.DEFAULT_NAME, constantType);
     }
@@ -246,7 +246,7 @@
      * bootstrap method return type.
      *
      * @param <T> the type of the dynamic constant
-     * @param bootstrapMethod a {@link ConstantMethodHandleDesc} describing the
+     * @param bootstrapMethod a {@link DirectMethodHandleDescImpl} describing the
      *                        bootstrap method for the constant
      * @param constantName The name that would appear in the {@code NameAndType}
      *                     operand of the {@code LDC} for this constant, as per
@@ -258,7 +258,7 @@
      * @jvms 4.2.2 Unqualified Names
      */
     @Foldable
-    public static<T> DynamicConstantDesc<T> of(ConstantMethodHandleDesc bootstrapMethod,
+    public static<T> DynamicConstantDesc<T> of(DirectMethodHandleDesc bootstrapMethod,
                                                String constantName) {
         return of(bootstrapMethod, constantName, bootstrapMethod.methodType().returnType());
     }
@@ -269,7 +269,7 @@
      * and whose type parameter is always the same as the bootstrap method return type.
      *
      * @param <T> the type of the dynamic constant
-     * @param bootstrapMethod a {@link ConstantMethodHandleDesc} describing the
+     * @param bootstrapMethod a {@link DirectMethodHandleDescImpl} describing the
      *                        bootstrap method for the constant
      * @return the nominal descriptor
      * @throws NullPointerException if any argument is null
@@ -277,7 +277,7 @@
      * format
      */
     @Foldable
-    public static<T> DynamicConstantDesc<T> of(ConstantMethodHandleDesc bootstrapMethod) {
+    public static<T> DynamicConstantDesc<T> of(DirectMethodHandleDesc bootstrapMethod) {
         return of(bootstrapMethod, ConstantDescs.DEFAULT_NAME);
     }
 
@@ -310,7 +310,7 @@
      * @return the bootstrap method
      */
     @Foldable
-    public ConstantMethodHandleDesc bootstrapMethod() {
+    public DirectMethodHandleDesc bootstrapMethod() {
         return bootstrapMethod;
     }
 
@@ -396,7 +396,7 @@
                                                            String bsmOwner, String bsmName, String bsmDesc,
                                                            String constantName, String constantType,
                                                            ConstantDesc<?>... args) {
-        return DynamicConstantDesc.of(MethodHandleDesc.of(MethodHandleDesc.Kind.STATIC,
+        return DynamicConstantDesc.of(MethodHandleDesc.of(DirectMethodHandleDesc.Kind.STATIC,
                                                           ClassDesc.ofDescriptor(bsmOwner), bsmName,
                                                           MethodTypeDesc.ofDescriptor(bsmDesc)),
                                       constantName, ClassDesc.ofDescriptor(constantType), args);
--- a/src/java.base/share/classes/java/lang/constant/MethodHandleDesc.java	Fri Jun 08 15:38:32 2018 -0700
+++ b/src/java.base/share/classes/java/lang/constant/MethodHandleDesc.java	Thu Jun 14 13:27:14 2018 -0700
@@ -25,70 +25,24 @@
 package java.lang.constant;
 
 import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandleInfo;
 import java.lang.invoke.MethodType;
 
 import jdk.internal.lang.annotation.Foldable;
 
-import static java.lang.invoke.MethodHandleInfo.REF_getField;
-import static java.lang.invoke.MethodHandleInfo.REF_getStatic;
-import static java.lang.invoke.MethodHandleInfo.REF_invokeInterface;
-import static java.lang.invoke.MethodHandleInfo.REF_invokeSpecial;
-import static java.lang.invoke.MethodHandleInfo.REF_invokeStatic;
-import static java.lang.invoke.MethodHandleInfo.REF_invokeVirtual;
-import static java.lang.invoke.MethodHandleInfo.REF_newInvokeSpecial;
-import static java.lang.invoke.MethodHandleInfo.REF_putField;
-import static java.lang.invoke.MethodHandleInfo.REF_putStatic;
 import static java.lang.constant.ConstantDescs.CR_void;
-import static java.lang.constant.MethodHandleDesc.Kind.CONSTRUCTOR;
+import static java.lang.constant.DirectMethodHandleDesc.Kind.CONSTRUCTOR;
 
 /**
  * A <a href="package-summary.html#nominal">nominal descriptor</a> for a
  * {@link MethodHandle} constant.
+ *
+ * @apiNote In the future, if the Java language permits, {@linkplain MethodHandleDesc}
+ * may become a {@code sealed} interface, which would prohibit subclassing except
+ * by explicitly permitted types.  Non-platform classes should not implement
+ * {@linkplain MethodHandleDesc} directly.
  */
 public interface MethodHandleDesc
         extends ConstantDesc<MethodHandle>, Constable<ConstantDesc<MethodHandle>> {
-    /**
-     * Kinds of method handles that can be described with {@linkplain MethodHandleDesc}.
-     */
-    public enum Kind {
-        /** A method handle for a method invoked as with {@code invokestatic} */
-        @Foldable STATIC(REF_invokeStatic),
-        /** A method handle for a method invoked as with {@code invokestatic} */
-        @Foldable INTERFACE_STATIC(REF_invokeStatic, true),
-        /** A method handle for a method invoked as with {@code invokevirtual} */
-        @Foldable VIRTUAL(REF_invokeVirtual),
-        /** A method handle for a method invoked as with {@code invokeinterface} */
-        @Foldable INTERFACE_VIRTUAL(REF_invokeInterface, true),
-        /** A method handle for a method invoked as with {@code invokespecial} */
-        @Foldable SPECIAL(REF_invokeSpecial),
-        /** A method handle for an interface method invoked as with {@code invokespecial} */
-        @Foldable INTERFACE_SPECIAL(REF_invokeSpecial, true),
-        /** A method handle for a constructor */
-        @Foldable CONSTRUCTOR(REF_newInvokeSpecial),
-        /** A method handle for a read accessor for an instance field  */
-        @Foldable GETTER(REF_getField),
-        /** A method handle for a write accessor for an instance field  */
-        @Foldable SETTER(REF_putField),
-        /** A method handle for a read accessor for a static field  */
-        @Foldable STATIC_GETTER(REF_getStatic),
-        /** A method handle for a write accessor for a static field  */
-        @Foldable STATIC_SETTER(REF_putStatic);
-
-        /** The corresponding {@code refKind} value for this kind of method handle,
-         * as defined by {@link MethodHandleInfo}
-         */
-        public final int refKind;
-        /** Is this an interface
-         */
-        public final boolean isInterface;
-
-        Kind(int refKind) {
-            this(refKind, false);
-        }
-        Kind(int refKind, boolean isInterface) { this.refKind = refKind; this.isInterface = isInterface; }
-    }
-
 
     /**
      * Create a {@linkplain MethodHandleDesc} corresponding to an invocation of a
@@ -101,7 +55,7 @@
      * take a leading receiver parameter, getters must return the type of the
      * field, setters must take a new value for the field and return {@code void}.
      *
-     * <p>For constructor and field access, the methods {@link #ofField(Kind, ClassDesc, String, ClassDesc)}
+     * <p>For constructor and field access, the methods {@link #ofField(DirectMethodHandleDesc.Kind, ClassDesc, String, ClassDesc)}
      * and {@link #ofConstructor(ClassDesc, ClassDesc...)} may be more convenient.
      *
      * @param kind The kind of method handle to be described
@@ -117,12 +71,11 @@
      * format
      * @jvms 4.2.2 Unqualified Names
      */
-    @Foldable
-    static ConstantMethodHandleDesc of(Kind kind,
-                                       ClassDesc clazz,
-                                       String name,
-                                       MethodTypeDesc type) {
-        return new ConstantMethodHandleDesc(kind, clazz, name, type);
+    static DirectMethodHandleDesc of(DirectMethodHandleDesc.Kind kind,
+                                     ClassDesc clazz,
+                                     String name,
+                                     MethodTypeDesc type) {
+        return new DirectMethodHandleDescImpl(kind, clazz, name, type);
     }
 
     /**
@@ -135,7 +88,7 @@
      * of field access and the type of the field; instance field accessors must
      * take a leading receiver parameter, getters must return the type of the
      * field, setters must take a new value for the field and return {@code void}.
-     * The method {@link #ofField(Kind, ClassDesc, String, ClassDesc)} will construct
+     * The method {@link #ofField(DirectMethodHandleDesc.Kind, ClassDesc, String, ClassDesc)} will construct
      * the appropriate invocation given the type of the field.
      *
      * @param kind The kind of method handle to be described
@@ -151,10 +104,10 @@
      * @jvms 4.3.3 Method Descriptors
      */
     @Foldable
-    static ConstantMethodHandleDesc of(Kind kind,
-                                       ClassDesc clazz,
-                                       String name,
-                                       String descriptorString) {
+    static DirectMethodHandleDesc of(DirectMethodHandleDesc.Kind kind,
+                                     ClassDesc clazz,
+                                     String name,
+                                     String descriptorString) {
         return of(kind, clazz, name, MethodTypeDesc.ofDescriptor(descriptorString));
     }
 
@@ -168,7 +121,7 @@
      * of field access and the type of the field; instance field accessors must
      * take a leading receiver parameter, getters must return the type of the
      * field, setters must take a new value for the field and return {@code void}.
-     * The method {@link #ofField(Kind, ClassDesc, String, ClassDesc)} will construct
+     * The method {@link #ofField(DirectMethodHandleDesc.Kind, ClassDesc, String, ClassDesc)} will construct
      * the appropriate invocation given the type of the field.
      *
      * @param kind The kind of method handle to be described
@@ -185,11 +138,11 @@
      * @jvms 4.2.2 Unqualified Names
      */
     @Foldable
-    static ConstantMethodHandleDesc of(Kind kind,
-                                       ClassDesc clazz,
-                                       String name,
-                                       ClassDesc returnType,
-                                       ClassDesc... paramTypes) {
+    static DirectMethodHandleDesc of(DirectMethodHandleDesc.Kind kind,
+                                     ClassDesc clazz,
+                                     String name,
+                                     ClassDesc returnType,
+                                     ClassDesc... paramTypes) {
         return of(kind, clazz, name, MethodTypeDesc.of(returnType, paramTypes));
     }
 
@@ -208,10 +161,10 @@
      * @jvms 4.2.2 Unqualified Names
      */
     @Foldable
-    static ConstantMethodHandleDesc ofField(Kind kind,
-                                            ClassDesc clazz,
-                                            String fieldName,
-                                            ClassDesc fieldType) {
+    static DirectMethodHandleDesc ofField(DirectMethodHandleDesc.Kind kind,
+                                          ClassDesc clazz,
+                                          String fieldName,
+                                          ClassDesc fieldType) {
         MethodTypeDesc mtr;
         switch (kind) {
             case GETTER: mtr = MethodTypeDesc.of(fieldType, clazz); break;
@@ -235,8 +188,8 @@
      * @throws NullPointerException if any of the arguments are null
      */
     @Foldable
-    static ConstantMethodHandleDesc ofConstructor(ClassDesc clazz,
-                                                  ClassDesc... paramTypes) {
+    static DirectMethodHandleDesc ofConstructor(ClassDesc clazz,
+                                                ClassDesc... paramTypes) {
         return MethodHandleDesc.of(CONSTRUCTOR, clazz, ConstantDescs.DEFAULT_NAME,
                                    MethodTypeDesc.of(CR_void, paramTypes));
     }
--- a/src/java.base/share/classes/java/lang/constant/MethodTypeDesc.java	Fri Jun 08 15:38:32 2018 -0700
+++ b/src/java.base/share/classes/java/lang/constant/MethodTypeDesc.java	Thu Jun 14 13:27:14 2018 -0700
@@ -26,6 +26,7 @@
 
 import jdk.internal.lang.annotation.Foldable;
 
+import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
 import java.lang.invoke.MethodTypeDescriptor;
 import java.util.List;
@@ -37,6 +38,11 @@
 /**
  * A <a href="package-summary.html#nominal">nominal descriptor</a> for a
  * {@linkplain MethodType} constant.
+ *
+ * @apiNote In the future, if the Java language permits, {@linkplain MethodTypeDesc}
+ * may become a {@code sealed} interface, which would prohibit subclassing except
+ * by explicitly permitted types.  Non-platform classes should not implement
+ * {@linkplain MethodTypeDesc} directly.
  */
 public interface MethodTypeDesc
         extends ConstantDesc<MethodType>,
@@ -54,7 +60,7 @@
      */
     @Foldable
     static MethodTypeDesc ofDescriptor(String descriptor) {
-        return ConstantMethodTypeDesc.ofDescriptor(descriptor);
+        return MethodTypeDescImpl.ofDescriptor(descriptor);
     }
 
     /**
@@ -68,7 +74,7 @@
      */
     @Foldable
     static MethodTypeDesc of(ClassDesc returnDesc, ClassDesc... paramDescs) {
-        return new ConstantMethodTypeDesc(returnDesc, paramDescs);
+        return new MethodTypeDescImpl(returnDesc, paramDescs);
     }
 
     /**
@@ -194,4 +200,20 @@
                                    .collect(Collectors.joining(",")),
                              returnType().displayName());
     }
+
+    /**
+     * Constant bootstrap method for representing a {@linkplain MethodTypeDesc} in
+     * the constant pool of a classfile.
+     *
+     * @param lookup ignored
+     * @param name ignored
+     * @param clazz ignored
+     * @param descriptor a method descriptor string for the method type, as per JVMS 4.3.3
+     * @return the {@linkplain MethodTypeDesc}
+     * @jvms 4.3.3 Method Descriptors
+     */
+    static MethodTypeDesc constantBootstrap(MethodHandles.Lookup lookup, String name, Class<ClassDesc> clazz,
+                                            String descriptor) {
+        return MethodTypeDesc.ofDescriptor(descriptor);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/constant/MethodTypeDescImpl.java	Thu Jun 14 13:27:14 2018 -0700
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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 java.lang.constant;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+
+import jdk.internal.lang.annotation.Foldable;
+
+import static java.lang.constant.ConstantDescs.BSM_METHODTYPEDESC;
+import static java.lang.constant.ConstantDescs.CR_MethodTypeDesc;
+import static java.lang.constant.ConstantDescs.DEFAULT_NAME;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * A <a href="package-summary.html#nominal">nominal descriptor</a> for a
+ * {@link MethodType}.  A {@linkplain MethodTypeDescImpl} corresponds to a
+ * {@code Constant_MethodType_info} entry in the constant pool of a classfile.
+ */
+final class MethodTypeDescImpl implements MethodTypeDesc {
+    private final ClassDesc returnType;
+    private final ClassDesc[] argTypes;
+
+    /**
+     * Construct a {@linkplain MethodTypeDesc} with the specified return type
+     * and parameter types
+     *
+     * @param returnType a {@link ClassDesc} describing the return type
+     * @param argTypes {@link ClassDesc}s describing the parameter types
+     */
+    MethodTypeDescImpl(ClassDesc returnType, ClassDesc[] argTypes) {
+        this.returnType = requireNonNull(returnType);
+        this.argTypes = requireNonNull(argTypes);
+
+        for (ClassDesc cr : argTypes)
+            if (cr.isPrimitive() && cr.descriptorString().equals("V"))
+                throw new IllegalArgumentException("Void parameters not permitted");
+    }
+
+    /**
+     * Create a {@linkplain MethodTypeDescImpl} given a method descriptor string.
+     *
+     * @param descriptor the method descriptor string, as per JVMS 4.3.3
+     * @return a {@linkplain MethodTypeDescImpl} describing the desired method type
+     * @throws IllegalArgumentException if the descriptor string is not a valid
+     * method descriptor
+     * @jvms 4.3.3 Method Descriptors
+     */
+    @Foldable
+    static MethodTypeDescImpl ofDescriptor(String descriptor) {
+        requireNonNull(descriptor);
+        List<String> types = ConstantUtils.parseMethodDescriptor(descriptor);
+        ClassDesc[] paramTypes = types.stream().skip(1).map(ClassDesc::ofDescriptor).toArray(ClassDesc[]::new);
+        return new MethodTypeDescImpl(ClassDesc.ofDescriptor(types.get(0)), paramTypes);
+    }
+
+    @Foldable
+    @Override
+    public ClassDesc returnType() {
+        return returnType;
+    }
+
+    @Foldable
+    @Override
+    public int parameterCount() {
+        return argTypes.length;
+    }
+
+    @Foldable
+    @Override
+    public ClassDesc parameterType(int index) {
+        return argTypes[index];
+    }
+
+    @Override
+    public List<ClassDesc> parameterList() {
+        return List.of(argTypes);
+    }
+
+    @Override
+    public ClassDesc[] parameterArray() {
+        return argTypes.clone();
+    }
+
+    @Foldable
+    @Override
+    public MethodTypeDesc changeReturnType(ClassDesc returnType) {
+        return MethodTypeDesc.of(returnType, argTypes);
+    }
+
+    @Foldable
+    @Override
+    public MethodTypeDesc changeParameterType(int index, ClassDesc paramType) {
+        ClassDesc[] newArgs = argTypes.clone();
+        newArgs[index] = paramType;
+        return MethodTypeDesc.of(returnType, newArgs);
+    }
+
+    @Foldable
+    @Override
+    public MethodTypeDesc dropParameterTypes(int start, int end) {
+        if (start < 0 || start >= argTypes.length || end < 0 || end > argTypes.length)
+            throw new IndexOutOfBoundsException();
+        else if (start > end)
+            throw new IllegalArgumentException(String.format("Range (%d, %d) not valid for size %d", start, end, argTypes.length));
+        ClassDesc[] newArgs = new ClassDesc[argTypes.length - (end - start)];
+        System.arraycopy(argTypes, 0, newArgs, 0, start);
+        System.arraycopy(argTypes, end, newArgs, start, argTypes.length - end);
+        return MethodTypeDesc.of(returnType, newArgs);
+    }
+
+    @Foldable
+    @Override
+    public MethodTypeDesc insertParameterTypes(int pos, ClassDesc... paramTypes) {
+        if (pos < 0 || pos > argTypes.length)
+            throw new IndexOutOfBoundsException(pos);
+        ClassDesc[] newArgs = new ClassDesc[argTypes.length + paramTypes.length];
+        System.arraycopy(argTypes, 0, newArgs, 0, pos);
+        System.arraycopy(paramTypes, 0, newArgs, pos, paramTypes.length);
+        System.arraycopy(argTypes, pos, newArgs, pos+paramTypes.length, argTypes.length - pos);
+        return MethodTypeDesc.of(returnType, newArgs);
+    }
+
+    @Override
+    public MethodType resolveConstantDesc(MethodHandles.Lookup lookup) {
+        return MethodType.fromMethodDescriptorString(descriptorString(), lookup.lookupClass().getClassLoader());
+    }
+
+    @Override
+    public Optional<? extends ConstantDesc<ConstantDesc<MethodType>>> describeConstable() {
+        return Optional.of(DynamicConstantDesc.of(BSM_METHODTYPEDESC, DEFAULT_NAME, CR_MethodTypeDesc,
+                                                  new ConstantDesc<?>[] { descriptorString() }));
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        MethodTypeDescImpl constant = (MethodTypeDescImpl) o;
+
+        return returnType.equals(constant.returnType)
+               && Arrays.equals(argTypes, constant.argTypes);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = returnType.hashCode();
+        result = 31 * result + Arrays.hashCode(argTypes);
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("MethodTypeDesc[%s]", displayDescriptor());
+    }
+}
--- a/src/java.base/share/classes/java/lang/constant/PrimitiveClassDesc.java	Fri Jun 08 15:38:32 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  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 java.lang.constant;
-
-import java.lang.invoke.MethodHandles;
-import java.util.Optional;
-
-import sun.invoke.util.Wrapper;
-
-import static java.util.Objects.requireNonNull;
-
-/**
- * A <a href="package-summary.html#nominal">nominal descriptor</a> for the class
- * constant corresponding to a primitive type (e.g., {@code int.class}).
- */
-final class PrimitiveClassDesc
-        extends DynamicConstantDesc<Class<?>> implements ClassDesc {
-
-    private final String descriptor;
-
-    /**
-     * Create a {@linkplain ClassDesc} given a descriptor string for a primitive
-     * type.
-     *
-     * @param descriptor the descriptor string, which must be a one-character
-     * string corresponding to one of the nine base types as per JVMS 4.3
-     * @throws IllegalArgumentException if the descriptor string does not
-     * describe a valid primitive type
-     * @jvms 4.3 Descriptors
-     */
-    PrimitiveClassDesc(String descriptor) {
-        super(ConstantDescs.BSM_PRIMITIVE_CLASS, requireNonNull(descriptor), ConstantDescs.CR_Class);
-        if (descriptor.length() != 1
-            || "VIJCSBFDZ".indexOf(descriptor.charAt(0)) < 0)
-            throw new IllegalArgumentException(String.format("not a valid primitive type descriptor: %s", descriptor));
-        this.descriptor = descriptor;
-    }
-
-    @Override
-    public String descriptorString() {
-        return descriptor;
-    }
-
-    @Override
-    public Class<?> resolveConstantDesc(MethodHandles.Lookup lookup) {
-        return Wrapper.forBasicType(descriptorString().charAt(0)).primitiveType();
-    }
-
-    @Override
-    public Optional<? extends ConstantDesc<ConstantDesc<Class<?>>>> describeConstable() {
-        return ConstantUtils.symbolizeHelper(ConstantDescs.MHR_CLASSDESC_FACTORY, ConstantDescs.CR_ClassDesc, descriptorString());
-    }
-
-    @Override
-    public String toString() {
-        return String.format("PrimitiveClassDesc[%s]", displayName());
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/constant/PrimitiveClassDescImpl.java	Thu Jun 14 13:27:14 2018 -0700
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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 java.lang.constant;
+
+import java.lang.invoke.MethodHandles;
+import java.util.Optional;
+
+import sun.invoke.util.Wrapper;
+
+import static java.lang.constant.ConstantDescs.BSM_CLASSDESC;
+import static java.lang.constant.ConstantDescs.CR_ClassDesc;
+import static java.lang.constant.ConstantDescs.DEFAULT_NAME;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * A <a href="package-summary.html#nominal">nominal descriptor</a> for the class
+ * constant corresponding to a primitive type (e.g., {@code int.class}).
+ */
+final class PrimitiveClassDescImpl
+        extends DynamicConstantDesc<Class<?>> implements ClassDesc {
+
+    private final String descriptor;
+
+    /**
+     * Create a {@linkplain ClassDesc} given a descriptor string for a primitive
+     * type.
+     *
+     * @param descriptor the descriptor string, which must be a one-character
+     * string corresponding to one of the nine base types as per JVMS 4.3
+     * @throws IllegalArgumentException if the descriptor string does not
+     * describe a valid primitive type
+     * @jvms 4.3 Descriptors
+     */
+    PrimitiveClassDescImpl(String descriptor) {
+        super(ConstantDescs.BSM_PRIMITIVE_CLASS, requireNonNull(descriptor), ConstantDescs.CR_Class);
+        if (descriptor.length() != 1
+            || "VIJCSBFDZ".indexOf(descriptor.charAt(0)) < 0)
+            throw new IllegalArgumentException(String.format("not a valid primitive type descriptor: %s", descriptor));
+        this.descriptor = descriptor;
+    }
+
+    @Override
+    public String descriptorString() {
+        return descriptor;
+    }
+
+    @Override
+    public Class<?> resolveConstantDesc(MethodHandles.Lookup lookup) {
+        return Wrapper.forBasicType(descriptorString().charAt(0)).primitiveType();
+    }
+
+    @Override
+    public Optional<? extends ConstantDesc<ConstantDesc<Class<?>>>> describeConstable() {
+        return Optional.of(DynamicConstantDesc.of(BSM_CLASSDESC, DEFAULT_NAME, CR_ClassDesc,
+                                                  new ConstantDesc<?>[] { descriptor }));
+    }
+
+    @Override
+    public String toString() {
+        return String.format("PrimitiveClassDesc[%s]", displayName());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/constant/ReferenceClassDescImpl.java	Thu Jun 14 13:27:14 2018 -0700
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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 java.lang.constant;
+
+import java.lang.invoke.MethodHandles;
+import java.util.Optional;
+
+import static java.lang.constant.ConstantDescs.BSM_CLASSDESC;
+import static java.lang.constant.ConstantDescs.CR_ClassDesc;
+import static java.lang.constant.ConstantDescs.DEFAULT_NAME;
+import static java.lang.constant.ConstantUtils.dropFirstAndLastChar;
+import static java.lang.constant.ConstantUtils.internalToBinary;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * A <a href="package-summary.html#nominal">nominal descriptor</a> for a class,
+ * interface, or array type.  A {@linkplain ReferenceClassDescImpl} corresponds to a
+ * {@code Constant_Class_info} entry in the constant pool of a classfile.
+ */
+final class ReferenceClassDescImpl implements ClassDesc {
+    private final String descriptor;
+
+    /**
+     * Create a {@linkplain ClassDesc} from a descriptor string for a class or
+     * interface type
+     *
+     * @param descriptor a field descriptor string for a class or interface type,
+     *                   as per JVMS 4.3.2
+     * @throws IllegalArgumentException if the descriptor string is not a valid
+     * field descriptor string, or does not describe a class or interface type
+     * @jvms 4.3.2 Field Descriptors
+     */
+    ReferenceClassDescImpl(String descriptor) {
+        requireNonNull(descriptor);
+        int len = ConstantUtils.matchSig(descriptor, 0, descriptor.length());
+        if (len == 0 || len == 1
+            || len != descriptor.length())
+            throw new IllegalArgumentException(String.format("not a valid reference type descriptor: %s", descriptor));
+        this.descriptor = descriptor;
+    }
+
+    @Override
+    public String descriptorString() {
+        return descriptor;
+    }
+
+    @Override
+    public Class<?> resolveConstantDesc(MethodHandles.Lookup lookup)
+            throws ReflectiveOperationException {
+        ClassDesc c = this;
+        int depth = ConstantUtils.arrayDepth(descriptorString());
+        for (int i=0; i<depth; i++)
+            c = c.componentType();
+
+        if (c.isPrimitive())
+            return lookup.findClass(descriptorString());
+        else {
+            Class<?> clazz = lookup.findClass(internalToBinary(dropFirstAndLastChar(c.descriptorString())));
+            for (int i = 0; i < depth; i++)
+                clazz = clazz.arrayType();
+            return clazz;
+        }
+    }
+
+    @Override
+    public Optional<? extends ConstantDesc<ConstantDesc<Class<?>>>> describeConstable() {
+        return Optional.of(DynamicConstantDesc.of(BSM_CLASSDESC, DEFAULT_NAME, CR_ClassDesc,
+                                                  new ConstantDesc<?>[] {descriptor }));
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        ClassDesc constant = (ClassDesc) o;
+        return descriptor.equals(constant.descriptorString());
+    }
+
+    @Override
+    public int hashCode() {
+        return descriptor.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return String.format("ClassDesc[%s]", displayName());
+    }
+}
--- a/src/java.base/share/classes/java/lang/constant/package-info.java	Fri Jun 08 15:38:32 2018 -0700
+++ b/src/java.base/share/classes/java/lang/constant/package-info.java	Thu Jun 14 13:27:14 2018 -0700
@@ -28,8 +28,8 @@
  * entities such as classes or method handles, and classfile entities such as
  * constant pool entries or {@code invokedynamic} call sites.  These classes
  * are suitable for use in bytecode reading and writing APIs, {@code invokedynamic}
- * bootstraps, bytecode intrinsic APIs (such as {@link java.lang.invoke.Intrinsics#ldc(ConstantDesc)}),
- * and compile-time or link-time program analysis tools.
+ * bootstraps, bytecode intrinsic APIs, and compile-time or link-time program
+ * analysis tools.
  *
  * <p>Every API that reads and writes bytecode instructions needs to model the
  * operands to these instructions and other classfile structures (such as entries
@@ -57,8 +57,8 @@
  * <p>The subtypes of of {@link java.lang.constant.ConstantDesc} describe various kinds
  * of constant values.  For each type of loadable constant pool entry defined in JVMS 4.4,
  * there is a corresponding subtype of {@link java.lang.constant.ConstantDesc}:
- * {@link java.lang.constant.ConstantClassDesc}, {@link java.lang.constant.ConstantMethodTypeDesc},
- * {@link java.lang.constant.ConstantMethodHandleDesc}, {@link java.lang.String},
+ * {@link java.lang.constant.ClassDesc}, {@link java.lang.constant.MethodTypeDesc},
+ * {@link java.lang.constant.DirectMethodHandleDescImpl}, {@link java.lang.String},
  * {@link java.lang.Integer}, {@link java.lang.Long}, {@link java.lang.Float},
  * {@link java.lang.Double}, and {@link java.lang.constant.DynamicConstantDesc}.  These classes
  * provides type-specific accessor methods to extract the nominal information for
@@ -68,7 +68,7 @@
  * When a bytecode-reading API encounters a constant pool entry, it can
  * convert it to the appropriate type of nominal descriptor.  For dynamic
  * constants, bytecode-reading APIs may wish to use the factory
- * {@link java.lang.constant.DynamicConstantDesc#ofCanonical(ConstantMethodHandleDesc, java.lang.String, ClassDesc, ConstantDesc[])},
+ * {@link java.lang.constant.DynamicConstantDesc#ofCanonical(DirectMethodHandleDesc, java.lang.String, ClassDesc, ConstantDesc[])},
  * which will inspect the bootstrap and, for well-known bootstraps, return
  * a more specific subtype of {@link java.lang.constant.DynamicConstantDesc}, such as
  * {@link java.lang.Enum.EnumDesc}.
@@ -87,9 +87,8 @@
  * pool entry.  It describes the bootstrap method, invocation name and type,
  * and bootstrap arguments associated with an {@code invokedynamic} instruction.
  * It is also suitable for describing {@code invokedynamic} call sites in bytecode
- * reading and writing APIs, and and is used by the
- * {@link java.lang.invoke.Intrinsics#invokedynamic(DynamicCallSiteDesc, java.lang.Object...)}
- * API for expressing {@code invokedynamic} call sites in Java source files.
+ * reading and writing APIs.
+ *
  * @jvms 4.4 The Constant Pool
  */
 package java.lang.constant;
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandle.java	Fri Jun 08 15:38:32 2018 -0700
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandle.java	Thu Jun 14 13:27:14 2018 -0700
@@ -31,6 +31,7 @@
 import java.lang.constant.ClassDesc;
 import java.lang.constant.Constable;
 import java.lang.constant.ConstantDesc;
+import java.lang.constant.DirectMethodHandleDesc;
 import java.lang.constant.MethodHandleDesc;
 import java.lang.constant.MethodTypeDesc;
 import java.util.Arrays;
@@ -1536,27 +1537,27 @@
 
         switch (info.getReferenceKind()) {
             case REF_getField:
-                return Optional.of(MethodHandleDesc.ofField(MethodHandleDesc.Kind.GETTER, owner, name, type.returnType()));
+                return Optional.of(MethodHandleDesc.ofField(DirectMethodHandleDesc.Kind.GETTER, owner, name, type.returnType()));
             case REF_putField:
-                return Optional.of(MethodHandleDesc.ofField(MethodHandleDesc.Kind.SETTER, owner, name, type.parameterType(0)));
+                return Optional.of(MethodHandleDesc.ofField(DirectMethodHandleDesc.Kind.SETTER, owner, name, type.parameterType(0)));
             case REF_getStatic:
-                return Optional.of(MethodHandleDesc.ofField(MethodHandleDesc.Kind.STATIC_GETTER, owner, name, type.returnType()));
+                return Optional.of(MethodHandleDesc.ofField(DirectMethodHandleDesc.Kind.STATIC_GETTER, owner, name, type.returnType()));
             case REF_putStatic:
-                return Optional.of(MethodHandleDesc.ofField(MethodHandleDesc.Kind.STATIC_SETTER, owner, name, type.parameterType(0)));
+                return Optional.of(MethodHandleDesc.ofField(DirectMethodHandleDesc.Kind.STATIC_SETTER, owner, name, type.parameterType(0)));
             case REF_invokeVirtual:
-                return Optional.of(MethodHandleDesc.of(MethodHandleDesc.Kind.VIRTUAL, owner, name, type));
+                return Optional.of(MethodHandleDesc.of(DirectMethodHandleDesc.Kind.VIRTUAL, owner, name, type));
             case REF_invokeStatic:
                 return isInterface ?
-                        Optional.of(MethodHandleDesc.of(MethodHandleDesc.Kind.INTERFACE_STATIC, owner, name, type)) :
-                        Optional.of(MethodHandleDesc.of(MethodHandleDesc.Kind.STATIC, owner, name, type));
+                        Optional.of(MethodHandleDesc.of(DirectMethodHandleDesc.Kind.INTERFACE_STATIC, owner, name, type)) :
+                        Optional.of(MethodHandleDesc.of(DirectMethodHandleDesc.Kind.STATIC, owner, name, type));
             case REF_invokeSpecial:
                 return isInterface ?
-                        Optional.of(MethodHandleDesc.of(MethodHandleDesc.Kind.INTERFACE_SPECIAL, owner, name, type)) :
-                        Optional.of(MethodHandleDesc.of(MethodHandleDesc.Kind.SPECIAL, owner, name, type));
+                        Optional.of(MethodHandleDesc.of(DirectMethodHandleDesc.Kind.INTERFACE_SPECIAL, owner, name, type)) :
+                        Optional.of(MethodHandleDesc.of(DirectMethodHandleDesc.Kind.SPECIAL, owner, name, type));
             case REF_invokeInterface:
-                return Optional.of(MethodHandleDesc.of(MethodHandleDesc.Kind.INTERFACE_VIRTUAL, owner, name, type));
+                return Optional.of(MethodHandleDesc.of(DirectMethodHandleDesc.Kind.INTERFACE_VIRTUAL, owner, name, type));
             case REF_newInvokeSpecial:
-                return Optional.of(MethodHandleDesc.of(MethodHandleDesc.Kind.CONSTRUCTOR, owner, name, type));
+                return Optional.of(MethodHandleDesc.of(DirectMethodHandleDesc.Kind.CONSTRUCTOR, owner, name, type));
             default:
                 return Optional.empty();
         }
--- a/src/java.base/share/classes/java/lang/invoke/VarHandle.java	Fri Jun 08 15:38:32 2018 -0700
+++ b/src/java.base/share/classes/java/lang/invoke/VarHandle.java	Thu Jun 14 13:27:14 2018 -0700
@@ -34,7 +34,7 @@
 import java.lang.constant.Constable;
 import java.lang.constant.ConstantDesc;
 import java.lang.constant.ConstantDescs;
-import java.lang.constant.ConstantMethodHandleDesc;
+import java.lang.constant.DirectMethodHandleDesc;
 import java.lang.constant.ConstantUtils;
 import java.lang.constant.DynamicConstantDesc;
 import java.util.HashMap;
@@ -2141,11 +2141,11 @@
             STATIC_FIELD(ConstantDescs.BSM_VARHANDLE_STATIC_FIELD, ConstantDescs.MHR_VARHANDLEDESC_OFSTATIC),
             ARRAY(ConstantDescs.BSM_VARHANDLE_ARRAY, ConstantDescs.MHR_VARHANDLEDESC_OFARRAY);
 
-            final ConstantMethodHandleDesc bootstrapMethod;
-            final ConstantMethodHandleDesc descFactory;
+            final DirectMethodHandleDesc bootstrapMethod;
+            final DirectMethodHandleDesc descFactory;
 
-            Kind(ConstantMethodHandleDesc bootstrapMethod,
-                 ConstantMethodHandleDesc descFactory) {
+            Kind(DirectMethodHandleDesc bootstrapMethod,
+                 DirectMethodHandleDesc descFactory) {
                 this.bootstrapMethod = bootstrapMethod;
                 this.descFactory = descFactory;
             }
--- a/test/jdk/java/lang/constant/CondyRefTest.java	Fri Jun 08 15:38:32 2018 -0700
+++ b/test/jdk/java/lang/constant/CondyRefTest.java	Thu Jun 14 13:27:14 2018 -0700
@@ -30,7 +30,7 @@
 import java.lang.constant.ClassDesc;
 import java.lang.constant.ConstantDesc;
 import java.lang.constant.ConstantDescs;
-import java.lang.constant.ConstantMethodHandleDesc;
+import java.lang.constant.DirectMethodHandleDesc;
 import java.lang.constant.DynamicConstantDesc;
 import java.lang.constant.MethodHandleDesc;
 
@@ -89,15 +89,15 @@
     }
 
     public void testDynamicConstant() throws ReflectiveOperationException {
-        ConstantMethodHandleDesc bsmRef = ConstantDescs.ofConstantBootstrap(ClassDesc.of("CondyRefTest"), "concatBSM",
+        DirectMethodHandleDesc bsmRef = ConstantDescs.ofConstantBootstrap(ClassDesc.of("CondyRefTest"), "concatBSM",
                                                                             CR_String, CR_String, CR_String);
         DynamicConstantDesc<String> r = DynamicConstantDesc.<String>of(bsmRef).withArgs("foo", "bar");
         testDCR(r, "foobar");
     }
 
     public void testNested() throws Throwable {
-        ConstantMethodHandleDesc invoker = ConstantDescs.ofConstantBootstrap(CR_ConstantBootstraps, "invoke", CR_Object, CR_MethodHandle, CR_Object.arrayType());
-        ConstantMethodHandleDesc format = MethodHandleDesc.of(MethodHandleDesc.Kind.STATIC, CR_String, "format", CR_String, CR_String, CR_Object.arrayType());
+        DirectMethodHandleDesc invoker = ConstantDescs.ofConstantBootstrap(CR_ConstantBootstraps, "invoke", CR_Object, CR_MethodHandle, CR_Object.arrayType());
+        DirectMethodHandleDesc format = MethodHandleDesc.of(MethodHandleDesc.Kind.STATIC, CR_String, "format", CR_String, CR_String, CR_Object.arrayType());
 
         String s = (String) invoker.resolveConstantDesc(LOOKUP)
                                    .invoke(LOOKUP, "", String.class,
--- a/test/jdk/java/lang/constant/ConstantUtilsTest.java	Fri Jun 08 15:38:32 2018 -0700
+++ b/test/jdk/java/lang/constant/ConstantUtilsTest.java	Thu Jun 14 13:27:14 2018 -0700
@@ -68,7 +68,7 @@
     }
 
     public void testSymbolizeHelper() {
-        ConstantMethodHandleDesc mh = MethodHandleDesc.of(MethodHandleDesc.Kind.VIRTUAL, ConstantDescs.CR_String, "isEmpty", "()Z");
+        DirectMethodHandleDesc mh = MethodHandleDesc.of(MethodHandleDesc.Kind.VIRTUAL, ConstantDescs.CR_String, "isEmpty", "()Z");
         try {
             ConstantUtils.symbolizeHelper(mh, null, "");
             fail("");
--- a/test/jdk/java/lang/constant/IndyRefTest.java	Fri Jun 08 15:38:32 2018 -0700
+++ b/test/jdk/java/lang/constant/IndyRefTest.java	Thu Jun 14 13:27:14 2018 -0700
@@ -29,7 +29,7 @@
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
 import java.lang.constant.ClassDesc;
-import java.lang.constant.ConstantMethodHandleDesc;
+import java.lang.constant.DirectMethodHandleDesc;
 import java.lang.constant.DynamicCallSiteDesc;
 import java.lang.constant.MethodHandleDesc;
 import java.lang.constant.MethodTypeDesc;
@@ -59,7 +59,7 @@
     public void testIndyRef() throws Throwable {
         ClassDesc c = ClassDesc.of("IndyRefTest");
         MethodTypeDesc mt = MethodTypeDesc.of(CR_CallSite, CR_MethodHandles_Lookup, CR_String, CR_MethodType, CR_Object.arrayType());
-        ConstantMethodHandleDesc mh = MethodHandleDesc.of(MethodHandleDesc.Kind.STATIC, c, "bootstrap", mt);
+        DirectMethodHandleDesc mh = MethodHandleDesc.of(MethodHandleDesc.Kind.STATIC, c, "bootstrap", mt);
         DynamicCallSiteDesc csd = DynamicCallSiteDesc.of(mh, "wooga", MethodTypeDesc.of(CR_String));
         CallSite cs = csd.resolveCallSiteDesc(MethodHandles.lookup());
         MethodHandle target = cs.getTarget();
@@ -94,7 +94,7 @@
     public void testEqualsHashToString() throws Throwable {
         ClassDesc c = ClassDesc.of("IndyRefTest");
         MethodTypeDesc mt = MethodTypeDesc.of(CR_CallSite, CR_MethodHandles_Lookup, CR_String, CR_MethodType, CR_Object.arrayType());
-        ConstantMethodHandleDesc mh = MethodHandleDesc.of(MethodHandleDesc.Kind.STATIC, c, "bootstrap", mt);
+        DirectMethodHandleDesc mh = MethodHandleDesc.of(MethodHandleDesc.Kind.STATIC, c, "bootstrap", mt);
 
         DynamicCallSiteDesc csd1 = DynamicCallSiteDesc.of(mh, "wooga", MethodTypeDesc.of(CR_String));
         DynamicCallSiteDesc csd2 = DynamicCallSiteDesc.of(mh, "wooga", MethodTypeDesc.of(CR_String));
@@ -111,7 +111,7 @@
     public void testEmptyInvocationName() throws Throwable {
         ClassDesc c = ClassDesc.of("IndyRefTest");
         MethodTypeDesc mt = MethodTypeDesc.of(CR_CallSite, CR_MethodHandles_Lookup, CR_String, CR_MethodType, CR_Object.arrayType());
-        ConstantMethodHandleDesc mh = MethodHandleDesc.of(MethodHandleDesc.Kind.STATIC, c, "bootstrap", mt);
+        DirectMethodHandleDesc mh = MethodHandleDesc.of(MethodHandleDesc.Kind.STATIC, c, "bootstrap", mt);
         DynamicCallSiteDesc csd1 = DynamicCallSiteDesc.of(mh, "", MethodTypeDesc.of(CR_String));
     }
 }
--- a/test/jdk/java/lang/constant/MethodHandleRefTest.java	Fri Jun 08 15:38:32 2018 -0700
+++ b/test/jdk/java/lang/constant/MethodHandleRefTest.java	Thu Jun 14 13:27:14 2018 -0700
@@ -30,7 +30,7 @@
 import java.lang.invoke.WrongMethodTypeException;
 import java.lang.constant.ClassDesc;
 import java.lang.constant.ConstantDescs;
-import java.lang.constant.ConstantMethodHandleDesc;
+import java.lang.constant.DirectMethodHandleDesc;
 import java.lang.constant.MethodHandleDesc;
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
@@ -81,10 +81,10 @@
     }
 
     private void testMethodHandleRef(MethodHandleDesc r) throws ReflectiveOperationException {
-        if (r instanceof ConstantMethodHandleDesc) {
+        if (r instanceof DirectMethodHandleDesc) {
             testSymbolicRef(r);
 
-            ConstantMethodHandleDesc rr = (ConstantMethodHandleDesc) r;
+            DirectMethodHandleDesc rr = (DirectMethodHandleDesc) r;
             assertEquals(r, MethodHandleDesc.of(rr.kind(), rr.owner(), rr.methodName(), r.methodType()));
         }
         else {
@@ -100,7 +100,7 @@
 
         // compare extractable properties: refKind, owner, name, type
         MethodHandleInfo mhi = LOOKUP.revealDirect(mh);
-        ConstantMethodHandleDesc rr = (ConstantMethodHandleDesc) r;
+        DirectMethodHandleDesc rr = (DirectMethodHandleDesc) r;
         assertEquals(mhi.getDeclaringClass().descriptorString(), rr.owner().descriptorString());
         assertEquals(mhi.getName(), rr.methodName());
         assertEquals(mhi.getReferenceKind(), rr.kind().refKind);
@@ -278,7 +278,7 @@
         Field[] fields = ConstantDescs.class.getDeclaredFields();
         for (Field f : fields) {
             try {
-                if (f.getType().equals(ConstantMethodHandleDesc.class)
+                if (f.getType().equals(DirectMethodHandleDesc.class)
                     && ((f.getModifiers() & Modifier.STATIC) != 0)
                     && ((f.getModifiers() & Modifier.PUBLIC) != 0)) {
                     MethodHandleDesc r = (MethodHandleDesc) f.get(null);