changeset 49327:f6a1ff6755b3 condy-folding

moving classes under j.l.sym to j.l.i.constant, relocating tests accordingly
author vromero
date Wed, 07 Mar 2018 16:34:02 -0500
parents b87fd4c97bd3
children 47f797792311
files src/java.base/share/classes/java/lang/Class.java src/java.base/share/classes/java/lang/Double.java src/java.base/share/classes/java/lang/Enum.java src/java.base/share/classes/java/lang/Float.java src/java.base/share/classes/java/lang/Integer.java src/java.base/share/classes/java/lang/Long.java src/java.base/share/classes/java/lang/String.java src/java.base/share/classes/java/lang/invoke/Intrinsics.java src/java.base/share/classes/java/lang/invoke/MethodHandle.java src/java.base/share/classes/java/lang/invoke/MethodType.java src/java.base/share/classes/java/lang/invoke/VarHandle.java src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template src/java.base/share/classes/java/lang/invoke/constant/AsTypeMethodHandleRef.java src/java.base/share/classes/java/lang/invoke/constant/ClassRef.java src/java.base/share/classes/java/lang/invoke/constant/Constable.java src/java.base/share/classes/java/lang/invoke/constant/ConstantClassRef.java src/java.base/share/classes/java/lang/invoke/constant/ConstantMethodHandleRef.java src/java.base/share/classes/java/lang/invoke/constant/ConstantMethodTypeRef.java src/java.base/share/classes/java/lang/invoke/constant/ConstantRef.java src/java.base/share/classes/java/lang/invoke/constant/ConstantRefs.java src/java.base/share/classes/java/lang/invoke/constant/DynamicCallSiteRef.java src/java.base/share/classes/java/lang/invoke/constant/DynamicConstantRef.java src/java.base/share/classes/java/lang/invoke/constant/EnumRef.java src/java.base/share/classes/java/lang/invoke/constant/MethodHandleRef.java src/java.base/share/classes/java/lang/invoke/constant/MethodTypeRef.java src/java.base/share/classes/java/lang/invoke/constant/PrimitiveClassRef.java src/java.base/share/classes/java/lang/invoke/constant/RefBootstraps.java src/java.base/share/classes/java/lang/invoke/constant/VarHandleRef.java src/java.base/share/classes/java/lang/invoke/constant/package-info.java src/java.base/share/classes/java/lang/sym/AsTypeMethodHandleRef.java src/java.base/share/classes/java/lang/sym/ClassRef.java src/java.base/share/classes/java/lang/sym/Constable.java src/java.base/share/classes/java/lang/sym/ConstantClassRef.java src/java.base/share/classes/java/lang/sym/ConstantMethodHandleRef.java src/java.base/share/classes/java/lang/sym/ConstantMethodTypeRef.java src/java.base/share/classes/java/lang/sym/ConstantRef.java src/java.base/share/classes/java/lang/sym/ConstantRefs.java src/java.base/share/classes/java/lang/sym/DynamicCallSiteRef.java src/java.base/share/classes/java/lang/sym/DynamicConstantRef.java src/java.base/share/classes/java/lang/sym/EnumRef.java src/java.base/share/classes/java/lang/sym/MethodHandleRef.java src/java.base/share/classes/java/lang/sym/MethodTypeRef.java src/java.base/share/classes/java/lang/sym/PrimitiveClassRef.java src/java.base/share/classes/java/lang/sym/RefBootstraps.java src/java.base/share/classes/java/lang/sym/VarHandleRef.java src/java.base/share/classes/java/lang/sym/package-info.java src/java.base/share/classes/jdk/internal/lang/annotation/Foldable.java src/java.base/share/classes/module-info.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java src/jdk.compiler/share/classes/com/sun/tools/javac/util/Constables.java test/jdk/java/lang/invoke/constant/ClassRefTest.java test/jdk/java/lang/invoke/constant/CondyRefTest.java test/jdk/java/lang/invoke/constant/IndyRefTest.java test/jdk/java/lang/invoke/constant/IntrinsifiedRefTest.java test/jdk/java/lang/invoke/constant/MethodHandleRefTest.java test/jdk/java/lang/invoke/constant/MethodTypeRefTest.java test/jdk/java/lang/invoke/constant/SymbolicRefTest.java test/jdk/java/lang/sym/ClassRefTest.java test/jdk/java/lang/sym/CondyRefTest.java test/jdk/java/lang/sym/IndyRefTest.java test/jdk/java/lang/sym/IntrinsifiedRefTest.java test/jdk/java/lang/sym/MethodHandleRefTest.java test/jdk/java/lang/sym/MethodTypeRefTest.java test/jdk/java/lang/sym/SymbolicRefTest.java test/langtools/tools/javac/condy/CheckForCondyDuplicatesTest.java test/langtools/tools/javac/specialConstantFolding/CheckForCorrectMRefTest.java test/langtools/tools/javac/specialConstantFolding/CondyCodeGenerationTest.java test/langtools/tools/javac/specialConstantFolding/CrashWithPrimitiveArgumentsTest.java test/langtools/tools/javac/specialConstantFolding/DontCompileIfSymbolCantBeFoundTest.java test/langtools/tools/javac/specialConstantFolding/EffectivelyFinalTestNeg.java test/langtools/tools/javac/specialConstantFolding/IndyCodeGenerationTest.java test/langtools/tools/javac/specialConstantFolding/IndyCrashTest.java test/langtools/tools/javac/specialConstantFolding/IndyLinkageErrorTest.java test/langtools/tools/javac/specialConstantFolding/IndyNegativeTest01.java test/langtools/tools/javac/specialConstantFolding/IndyPositiveTest01.java test/langtools/tools/javac/specialConstantFolding/IntrinsicsTest.java test/langtools/tools/javac/specialConstantFolding/LDCNegativeTest.java test/langtools/tools/javac/specialConstantFolding/MultipleBSMEntriesTest.java test/langtools/tools/javac/specialConstantFolding/ReflectiveErrorTest.java test/langtools/tools/javac/specialConstantFolding/ReflectiveErrorTest.out test/langtools/tools/javac/specialConstantFolding/ReportIncorrectMHForIndyTest.java test/langtools/tools/javac/specialConstantFolding/TwoVisitsAreNeededCauseOfForwardRefTest.java test/langtools/tools/javac/specialConstantFolding/checkMethodTypeShape/MethodTypeNegTest.java test/langtools/tools/javac/specialConstantFolding/checkMethodTypeShape/MethodTypeNegTest.out test/langtools/tools/javac/specialConstantFolding/dead_code_elimination/DontDoDCEOfConstableTest.java test/langtools/tools/javac/specialConstantFolding/harness/tests/ConstantDefinitions.java test/langtools/tools/javac/specialConstantFolding/harness/tests/ConstantFoldingOfMethodTypeDiffContextsTest.java test/langtools/tools/javac/specialConstantFolding/harness/tests/ConstantPropagationTest.java test/langtools/tools/javac/specialConstantFolding/harness/tests/EffectivelyFinalTest.java test/langtools/tools/javac/specialConstantFolding/harness/tests/FindConstructorTest.java test/langtools/tools/javac/specialConstantFolding/harness/tests/FindGetterTest.java test/langtools/tools/javac/specialConstantFolding/harness/tests/FindMethodWithGenericArgumentsTest.java test/langtools/tools/javac/specialConstantFolding/harness/tests/FindSetterTest.java test/langtools/tools/javac/specialConstantFolding/harness/tests/FindStaticGetterTest.java test/langtools/tools/javac/specialConstantFolding/harness/tests/FindStaticSetterTest.java test/langtools/tools/javac/specialConstantFolding/harness/tests/FindStaticTest.java test/langtools/tools/javac/specialConstantFolding/harness/tests/FindVirtualTest01.java test/langtools/tools/javac/specialConstantFolding/harness/tests/FindVirtualTest02.java test/langtools/tools/javac/specialConstantFolding/harness/tests/InstanceTrackableMethodsTest.java test/langtools/tools/javac/specialConstantFolding/harness/tests/StringFoldingTest.java test/langtools/tools/javac/specialConstantFolding/warningNotFoundOrIncorrect/WarningIfClassOrMemberNotFound.java test/langtools/tools/javac/specialConstantFolding/warningNotFoundOrIncorrect/WarningIfClassOrMemberNotFound2.java test/langtools/tools/javac/specialConstantFolding/warningNotFoundOrIncorrect/WarningIfClassOrMemberNotFound3.java test/langtools/tools/javac/specialConstantFolding/warningNotFoundOrIncorrect/WarningIfMemberIncorrect.java
diffstat 104 files changed, 4567 insertions(+), 4567 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/java/lang/Class.java	Wed Mar 07 14:59:03 2018 -0500
+++ b/src/java.base/share/classes/java/lang/Class.java	Wed Mar 07 16:34:02 2018 -0500
@@ -47,8 +47,8 @@
 import java.lang.reflect.Proxy;
 import java.lang.reflect.Type;
 import java.lang.reflect.TypeVariable;
-import java.lang.sym.ClassRef;
-import java.lang.sym.Constable;
+import java.lang.invoke.constant.ClassRef;
+import java.lang.invoke.constant.Constable;
 import java.net.URL;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
--- a/src/java.base/share/classes/java/lang/Double.java	Wed Mar 07 14:59:03 2018 -0500
+++ b/src/java.base/share/classes/java/lang/Double.java	Wed Mar 07 16:34:02 2018 -0500
@@ -26,8 +26,8 @@
 package java.lang;
 
 import java.lang.invoke.MethodHandles;
-import java.lang.sym.Constable;
-import java.lang.sym.ConstantRef;
+import java.lang.invoke.constant.Constable;
+import java.lang.invoke.constant.ConstantRef;
 import java.util.Optional;
 
 import jdk.internal.math.FloatingDecimal;
--- a/src/java.base/share/classes/java/lang/Enum.java	Wed Mar 07 14:59:03 2018 -0500
+++ b/src/java.base/share/classes/java/lang/Enum.java	Wed Mar 07 16:34:02 2018 -0500
@@ -31,8 +31,8 @@
 import java.io.ObjectInputStream;
 import java.io.ObjectStreamException;
 import java.lang.invoke.MethodHandles;
-import java.lang.sym.Constable;
-import java.lang.sym.EnumRef;
+import java.lang.invoke.constant.Constable;
+import java.lang.invoke.constant.EnumRef;
 import java.util.Optional;
 
 /**
--- a/src/java.base/share/classes/java/lang/Float.java	Wed Mar 07 14:59:03 2018 -0500
+++ b/src/java.base/share/classes/java/lang/Float.java	Wed Mar 07 16:34:02 2018 -0500
@@ -26,8 +26,8 @@
 package java.lang;
 
 import java.lang.invoke.MethodHandles;
-import java.lang.sym.Constable;
-import java.lang.sym.ConstantRef;
+import java.lang.invoke.constant.Constable;
+import java.lang.invoke.constant.ConstantRef;
 import java.util.Optional;
 
 import jdk.internal.math.FloatingDecimal;
--- a/src/java.base/share/classes/java/lang/Integer.java	Wed Mar 07 14:59:03 2018 -0500
+++ b/src/java.base/share/classes/java/lang/Integer.java	Wed Mar 07 16:34:02 2018 -0500
@@ -27,8 +27,8 @@
 
 import java.lang.annotation.Native;
 import java.lang.invoke.MethodHandles;
-import java.lang.sym.Constable;
-import java.lang.sym.ConstantRef;
+import java.lang.invoke.constant.Constable;
+import java.lang.invoke.constant.ConstantRef;
 import java.util.Objects;
 import java.util.Optional;
 
--- a/src/java.base/share/classes/java/lang/Long.java	Wed Mar 07 14:59:03 2018 -0500
+++ b/src/java.base/share/classes/java/lang/Long.java	Wed Mar 07 16:34:02 2018 -0500
@@ -27,8 +27,8 @@
 
 import java.lang.annotation.Native;
 import java.lang.invoke.MethodHandles;
-import java.lang.sym.Constable;
-import java.lang.sym.ConstantRef;
+import java.lang.invoke.constant.Constable;
+import java.lang.invoke.constant.ConstantRef;
 import java.math.*;
 import java.util.Objects;
 import java.util.Optional;
--- a/src/java.base/share/classes/java/lang/String.java	Wed Mar 07 14:59:03 2018 -0500
+++ b/src/java.base/share/classes/java/lang/String.java	Wed Mar 07 16:34:02 2018 -0500
@@ -29,8 +29,8 @@
 import java.io.UnsupportedEncodingException;
 import java.lang.annotation.Native;
 import java.lang.invoke.MethodHandles;
-import java.lang.sym.Constable;
-import java.lang.sym.ConstantRef;
+import java.lang.invoke.constant.Constable;
+import java.lang.invoke.constant.ConstantRef;
 import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.Arrays;
--- a/src/java.base/share/classes/java/lang/invoke/Intrinsics.java	Wed Mar 07 14:59:03 2018 -0500
+++ b/src/java.base/share/classes/java/lang/invoke/Intrinsics.java	Wed Mar 07 16:34:02 2018 -0500
@@ -24,8 +24,8 @@
  */
 package java.lang.invoke;
 
-import java.lang.sym.ConstantRef;
-import java.lang.sym.DynamicCallSiteRef;
+import java.lang.invoke.constant.ConstantRef;
+import java.lang.invoke.constant.DynamicCallSiteRef;
 
 /**
  * Intrinsics
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandle.java	Wed Mar 07 14:59:03 2018 -0500
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandle.java	Wed Mar 07 16:34:02 2018 -0500
@@ -28,10 +28,10 @@
 
 import jdk.internal.HotSpotIntrinsicCandidate;
 
-import java.lang.sym.ClassRef;
-import java.lang.sym.Constable;
-import java.lang.sym.MethodHandleRef;
-import java.lang.sym.MethodTypeRef;
+import java.lang.invoke.constant.ClassRef;
+import java.lang.invoke.constant.Constable;
+import java.lang.invoke.constant.MethodHandleRef;
+import java.lang.invoke.constant.MethodTypeRef;
 import java.util.Arrays;
 import java.util.Objects;
 import java.util.Optional;
--- a/src/java.base/share/classes/java/lang/invoke/MethodType.java	Wed Mar 07 14:59:03 2018 -0500
+++ b/src/java.base/share/classes/java/lang/invoke/MethodType.java	Wed Mar 07 16:34:02 2018 -0500
@@ -30,9 +30,9 @@
 import java.lang.ref.WeakReference;
 import java.lang.ref.Reference;
 import java.lang.ref.ReferenceQueue;
-import java.lang.sym.ClassRef;
-import java.lang.sym.Constable;
-import java.lang.sym.MethodTypeRef;
+import java.lang.invoke.constant.ClassRef;
+import java.lang.invoke.constant.Constable;
+import java.lang.invoke.constant.MethodTypeRef;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
--- a/src/java.base/share/classes/java/lang/invoke/VarHandle.java	Wed Mar 07 14:59:03 2018 -0500
+++ b/src/java.base/share/classes/java/lang/invoke/VarHandle.java	Wed Mar 07 16:34:02 2018 -0500
@@ -30,8 +30,8 @@
 import jdk.internal.vm.annotation.ForceInline;
 import jdk.internal.vm.annotation.Stable;
 
-import java.lang.sym.Constable;
-import java.lang.sym.VarHandleRef;
+import java.lang.invoke.constant.Constable;
+import java.lang.invoke.constant.VarHandleRef;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
--- a/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template	Wed Mar 07 14:59:03 2018 -0500
+++ b/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template	Wed Mar 07 16:34:02 2018 -0500
@@ -27,7 +27,7 @@
 import jdk.internal.util.Preconditions;
 import jdk.internal.vm.annotation.ForceInline;
 
-import java.lang.sym.VarHandleRef;
+import java.lang.invoke.constant.VarHandleRef;
 import java.util.Objects;
 import java.util.Optional;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/AsTypeMethodHandleRef.java	Wed Mar 07 16:34:02 2018 -0500
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2012, 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.invoke.constant;
+
+import jdk.internal.lang.annotation.Foldable;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.Optional;
+
+import static java.lang.invoke.constant.ConstantRefs.BSM_INVOKE;
+import static java.lang.invoke.constant.ConstantRefs.CR_MethodHandle;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * AsTypeMethodHandleRef
+ *
+ * @author Brian Goetz
+ */
+final class AsTypeMethodHandleRef extends DynamicConstantRef<MethodHandle>
+        implements MethodHandleRef {
+
+    private final MethodHandleRef underlying;
+    private final MethodTypeRef type;
+
+    AsTypeMethodHandleRef(MethodHandleRef underlying, MethodTypeRef type) {
+        super(BSM_INVOKE, "_", CR_MethodHandle,
+              ConstantRefs.MHR_METHODHANDLE_ASTYPE, underlying, type);
+        // Any type checking we can do?
+        this.underlying = requireNonNull(underlying);
+        this.type = requireNonNull(type);
+    }
+
+    @Override
+    @Foldable
+    public MethodTypeRef methodType() {
+        return type;
+    }
+
+    @Override
+    public MethodHandle resolveConstantRef(MethodHandles.Lookup lookup) throws ReflectiveOperationException {
+        MethodHandle handle = underlying.resolveConstantRef(lookup);
+        MethodType methodType = type.resolveConstantRef(lookup);
+        return handle.asType(methodType);
+    }
+
+    @Override
+    public Optional<? extends ConstantRef<? super ConstantRef<MethodHandle>>> toConstantRef(MethodHandles.Lookup lookup) {
+        return DynamicConstantRef.symbolizeHelper(lookup, ConstantRefs.MHR_METHODHANDLEREF_ASTYPE, ConstantRefs.CR_MethodHandleRef,
+                                                  underlying, type);
+    }
+
+    @Override
+    public String toString() {
+        return underlying.toString() + String.format(".asType%s", type.simpleDescriptor());
+    }
+
+    // @@@ canonical?
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/ClassRef.java	Wed Mar 07 16:34:02 2018 -0500
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2012, 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.invoke.constant;
+
+import jdk.internal.lang.annotation.Foldable;
+
+import java.util.stream.Stream;
+
+import sun.invoke.util.Wrapper;
+
+import static java.util.Objects.requireNonNull;
+import static java.util.stream.Collectors.joining;
+
+/**
+ * A nominal reference for a {@link Class}.
+ */
+public interface ClassRef extends ConstantRef<Class<?>>, Constable<ConstantRef<Class<?>>> {
+    /**
+     * Create a {@linkplain ClassRef} from a fully-qualified, dot-separated
+     * class name
+     *
+     * @param name the fully qualified class name, dot-separated
+     * @return a {@linkplain ClassRef} describing the desired class
+     * @throws IllegalArgumentException if the name string does not
+     * describe a valid class name
+     */
+    @Foldable
+    static ClassRef of(String name) {
+        return ClassRef.ofDescriptor("L" + name.replace('.', '/') + ";");
+    }
+
+    /**
+     * Create a {@linkplain ClassRef} from a dot-separated package name and an
+     * unqualified class name
+     *
+     * @param packageName the package name, dot-separated
+     * @param className the unqualified class name
+     * @return a {@linkplain ClassRef} describing the desired class
+     * @throws IllegalArgumentException if the package name or class name are
+     * not in the correct format
+     */
+    @Foldable
+    static ClassRef of(String packageName, String className) {
+        if (className.contains("."))
+            throw new IllegalArgumentException(className);
+        return ofDescriptor("L" + packageName.replace('.', '/')
+                            + (packageName.length() > 0 ? "/" : "")
+                            + className + ";");
+    }
+
+    /**
+     * Create a {@linkplain ClassRef} from a descriptor string for a class
+     *
+     * @param descriptor the descriptor string
+     * @return a {@linkplain ClassRef} describing the desired class
+     * @throws NullPointerException if the descriptor string is null
+     * @throws IllegalArgumentException if the descriptor string is not
+     * a valid class descriptor
+     */
+    @Foldable
+    static ClassRef ofDescriptor(String descriptor) {
+        requireNonNull(descriptor);
+        return (descriptor.length() == 1)
+               ? new PrimitiveClassRef(descriptor)
+               : new ConstantClassRef(descriptor);
+    }
+
+    /**
+     * Create a {@linkplain ClassRef} describing an array of the type
+     * described by this {@linkplain ClassRef}
+     *
+     * @return a {@linkplain ClassRef} describing the array type
+     */
+    @Foldable
+    default ClassRef array() {
+        return ClassRef.ofDescriptor("[" + descriptorString());
+    }
+
+    /**
+     * Create a {@linkplain ClassRef} describing an inner class of the
+     * non-array reference type described by this {@linkplain ClassRef}
+     * @param innerName the name of the inner class
+     * @return a {@linkplain ClassRef} describing the inner class
+     */
+    @Foldable
+    default ClassRef inner(String innerName) {
+        if (!descriptorString().startsWith("L"))
+            throw new IllegalStateException("Outer class is not a non-array reference type");
+        return ClassRef.ofDescriptor(descriptorString().substring(0, descriptorString().length() - 1) + "$" + innerName + ";");
+    }
+
+    /**
+     * Create a {@linkplain ClassRef} describing a multiply nested inner class of the
+     * non-array reference type described by this {@linkplain ClassRef}
+     *
+     * @param firstInnerName the name of the first level of inner class
+     * @param moreInnerNames the name(s) of the remaining levels of inner class
+     * @return a {@linkplain ClassRef} describing the inner class
+     */
+    @Foldable
+    default ClassRef inner(String firstInnerName, String... moreInnerNames) {
+        if (!descriptorString().startsWith("L"))
+            throw new IllegalStateException("Outer class is not a non-array reference type");
+        return moreInnerNames.length == 0
+               ? inner(firstInnerName)
+               : ClassRef.ofDescriptor(descriptorString().substring(0, descriptorString().length() - 1) + "$" + firstInnerName
+                                       + Stream.of(moreInnerNames).collect(joining("$", "$", "")) + ";");
+    }
+
+    /**
+     * Returns whether this {@linkplain ClassRef} describes an array type
+     *
+     * @return whether this {@linkplain ClassRef} describes an array type
+     */
+    default boolean isArray() {
+        return descriptorString().startsWith("[");
+    }
+
+    /**
+     * Returns whether this {@linkplain ClassRef} describes a primitive type
+     *
+     * @return whether this {@linkplain ClassRef} describes a primitive type
+     */
+    default boolean isPrimitive() {
+        return descriptorString().length() == 1;
+    }
+
+    /**
+     * Returns the component type of this {@linkplain ClassRef}, if it describes
+     * an array type
+     *
+     * @return a {@linkplain ClassRef} describing the component type
+     * @throws IllegalStateException if this {@linkplain ClassRef} does not
+     * describe an array type
+     */
+    @Foldable
+    default ClassRef componentType() {
+        if (!isArray())
+            throw new IllegalStateException();
+        return ClassRef.ofDescriptor(descriptorString().substring(1));
+    }
+
+    /**
+     * Returns a human-readable name for the type described by this descriptor
+     *
+     * @return a human-readable name for the type described by this descriptor
+     */
+    default String simpleName() {
+        if (descriptorString().length() == 1)
+            return Wrapper.forBasicType(descriptorString().charAt(0)).primitiveSimpleName();
+        else if (descriptorString().startsWith("L")) {
+            return descriptorString().substring(Math.max(1, descriptorString().lastIndexOf('/') + 1),
+                                                descriptorString().length() - 1);
+        }
+        else if (descriptorString().startsWith(("["))) {
+            int depth=arrayDepth();
+            ClassRef c = this;
+            for (int i=0; i<depth; i++)
+                c = c.componentType();
+            String name = c.simpleName();
+            StringBuilder sb = new StringBuilder(name.length() + 2*depth);
+            sb.append(name);
+            for (int i=0; i<depth; i++)
+                sb.append("[]");
+            return sb.toString();
+        }
+        else
+            throw new IllegalStateException(descriptorString());
+    }
+
+    private int arrayDepth() {
+        int depth = 0;
+        while (descriptorString().charAt(depth) == '[')
+            depth++;
+        return depth;
+    }
+
+    /**
+     * Return the type descriptor string
+     * @return the type descriptor string
+     */
+    @Foldable
+    String descriptorString();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/Constable.java	Wed Mar 07 16:34:02 2018 -0500
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2012, 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.invoke.constant;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.VarHandle;
+import java.util.Optional;
+
+/**
+ * Represents a type which is <em>constable</em>.  A constable type is one whose
+ * values can be represented in the constant pool of a Java classfile.
+ *
+ * <p>The basic constable types are types whose values have a native representation
+ * in the constant pool: ({@link String}, {@link Integer}, {@link Long}, {@link Float},
+ * {@link Double}, {@link Class}, {@link MethodType}, and {@link MethodHandle}).
+ *
+ * <p>Other reference types can be constable if their instances can describe
+ * themselves in nominal form as a {@link ConstantRef}. Examples in the Java SE
+ * Platform API are types that support Java language features, such as {@link Enum},
+ * and runtime support classes, such as {@link VarHandle}.
+ *
+ * <p>The nominal form of an instance of a constable type is obtained via
+ * {@link #toConstantRef(MethodHandles.Lookup)}. A {@linkplain Constable} need
+ * not be able to (or may choose not to) render all its instances in the form of
+ * a {@link ConstantRef}; this method returns an {@link Optional} to indicate
+ * whether a nominal reference could be created for a particular instance. (For
+ * example, {@link MethodHandle} will produce nominal references for direct
+ * method handles, but not necessarily for method handles resulting from method
+ * handle combinators such as {@link MethodHandle#asType(MethodType)}.)
+ *
+ * @param <T> the type of the class implementing {@linkplain Constable}
+ */
+public interface Constable<T> {
+    /**
+     * Return a nominal reference for this instance, if one can be
+     * constructed.
+     *
+     * @implSpec This method behaves as if {@link #toConstantRef(MethodHandles.Lookup)}
+     * were called with a lookup parameter of {@code MethodHandles.publicLookup()}.
+     *
+     * @return An {@link Optional} describing the resulting nominal reference,
+     * or an empty {@link Optional} if one cannot be constructed
+     */
+    default Optional<? extends ConstantRef<? super T>> toConstantRef() {
+        return toConstantRef(MethodHandles.publicLookup());
+    }
+
+    /**
+     * Return a nominal reference for this instance, if one can be
+     * constructed.  This object (and any classes needed to construct its
+     * nominal description) must be accessible from the class described by the
+     * {@code lookup} parameter.
+     *
+     * @param lookup A {@link MethodHandles.Lookup} to be used to perform
+     *               access control determinations
+     * @return An {@link Optional} describing the resulting nominal reference,
+     * or an empty {@link Optional} if one cannot be constructed or this object
+     * is not accessible from {@code lookup}
+     */
+    Optional<? extends ConstantRef<? super T>> toConstantRef(MethodHandles.Lookup lookup);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/ConstantClassRef.java	Wed Mar 07 16:34:02 2018 -0500
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2012, 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.invoke.constant;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Array;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.regex.Pattern;
+
+import static java.lang.invoke.constant.ConstantRefs.CR_ClassRef;
+
+/**
+ * ConstantClassRef
+ *
+ * @author Brian Goetz
+ */
+public class ConstantClassRef implements ClassRef {
+    private static final Pattern TYPE_DESC = Pattern.compile("(\\[*)(V|I|J|S|B|C|F|D|Z|L[^/.\\[;][^.\\[;]*;)");
+
+    private final String descriptor;
+
+    /**
+     * Create a {@linkplain ClassRef} from a descriptor string for a reference
+     * type
+     *
+     * @param descriptor the descriptor string
+     * @throws IllegalArgumentException if the descriptor string does not
+     * describe a valid reference type name
+     */
+    ConstantClassRef(String descriptor) {
+        // @@@ Replace validation with a lower-overhead mechanism than regex
+        // Follow the trail from MethodType.fromMethodDescriptorString to
+        // parsing code in sun/invoke/util/BytecodeDescriptor.java which could
+        // be extracted and/or shared
+        if (descriptor == null
+            || !TYPE_DESC.matcher(descriptor).matches())
+            throw new IllegalArgumentException(String.format("%s is not a valid type descriptor", descriptor));
+        this.descriptor = descriptor;
+    }
+
+    @Override
+    public String descriptorString() {
+        return descriptor;
+    }
+
+    private int arrayDepth() {
+        int depth = 0;
+        while (descriptorString().charAt(depth) == '[')
+            depth++;
+        return depth;
+    }
+
+    @Override
+    public Class<?> resolveConstantRef(MethodHandles.Lookup lookup) throws ReflectiveOperationException {
+        ClassRef c = this;
+        int depth = arrayDepth();
+        for (int i=0; i<depth; i++)
+            c = c.componentType();
+
+        if (c.descriptorString().length() == 1)
+            return Class.forName(descriptorString(), true, lookup.lookupClass().getClassLoader());
+        else {
+            Class<?> clazz = Class.forName(c.descriptorString().substring(1, c.descriptorString().length() - 1)
+                                            .replace('/', '.'), true, lookup.lookupClass().getClassLoader());
+            for (int i = 0; i < depth; i++)
+                clazz = Array.newInstance(clazz, 0).getClass();
+            return clazz;
+        }
+    }
+
+    @Override
+    public Optional<? extends ConstantRef<? super ConstantRef<Class<?>>>> toConstantRef(MethodHandles.Lookup lookup) {
+        return Optional.of(DynamicConstantRef.of(RefBootstraps.BSM_CLASSREF, CR_ClassRef).withArgs(descriptor));
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        ClassRef constant = (ClassRef) o;
+        return Objects.equals(descriptor, constant.descriptorString());
+    }
+
+    @Override
+    public int hashCode() {
+        return descriptor != null ? descriptor.hashCode() : 0;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("ClassRef[%s]", simpleName());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/ConstantMethodHandleRef.java	Wed Mar 07 16:34:02 2018 -0500
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2012, 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.invoke.constant;
+
+import jdk.internal.lang.annotation.Foldable;
+
+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 static java.lang.invoke.constant.ConstantRefs.CR_MethodTypeRef;
+import static java.lang.invoke.constant.MethodHandleRef.Kind.CONSTRUCTOR;
+import static java.lang.invoke.constant.ConstantRefs.CR_MethodHandleRef;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * DirectMethodHandleRef
+ *
+ * @author Brian Goetz
+ */
+public class ConstantMethodHandleRef implements MethodHandleRef {
+
+    private final Kind kind;
+    private final ClassRef owner;
+    private final String name;
+    private final MethodTypeRef type;
+
+    /**
+     * Construct a {@linkplain ConstantMethodHandleRef} from a kind, owner, name, and type
+     * @param kind the kind of the method handle
+     * @param owner the declaring class for the method
+     * @param name the name of the method (ignored if {@code kind} is {@code CONSTRUCTOR})
+     * @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
+     */
+    ConstantMethodHandleRef(Kind kind, ClassRef owner, String name, MethodTypeRef type) {
+        super();
+        if (kind == CONSTRUCTOR)
+            name = "<init>";
+
+        requireNonNull(kind);
+        requireNonNull(owner);
+        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(MethodTypeRef 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(MethodTypeRef 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 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; }
+
+    /**
+     * Return the {@code kind} of the method handle described by this nominal reference
+     * @return the {@link Kind}
+     */
+    @Foldable
+    public Kind kind() { return kind; }
+
+    /**
+     * Return the class which declares the method or field described by
+     * this nominal reference
+     *
+     * @return the class in which the method or field is declared
+     */
+    @Foldable
+    public ClassRef owner() {
+        return owner;
+    }
+
+    /**
+     * Return the name of the method described by this nominal reference
+     *
+     * @return the name of the method
+     */
+    @Foldable
+    public String methodName() {
+        return name;
+    }
+
+    /**
+     * Return the type of the method described by this nominal reference
+     * @return the method type
+     */
+    @Foldable
+    public MethodTypeRef methodType() {
+        return type;
+    }
+
+    public MethodHandle resolveConstantRef(MethodHandles.Lookup lookup) throws ReflectiveOperationException {
+        Class<?> resolvedOwner = owner.resolveConstantRef(lookup);
+        MethodType resolvedType = this.type.resolveConstantRef(lookup);
+        switch (kind) {
+            case STATIC:
+                return lookup.findStatic(resolvedOwner, name, resolvedType);
+            case INTERFACE_VIRTUAL:
+            case VIRTUAL:
+                return lookup.findVirtual(resolvedOwner, name, resolvedType);
+            case 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 ConstantRef<? super ConstantRef<MethodHandle>>> toConstantRef(MethodHandles.Lookup lookup) {
+        return Optional.of(DynamicConstantRef.of(RefBootstraps.BSM_METHODHANDLEREF, CR_MethodHandleRef)
+                                             .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;
+        ConstantMethodHandleRef ref = (ConstantMethodHandleRef) o;
+        return kind == ref.kind &&
+               Objects.equals(owner, ref.owner) &&
+               Objects.equals(name, ref.name) &&
+               Objects.equals(type, ref.type);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(kind, owner, name, type);
+    }
+
+    @Override
+    public String toString() {
+        return String.format("MethodHandleRef[%s/%s::%s%s]", kind, owner.simpleName(), name, type.simpleDescriptor());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/ConstantMethodTypeRef.java	Wed Mar 07 16:34:02 2018 -0500
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2012, 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.invoke.constant;
+
+import jdk.internal.lang.annotation.Foldable;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static java.lang.invoke.constant.ConstantRefs.CR_ClassRef;
+import static java.lang.invoke.constant.ConstantRefs.CR_MethodTypeRef;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * ConstantMethodTypeRef
+ *
+ * @author Brian Goetz
+ */
+public final class ConstantMethodTypeRef implements MethodTypeRef {
+
+    private static final Pattern TYPE_DESC = Pattern.compile("(\\[*)(V|I|J|S|B|C|F|D|Z|L[^/.\\[;][^.\\[;]*;)");
+    private static final Pattern pattern = Pattern.compile("\\((.*)\\)(.*)");
+
+    private final ClassRef returnType;
+    private final ClassRef[] argTypes;
+
+    /**
+     * Construct a {@linkplain MethodTypeRef} with the specified return type
+     * and parameter types
+     *
+     * @param returnType a {@link ClassRef} describing the return type
+     * @param argTypes {@link ClassRef}s describing the parameter types
+     */
+    ConstantMethodTypeRef(ClassRef returnType, ClassRef[] argTypes) {
+        this.returnType = requireNonNull(returnType);
+        this.argTypes = requireNonNull(argTypes);
+
+        for (ClassRef cr : argTypes)
+            if (cr.isPrimitive() && cr.descriptorString().equals("V"))
+                throw new IllegalArgumentException("Void parameters not permitted");
+    }
+
+    /**
+     * Create a {@linkplain ConstantMethodTypeRef} from a method descriptor string
+     *
+     * @param descriptor the method descriptor string
+     * @return a {@linkplain ConstantMethodTypeRef} describing the desired method type
+     * @throws IllegalArgumentException if the descriptor string is not a valid
+     * method descriptor
+     */
+    @Foldable
+    static MethodTypeRef ofDescriptor(String descriptor) {
+        // @@@ Replace validation with a lower-overhead mechanism than regex
+        // Follow the trail from MethodType.fromMethodDescriptorString to
+        // parsing code in sun/invoke/util/BytecodeDescriptor.java which could
+        // be extracted and/or shared
+        Matcher matcher = pattern.matcher(descriptor);
+        if (!matcher.matches())
+            throw new IllegalArgumentException(String.format("%s is not a valid method descriptor", descriptor));
+        String paramTypes = matcher.group(1);
+        String returnType = matcher.group(2);
+        if (!TYPE_DESC.matcher(returnType).matches())
+            throw new IllegalArgumentException(String.format("Invalid return type %s", returnType));
+        List<String> params = new ArrayList<>();
+        matcher = TYPE_DESC.matcher(paramTypes);
+        while (matcher.regionStart() < paramTypes.length()) {
+            if (matcher.lookingAt()) {
+                params.add(matcher.group());
+                matcher.region(matcher.end(), matcher.regionEnd());
+            }
+            else
+                throw new IllegalArgumentException(String.format("Invalid parameter type: %s", paramTypes.substring(matcher.regionStart(), matcher.regionEnd())));
+        }
+        return new ConstantMethodTypeRef(ClassRef.ofDescriptor(returnType), params.stream().map(ClassRef::ofDescriptor).toArray(ClassRef[]::new));
+    }
+
+    @Foldable
+    @Override
+    public ClassRef returnType() {
+        return returnType;
+    }
+
+    @Foldable
+    @Override
+    public int parameterCount() {
+        return argTypes.length;
+    }
+
+    @Foldable
+    @Override
+    public ClassRef parameterType(int index) {
+        return argTypes[index];
+    }
+
+    @Override
+    public List<ClassRef> parameterList() {
+        return List.of(argTypes);
+    }
+
+    @Override
+    public ClassRef[] parameterArray() {
+        return argTypes.clone();
+    }
+
+    @Foldable
+    @Override
+    public MethodTypeRef changeReturnType(ClassRef returnType) {
+        return MethodTypeRef.of(returnType, argTypes);
+    }
+
+    @Foldable
+    @Override
+    public MethodTypeRef changeParameterType(int index, ClassRef paramType) {
+        ClassRef[] newArgs = argTypes.clone();
+        newArgs[index] = paramType;
+        return MethodTypeRef.of(returnType, newArgs);
+    }
+
+    @Foldable
+    @Override
+    public MethodTypeRef 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));
+        ClassRef[] newArgs = new ClassRef[argTypes.length - (end - start)];
+        System.arraycopy(argTypes, 0, newArgs, 0, start);
+        System.arraycopy(argTypes, end, newArgs, start, argTypes.length - end);
+        return MethodTypeRef.of(returnType, newArgs);
+    }
+
+    @Foldable
+    @Override
+    public MethodTypeRef insertParameterTypes(int pos, ClassRef... paramTypes) {
+        if (pos < 0 || pos > argTypes.length)
+            throw new IndexOutOfBoundsException(pos);
+        ClassRef[] newArgs = new ClassRef[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 MethodTypeRef.of(returnType, newArgs);
+    }
+
+    @Override
+    public MethodType resolveConstantRef(MethodHandles.Lookup lookup) {
+        return MethodType.fromMethodDescriptorString(descriptorString(), lookup.lookupClass().getClassLoader());
+    }
+
+    @Override
+    public Optional<? extends ConstantRef<? super ConstantRef<MethodType>>> toConstantRef(MethodHandles.Lookup lookup) {
+        return Optional.of(DynamicConstantRef.of(RefBootstraps.BSM_METHODTYPEREF, CR_MethodTypeRef).withArgs(descriptorString()));
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        ConstantMethodTypeRef constant = (ConstantMethodTypeRef) 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("MethodTypeRef[%s]", simpleDescriptor());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/ConstantRef.java	Wed Mar 07 16:34:02 2018 -0500
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2012, 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.invoke.constant;
+
+import java.lang.invoke.Intrinsics;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+
+/**
+ * A nominal reference to a loadable constant value, as defined in JVMS 4.4.
+ * Such a nominal reference can be stored in the constant pool of a classfile
+ * and resolved to yield the constant value itself.
+ *
+ * <p>Static constants that are expressible natively in the constant pool ({@link String},
+ * {@link Integer}, {@link Long}, {@link Float}, and {@link Double}) implement
+ * {@link ConstantRef}, serve as nominal references for themselves.
+ * Native linkable constants ({@link Class}, {@link MethodType}, and
+ * {@link MethodHandle}) have counterpart {@linkplain ConstantRef} types:
+ * {@link ClassRef}, {@link MethodTypeRef}, and {@link MethodHandleRef}.
+ * Other constants are represented by subtypes of {@link DynamicConstantRef}.
+ *
+ * <p>Non-platform classes should not implement {@linkplain ConstantRef} directly.
+ * Instead, they should extend {@link DynamicConstantRef} (as {@link EnumRef}
+ * and {@link VarHandleRef} do.)
+ *
+ * <p>Constants can be reflectively resolved via {@link ConstantRef#resolveConstantRef(MethodHandles.Lookup)}.
+ *
+ * <p>Constants describing various useful nominal references (such as {@link ClassRef}
+ * instances for platform classes) can be found in {@link ConstantRefs}.
+ *
+ * <p>APIs that perform generation or parsing of bytecode are encouraged to use
+ * {@linkplain ConstantRef} to describe the operand of an {@code ldc} instruction
+ * (including dynamic constants), the static bootstrap arguments of
+ * dynamic constants and {@code invokedynamic} instructions, and other
+ * bytecodes or classfile structures that make use of the constant pool.
+ *
+ * <p>The {@linkplain ConstantRef} types are also used by {@link Intrinsics}
+ * to express {@code ldc} instructions.
+ *
+ * <p>Implementations of {@linkplain ConstantRef} must be
+ * <a href="../doc-files/ValueBased.html">value-based</a> classes.
+ *
+ * @apiNote In the future, if the Java language permits, {@linkplain ConstantRef}
+ * may become a {@code sealed} interface, which would prohibit subclassing except by
+ * explicitly permitted types.  Bytecode libraries can assume that the following
+ * is an exhaustive set of direct subtypes: {@link String}, {@link Integer},
+ * {@link Long}, {@link Float}, {@link Double}, {@link ClassRef},
+ * {@link MethodTypeRef}, {@link MethodHandleRef}, and {@link DynamicConstantRef}.
+ *
+ * @see Constable
+ * @see ConstantRef
+ * @see Intrinsics
+ * @see ConstantRefs
+ *
+ */
+public interface ConstantRef<T> {
+    /**
+     * Resolve this reference reflectively, using a {@link MethodHandles.Lookup}
+     * to resolve any type names into classes.
+     *
+     * @param lookup The {@link MethodHandles.Lookup} to be used in name resolution
+     * @return the resolved object
+     * @throws ReflectiveOperationException if this nominal reference refers
+     * (directly or indirectly) to a class, method, or field that cannot be
+     * resolved
+     */
+    T resolveConstantRef(MethodHandles.Lookup lookup) throws ReflectiveOperationException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/ConstantRefs.java	Wed Mar 07 16:34:02 2018 -0500
@@ -0,0 +1,324 @@
+/*
+ * Copyright (c) 2012, 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.invoke.constant;
+
+import jdk.internal.lang.annotation.Foldable;
+
+import java.lang.invoke.CallSite;
+import java.lang.invoke.ConstantBootstraps;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.VarHandle;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Predefined constants for common nominal references to constants.  Includes
+ * class references for primitive types and common platform types, and method
+ * handle references for standard bootstrap methods.
+ *
+ * @see ConstantRef
+ */
+public final class ConstantRefs {
+    // No instances
+    private ConstantRefs() { }
+
+    // Don't change the order of these declarations!
+
+    /** {@link ClassRef} representing {@link Object} */
+    @Foldable
+    public static final ClassRef CR_Object = ClassRef.of("java.lang.Object");
+
+    /** {@link ClassRef} representing {@link String} */
+    @Foldable
+    public static final ClassRef CR_String = ClassRef.of("java.lang.String");
+
+    /** {@link ClassRef} representing {@link Class} */
+    @Foldable
+    public static final ClassRef CR_Class = ClassRef.of("java.lang.Class");
+
+    /** {@link ClassRef} representing {@link Number} */
+    @Foldable
+    public static final ClassRef CR_Number = ClassRef.of("java.lang.Number");
+
+    /** {@link ClassRef} representing {@link Integer} */
+    @Foldable
+    public static final ClassRef CR_Integer = ClassRef.of("java.lang.Integer");
+
+    /** {@link ClassRef} representing {@link Long} */
+    @Foldable
+    public static final ClassRef CR_Long = ClassRef.of("java.lang.Long");
+
+    /** {@link ClassRef} representing {@link Float} */
+    @Foldable
+    public static final ClassRef CR_Float = ClassRef.of("java.lang.Float");
+
+    /** {@link ClassRef} representing {@link Double} */
+    @Foldable
+    public static final ClassRef CR_Double = ClassRef.of("java.lang.Double");
+
+    /** {@link ClassRef} representing {@link Short} */
+    @Foldable
+    public static final ClassRef CR_Short = ClassRef.of("java.lang.Short");
+
+    /** {@link ClassRef} representing {@link Byte} */
+    @Foldable
+    public static final ClassRef CR_Byte = ClassRef.of("java.lang.Byte");
+
+    /** {@link ClassRef} representing {@link Character} */
+    @Foldable
+    public static final ClassRef CR_Character = ClassRef.of("java.lang.Character");
+
+    /** {@link ClassRef} representing {@link Boolean} */
+    @Foldable
+    public static final ClassRef CR_Boolean = ClassRef.of("java.lang.Boolean");
+
+    /** {@link ClassRef} representing {@link Void} */
+    @Foldable
+    public static final ClassRef CR_Void = ClassRef.of("java.lang.Void");
+
+    /** {@link ClassRef} representing {@link Throwable} */
+    @Foldable
+    public static final ClassRef CR_Throwable = ClassRef.of("java.lang.Throwable");
+
+    /** {@link ClassRef} representing {@link Exception} */
+    @Foldable
+    public static final ClassRef CR_Exception = ClassRef.of("java.lang.Exception");
+
+    /** {@link ClassRef} representing {@link Enum} */
+    @Foldable
+    public static final ClassRef CR_Enum = ClassRef.of("java.lang.Enum");
+
+    /** {@link ClassRef} representing {@link VarHandle} */
+    @Foldable
+    public static final ClassRef CR_VarHandle = ClassRef.of("java.lang.invoke.VarHandle");
+
+    /** {@link ClassRef} representing {@link MethodHandles} */
+    @Foldable
+    public static final ClassRef CR_MethodHandles = ClassRef.of("java.lang.invoke.MethodHandles");
+
+    /** {@link ClassRef} representing {@link MethodHandles.Lookup} */
+    @Foldable
+    public static final ClassRef CR_MethodHandles_Lookup = CR_MethodHandles.inner("Lookup");
+
+    /** {@link ClassRef} representing {@link MethodHandle} */
+    @Foldable
+    public static final ClassRef CR_MethodHandle = ClassRef.of("java.lang.invoke.MethodHandle");
+
+    /** {@link ClassRef} representing {@link MethodType} */
+    @Foldable
+    public static final ClassRef CR_MethodType = ClassRef.of("java.lang.invoke.MethodType");
+
+    /** {@link ClassRef} representing {@link CallSite} */
+    @Foldable
+    public static final ClassRef CR_CallSite = ClassRef.of("java.lang.invoke.CallSite");
+
+    /** {@link ClassRef} representing {@link Collection} */
+    @Foldable
+    public static final ClassRef CR_Collection = ClassRef.of("java.util.Collection");
+
+    /** {@link ClassRef} representing {@link List} */
+    @Foldable
+    public static final ClassRef CR_List = ClassRef.of("java.util.List");
+
+    /** {@link ClassRef} representing {@link Set} */
+    @Foldable
+    public static final ClassRef CR_Set = ClassRef.of("java.util.Set");
+
+    /** {@link ClassRef} representing {@link Map} */
+    @Foldable
+    public static final ClassRef CR_Map = ClassRef.of("java.util.Map");
+
+    /** {@link ClassRef} representing {@link ConstantRef} */
+    @Foldable
+    static final ClassRef CR_ConstantRef = ClassRef.of("java.lang.invoke.constant.ConstantRef");
+
+    /** {@link ClassRef} representing {@link ClassRef} */
+    @Foldable
+    static final ClassRef CR_ClassRef = ClassRef.of("java.lang.invoke.constant.ClassRef");
+
+    /** {@link ClassRef} representing {@link EnumRef} */
+    @Foldable
+    static final ClassRef CR_EnumRef = ClassRef.of("java.lang.invoke.constant.EnumRef");
+
+    /** {@link ClassRef} representing {@link MethodTypeRef} */
+    @Foldable
+    static final ClassRef CR_MethodTypeRef = ClassRef.of("java.lang.invoke.constant.MethodTypeRef");
+
+    /** {@link ClassRef} representing {@link MethodHandleRef} */
+    @Foldable
+    static final ClassRef CR_MethodHandleRef = ClassRef.of("java.lang.invoke.constant.MethodHandleRef");
+
+    /** {@link ClassRef} representing {@link VarHandleRef} */
+    @Foldable
+    static final ClassRef CR_VarHandleRef = ClassRef.of("java.lang.invoke.constant.VarHandleRef");
+
+    /** {@link ClassRef} representing {@link MethodHandleRef.Kind} */
+    @Foldable
+    static final ClassRef CR_MethodHandleRef_Kind = CR_MethodHandleRef.inner("Kind");
+
+    /** {@link ClassRef} representing {@link DynamicConstantRef} */
+    @Foldable
+    static final ClassRef CR_DynamicConstantRef = ClassRef.of("java.lang.invoke.constant.DynamicConstantRef");
+
+    /** {@link ClassRef} representing {@link DynamicCallSiteRef} */
+    @Foldable
+    static final ClassRef CR_DynamicCallSiteRef = ClassRef.of("java.lang.invoke.constant.DynamicCallSiteRef");
+
+    /** {@link ClassRef} representing {@link ConstantBootstraps} */
+    @Foldable
+    static final ClassRef CR_ConstantBootstraps = ClassRef.of("java.lang.invoke.ConstantBootstraps");
+
+    // Used by MethodHandleRef, but initialized here before reference to
+    // MethodHandleRef to avoid static initalization circularities
+    static final ClassRef[] INDY_BOOTSTRAP_ARGS = {
+            ConstantRefs.CR_MethodHandles_Lookup,
+            ConstantRefs.CR_String,
+            ConstantRefs.CR_MethodType };
+
+    static final ClassRef[] CONDY_BOOTSTRAP_ARGS = {
+            ConstantRefs.CR_MethodHandles_Lookup,
+            ConstantRefs.CR_String,
+            ConstantRefs.CR_Class };
+
+    /** {@link MethodHandleRef} representing {@link ConstantBootstraps#primitiveClass(Lookup, String, Class)} */
+    @Foldable
+    public static final MethodHandleRef BSM_PRIMITIVE_CLASS
+            = MethodHandleRef.ofDynamicConstant(CR_ConstantBootstraps, "primitiveClass", CR_Class);
+
+    /** {@link MethodHandleRef} representing {@link ConstantBootstraps#enumConstant(Lookup, String, Class)} */
+    @Foldable
+    public static final MethodHandleRef BSM_ENUM_CONSTANT
+            = MethodHandleRef.ofDynamicConstant(CR_ConstantBootstraps, "enumConstant", CR_Enum);
+
+    /** {@link MethodHandleRef} representing {@link ConstantBootstraps#nullConstant(Lookup, String, Class)} */
+    @Foldable
+    public static final MethodHandleRef BSM_NULL_CONSTANT
+            = MethodHandleRef.ofDynamicConstant(CR_ConstantBootstraps, "nullConstant", ConstantRefs.CR_Object);
+
+    /** {@link MethodHandleRef} representing {@link ConstantBootstraps#fieldVarHandle(Lookup, String, Class, Class, Class)} */
+    @Foldable
+    public static final MethodHandleRef BSM_VARHANDLE_FIELD
+            = MethodHandleRef.ofDynamicConstant(CR_ConstantBootstraps, "fieldVarHandle", CR_VarHandle, CR_Class, CR_Class);
+
+    /** {@link MethodHandleRef} representing {@link ConstantBootstraps#staticFieldVarHandle(Lookup, String, Class, Class, Class)} */
+    @Foldable
+    public static final MethodHandleRef BSM_VARHANDLE_STATIC_FIELD
+            = MethodHandleRef.ofDynamicConstant(CR_ConstantBootstraps, "staticFieldVarHandle", CR_VarHandle, CR_Class, CR_Class);
+
+    /** {@link MethodHandleRef} representing {@link ConstantBootstraps#arrayVarHandle(Lookup, String, Class, Class)} */
+    @Foldable
+    public static final MethodHandleRef BSM_VARHANDLE_ARRAY
+            = MethodHandleRef.ofDynamicConstant(CR_ConstantBootstraps, "arrayVarHandle", CR_VarHandle, CR_Class);
+
+    /** {@link MethodHandleRef} representing {@link ConstantBootstraps#invoke(Lookup, String, Class, MethodHandle, Object...)} */
+    @Foldable
+    public static final MethodHandleRef BSM_INVOKE
+            = MethodHandleRef.ofDynamicConstant(CR_ConstantBootstraps, "invoke", CR_Object, CR_MethodHandle, CR_Object.array());
+
+    /** {@link ClassRef} representing the primitive type {@code int} */
+    @Foldable
+    public static final ClassRef CR_int = ClassRef.ofDescriptor("I");
+
+    /** {@link ClassRef} representing the primitive type {@code long} */
+    @Foldable
+    public static final ClassRef CR_long = ClassRef.ofDescriptor("J");
+
+    /** {@link ClassRef} representing the primitive type {@code float} */
+    @Foldable
+    public static final ClassRef CR_float = ClassRef.ofDescriptor("F");
+
+    /** {@link ClassRef} representing the primitive type {@code double} */
+    @Foldable
+    public static final ClassRef CR_double = ClassRef.ofDescriptor("D");
+
+    /** {@link ClassRef} representing the primitive type {@code short} */
+    @Foldable
+    public static final ClassRef CR_short = ClassRef.ofDescriptor("S");
+
+    /** {@link ClassRef} representing the primitive type {@code byte} */
+    @Foldable
+    public static final ClassRef CR_byte = ClassRef.ofDescriptor("B");
+
+    /** {@link ClassRef} representing the primitive type {@code char} */
+    @Foldable
+    public static final ClassRef CR_char = ClassRef.ofDescriptor("C");
+
+    /** {@link ClassRef} representing the primitive type {@code boolean} */
+    @Foldable
+    public static final ClassRef CR_boolean = ClassRef.ofDescriptor("Z");
+
+    /** {@link ClassRef} representing the primitive type {@code void} */
+    @Foldable
+    public static final ClassRef CR_void = ClassRef.ofDescriptor("V");
+
+    /** Nominal reference representing the constant {@code null} */
+    @Foldable
+    public static final ConstantRef<?> NULL = DynamicConstantRef.of(ConstantRefs.BSM_NULL_CONSTANT, ConstantRefs.CR_Object);
+
+    // Used by XxxRef classes, but need to be hear to avoid bootstrap cycles
+    static final MethodHandleRef MHR_METHODTYPEREF_FACTORY
+            = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_MethodTypeRef, "ofDescriptor", CR_MethodTypeRef, CR_String);
+
+    static final MethodHandleRef MHR_CLASSREF_FACTORY
+            = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_ClassRef, "ofDescriptor", CR_ClassRef, CR_String);
+
+    static final MethodHandleRef MHR_METHODHANDLEREF_FACTORY
+            = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_MethodHandleRef, "of",
+                                 CR_MethodHandleRef, CR_MethodHandleRef_Kind, CR_ClassRef, CR_String, CR_MethodTypeRef);
+
+    static final MethodHandleRef MHR_METHODHANDLE_ASTYPE
+            = MethodHandleRef.of(MethodHandleRef.Kind.VIRTUAL, CR_MethodHandle, "asType", CR_MethodHandle, CR_MethodType);
+
+    static final MethodHandleRef MHR_METHODHANDLEREF_ASTYPE
+            = MethodHandleRef.of(MethodHandleRef.Kind.VIRTUAL, CR_MethodHandleRef, "asType", CR_MethodHandleRef, CR_MethodTypeRef);
+
+    static final MethodHandleRef MHR_DYNAMICCONSTANTREF_FACTORY
+            = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_DynamicConstantRef, "of",
+                                 CR_DynamicConstantRef, CR_MethodHandleRef, CR_String, CR_ClassRef);
+
+    static final MethodHandleRef MHR_DYNAMICCONSTANTREF_WITHARGS
+            = MethodHandleRef.of(MethodHandleRef.Kind.VIRTUAL, CR_DynamicConstantRef, "withArgs",
+                                 CR_DynamicConstantRef, CR_ConstantRef.array());
+
+    static final MethodHandleRef MHR_ENUMREF_FACTORY
+            = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_EnumRef, "of", CR_EnumRef, CR_ClassRef, CR_String);
+
+    static final MethodHandleRef MHR_VARHANDLEREF_OFFIELD
+            = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_VarHandleRef, "ofField",
+                                 CR_VarHandleRef, CR_ClassRef, CR_String, CR_ClassRef);
+
+    static final MethodHandleRef MHR_VARHANDLEREF_OFSTATIC
+            = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_VarHandleRef, "ofStaticField",
+                                 CR_VarHandleRef, CR_ClassRef, CR_String, CR_ClassRef);
+
+    static final MethodHandleRef MHR_VARHANDLEREF_OFARRAY
+            = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_VarHandleRef, "ofArray",
+                                 CR_VarHandleRef, CR_ClassRef);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/DynamicCallSiteRef.java	Wed Mar 07 16:34:02 2018 -0500
@@ -0,0 +1,257 @@
+/*
+ * 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.invoke.constant;
+
+import jdk.internal.lang.annotation.Foldable;
+
+import java.lang.invoke.CallSite;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.util.Arrays;
+import java.util.Objects;
+
+import static java.lang.invoke.constant.ConstantRefs.CR_String;
+
+/**
+ * A nominal reference for an {@code invokedynamic} call site.
+ */
+@SuppressWarnings("rawtypes")
+public final class DynamicCallSiteRef {
+    private static final ConstantRef<?>[] EMPTY_ARGS = new ConstantRef<?>[0];
+
+    private final MethodHandleRef bootstrapMethod;
+    private final ConstantRef<?>[] bootstrapArgs;
+    private final String name;
+    private final MethodTypeRef type;
+
+    /**
+     * Construct a nominal reference for an {@code invokedynamic} call site
+     *
+     * @param bootstrapMethod The bootstrap method for the {@code invokedynamic}
+     * @param name The name that would appear in the {@code NameAndType} operand
+     *             of the {@code invokedynamic}
+     * @param type The invocation type that would appear in the {@code NameAndType} operand
+     *             of the {@code invokedynamic}
+     * @param bootstrapArgs The static arguments to the bootstrap, that would
+     *                      appear in the {@code BootstrapMethods} attribute
+     * @throws NullPointerException if any parameter is null
+     */
+    private DynamicCallSiteRef(MethodHandleRef bootstrapMethod,
+                               String name,
+                               MethodTypeRef type,
+                               ConstantRef<?>[] bootstrapArgs) {
+        this.name = Objects.requireNonNull(name);
+        this.type = Objects.requireNonNull(type);
+        this.bootstrapMethod = Objects.requireNonNull(bootstrapMethod);
+        this.bootstrapArgs = Objects.requireNonNull(bootstrapArgs.clone());
+    }
+
+    /**
+     * Return a nominal reference for an {@code invokedynamic} call site.  If
+     * the bootstrap method corresponds to a well-known bootstrap, for which a
+     * more specific nominal reference type exists, the more specific nominal
+     * reference type is returned.
+     *
+     * @param bootstrapMethod The bootstrap method for the {@code invokedynamic}
+     * @param name The name that would appear in the {@code NameAndType} operand
+     *             of the {@code invokedynamic}
+     * @param type The invocation type that would appear in the {@code NameAndType} operand
+     *             of the {@code invokedynamic}
+     * @param bootstrapArgs The static arguments to the bootstrap, that would
+     *                      appear in the {@code BootstrapMethods} attribute
+     * @return the nominal reference
+     * @throws NullPointerException if any parameter is null
+     */
+    @Foldable
+    public static DynamicCallSiteRef ofCanonical(MethodHandleRef bootstrapMethod, String name, MethodTypeRef type, ConstantRef<?>... bootstrapArgs) {
+        DynamicCallSiteRef ref = new DynamicCallSiteRef(bootstrapMethod, name, type, bootstrapArgs);
+        return ref.canonicalize();
+    }
+
+    /**
+     * Return a nominal reference for an {@code invokedynamic} call site.
+     *
+     * @param bootstrapMethod The bootstrap method for the {@code invokedynamic}
+     * @param name The name that would appear in the {@code NameAndType} operand
+     *             of the {@code invokedynamic}
+     * @param type The invocation type that would appear in the {@code NameAndType} operand
+     *             of the {@code invokedynamic}
+     * @param bootstrapArgs The static arguments to the bootstrap, that would
+     *                      appear in the {@code BootstrapMethods} attribute
+     * @return the nominal reference
+     * @throws NullPointerException if any parameter is null
+     */
+    @Foldable
+    public static DynamicCallSiteRef of(MethodHandleRef bootstrapMethod, String name, MethodTypeRef type, ConstantRef<?>... bootstrapArgs) {
+        return new DynamicCallSiteRef(bootstrapMethod, name, type, bootstrapArgs);
+    }
+
+    /**
+     * Return a nominal reference for an {@code invokedynamic} call site whose
+     * bootstrap method has no static arguments.
+     *
+     * @param bootstrapMethod The bootstrap method for the {@code invokedynamic}
+     * @param name The name that would appear in the {@code NameAndType} operand
+     *             of the {@code invokedynamic}
+     * @param type The invocation type that would appear in the {@code NameAndType} operand
+     *             of the {@code invokedynamic}
+     * @return the nominal reference
+     * @throws NullPointerException if any parameter is null
+     */
+    @Foldable
+    public static DynamicCallSiteRef of(MethodHandleRef bootstrapMethod, String name, MethodTypeRef type) {
+        return new DynamicCallSiteRef(bootstrapMethod, name, type, EMPTY_ARGS);
+    }
+
+    /**
+     * Return a nominal reference for an {@code invokedynamic} call site whose
+     * bootstrap method has no static arguments and whose name parameter is ignored.
+     *
+     * @param bootstrapMethod The bootstrap method for the {@code invokedynamic}
+     * @param type The invocation type that would appear in the {@code NameAndType} operand
+     *             of the {@code invokedynamic}
+     * @return the nominal reference
+     * @throws NullPointerException if any parameter is null
+     */
+    @Foldable
+    public static DynamicCallSiteRef of(MethodHandleRef bootstrapMethod, MethodTypeRef type) {
+        return of(bootstrapMethod, "_", type);
+    }
+
+    /**
+     * Return a nominal reference for an {@code invokedynamic} call site whose
+     * bootstrap method, name, and invocation type are the same as this one, but
+     * with the specified bootstrap arguments.
+     *
+     * @param bootstrapArgs The static arguments to the bootstrap, that would
+     *                      appear in the {@code BootstrapMethods} attribute
+     * @return the nominal reference
+     * @throws NullPointerException if any parameter is null
+     */
+    @Foldable
+    public DynamicCallSiteRef withArgs(ConstantRef<?>... bootstrapArgs) {
+        return new DynamicCallSiteRef(bootstrapMethod, name, type, bootstrapArgs);
+    }
+
+    /**
+     * Return a nominal reference for an {@code invokedynamic} call site whose
+     * bootstrap and bootstrap arguments are the same as this one, but with the
+     * specified name and invocation type
+     *
+     * @param name The name that would appear in the {@code NameAndType} operand
+     *             of the {@code invokedynamic}
+     * @param type The invocation type that would appear in the {@code NameAndType} operand
+     *             of the {@code invokedynamic}
+     * @return the nominal reference
+     * @throws NullPointerException if any parameter is null
+     */
+    @Foldable
+    public DynamicCallSiteRef withNameAndType(String name, MethodTypeRef type) {
+        return new DynamicCallSiteRef(bootstrapMethod, name, type, bootstrapArgs);
+    }
+
+    private DynamicCallSiteRef canonicalize() {
+        // @@@ MethodRef
+        return this;
+    }
+
+    /**
+     * Returns the invocation name that would appear in the {@code NameAndType} operand
+     * of the {@code invokedynamic}
+     * @return the invocation name
+     */
+    @Foldable
+    public String name() {
+        return name;
+    }
+
+    /**
+     * Returns the invocation type that would appear in the {@code NameAndType} operand
+     * of the {@code invokedynamic}
+     * @return the invocation type
+     */
+    @Foldable
+    public MethodTypeRef type() {
+        return type;
+    }
+
+    /**
+     * Returns the bootstrap method for the {@code invokedynamic}
+     * @return the bootstrap method for the {@code invokedynamic}
+     */
+    @Foldable
+    public MethodHandleRef bootstrapMethod() { return bootstrapMethod; }
+
+    /**
+     * Returns the bootstrap arguments for the {@code invokedynamic}
+     * @return the bootstrap arguments for the {@code invokedynamic}
+     */
+    public ConstantRef<?>[] bootstrapArgs() { return bootstrapArgs.clone(); }
+
+    /**
+     * Reflectively invokes the bootstrap method, and returns a dynamic invoker
+     * {@link MethodHandle} for the returned {@link CallSite}
+     *
+     * @param lookup The {@link MethodHandles.Lookup} used to resolve class names
+     * @return the dynamic invoker
+     * @throws Throwable if any exception is thrown by the bootstrap method
+     *
+     * @see CallSite#dynamicInvoker()
+     */
+    public MethodHandle dynamicInvoker(MethodHandles.Lookup lookup) throws Throwable {
+        assert bootstrapMethod.methodType().parameterType(1).equals(CR_String);
+        MethodHandle bsm = bootstrapMethod.resolveConstantRef(lookup);
+        Object[] args = new Object[bootstrapArgs.length + 3];
+        args[0] = lookup;
+        args[1] = name;
+        args[2] = type.resolveConstantRef(lookup);
+        System.arraycopy(bootstrapArgs, 0, args, 3, bootstrapArgs.length);
+        CallSite callSite = (CallSite) bsm.invokeWithArguments(args);
+        return callSite.dynamicInvoker();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        DynamicCallSiteRef specifier = (DynamicCallSiteRef) o;
+        return Objects.equals(bootstrapMethod, specifier.bootstrapMethod) &&
+               Arrays.equals(bootstrapArgs, specifier.bootstrapArgs) &&
+               Objects.equals(name, specifier.name) &&
+               Objects.equals(type, specifier.type);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = Objects.hash(bootstrapMethod, name, type);
+        result = 31 * result + Arrays.hashCode(bootstrapArgs);
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("DynamicCallSiteRef[%s(%s) %s%s]", bootstrapMethod, Arrays.toString(bootstrapArgs), name, type);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/DynamicConstantRef.java	Wed Mar 07 16:34:02 2018 -0500
@@ -0,0 +1,403 @@
+/*
+ * Copyright (c) 2012, 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.invoke.constant;
+
+import jdk.internal.lang.annotation.Foldable;
+
+import java.lang.invoke.ConstantBootstraps;
+import java.lang.invoke.MethodHandles;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import static java.lang.invoke.constant.ConstantRefs.CR_DynamicConstantRef;
+import static java.util.Objects.requireNonNull;
+import static java.util.stream.Collectors.joining;
+
+/**
+ * A nominal reference for a dynamic constant (one described in the constant
+ * pool with {@code Constant_Dynamic_info}.)
+ *
+ * <p>Concrete subtypes of {@linkplain DynamicConstantRef} must be
+ * <a href="../doc-files/ValueBased.html">value-based</a>.
+ *
+ * @param <T> the type of the dynamic constant
+ */
+public abstract class DynamicConstantRef<T> implements ConstantRef<T>, Constable<ConstantRef<T>> {
+    private final ConstantMethodHandleRef bootstrapMethod;
+    private final ConstantRef<?>[] bootstrapArgs;
+    private final String name;
+    private final ClassRef type;
+
+    @SuppressWarnings("rawtypes")
+    private static final Map<MethodHandleRef, Function<DynamicConstantRef, ConstantRef<?>>> canonicalMap
+            = Map.ofEntries(Map.entry(ConstantRefs.BSM_PRIMITIVE_CLASS, d -> ClassRef.ofDescriptor(d.name)),
+                            Map.entry(ConstantRefs.BSM_ENUM_CONSTANT, d -> EnumRef.of(d.type, d.name)),
+                            Map.entry(ConstantRefs.BSM_NULL_CONSTANT, d -> ConstantRefs.NULL),
+                            Map.entry(ConstantRefs.BSM_VARHANDLE_STATIC_FIELD,
+                                      d -> VarHandleRef.ofStaticField((ClassRef) d.bootstrapArgs[0],
+                                                                      (String) d.bootstrapArgs[1],
+                                                                      (ClassRef) d.bootstrapArgs[2])),
+                            Map.entry(ConstantRefs.BSM_VARHANDLE_FIELD,
+                                      d -> VarHandleRef.ofField((ClassRef) d.bootstrapArgs[0],
+                                                                (String) d.bootstrapArgs[1],
+                                                                (ClassRef) d.bootstrapArgs[2])),
+                            Map.entry(ConstantRefs.BSM_VARHANDLE_ARRAY,
+                                      d -> VarHandleRef.ofArray((ClassRef) d.bootstrapArgs[0]))
+    );
+
+    /**
+     * Construct a nominal reference for a dynamic constant
+     *
+     * @param bootstrapMethod The bootstrap method for the constant
+     * @param name The name that would appear in the {@code NameAndType} operand
+     *             of the {@code LDC} for this constant
+     * @param type The type that would appear in the {@code NameAndType} operand
+     *             of the {@code LDC} for this constant
+     * @param bootstrapArgs The static arguments to the bootstrap, that would
+     *                      appear in the {@code BootstrapMethods} attribute
+     * @throws NullPointerException if any argument is null
+     * @throws IllegalArgumentException if the bootstrap method is not a
+     * {@link ConstantMethodHandleRef}
+     * @throws IllegalArgumentException if {@code name.length()} is zero
+     */
+    protected DynamicConstantRef(MethodHandleRef bootstrapMethod, String name, ClassRef type, ConstantRef<?>... bootstrapArgs) {
+        requireNonNull(bootstrapMethod);
+        if (!(bootstrapMethod instanceof ConstantMethodHandleRef))
+            throw new IllegalArgumentException("bootstrap method must be a ConstantMethodHandleRef");
+        this.bootstrapMethod = (ConstantMethodHandleRef) bootstrapMethod;
+        this.name = requireNonNull(name);
+        this.type = requireNonNull(type);
+        this.bootstrapArgs = requireNonNull(bootstrapArgs).clone();
+
+        if (name.length() == 0)
+            throw new IllegalArgumentException("Illegal invocation name: " + name);
+    }
+
+    /**
+     * Return a nominal reference for a dynamic constant whose bootstrap, invocation
+     * name, and invocation type are the same as this one, but with the specified
+     * bootstrap arguments
+     *
+     * @param bootstrapArgs the bootstrap arguments
+     * @return the nominal reference
+     * @throws NullPointerException if any argument is null
+     */
+    @Foldable
+    public DynamicConstantRef<T> withArgs(ConstantRef<?>... bootstrapArgs) {
+        return new DynamicConstantRefImpl<>(bootstrapMethod, name, type, bootstrapArgs);
+    }
+
+    /**
+     * Return a nominal reference for a dynamic constant.  If  the bootstrap
+     * corresponds to a well-known bootstrap, for which a more specific nominal
+     * reference type (e.g., ClassRef) is available, then the more specific
+     * nominal reference will be returned.
+     *
+     * @param <T> the type of the dynamic constant
+     * @param bootstrapMethod The bootstrap method for the constant
+     * @param name The name that would appear in the {@code NameAndType} operand
+     *             of the {@code LDC} for this constant
+     * @param type The type that would appear in the {@code NameAndType} operand
+     *             of the {@code LDC} for this constant
+     * @param bootstrapArgs The static arguments to the bootstrap, that would
+     *                      appear in the {@code BootstrapMethods} attribute
+     * @return the nominal reference
+     * @throws NullPointerException if any argument is null
+     * @throws IllegalArgumentException if {@code name.length()} is zero
+     */
+    @Foldable
+    public static<T> ConstantRef<T> ofCanonical(MethodHandleRef bootstrapMethod, String name, ClassRef type, ConstantRef<?>[] bootstrapArgs) {
+        DynamicConstantRef<T> dcr = new DynamicConstantRefImpl<>(bootstrapMethod, name, type, bootstrapArgs);
+        return dcr.canonicalize();
+    }
+
+    private ConstantRef<T> canonicalize() {
+        // @@@ Existing map-based approach is cute but not very robust; need to add more checking of target DCRef
+        @SuppressWarnings("rawtypes")
+        Function<DynamicConstantRef, ConstantRef<?>> f = canonicalMap.get(bootstrapMethod);
+        if (f != null) {
+            @SuppressWarnings("unchecked")
+            ConstantRef<T> converted = (ConstantRef<T>) f.apply(this);
+            return converted;
+        }
+        return this;
+    }
+
+    /**
+     * Return a nominal reference for a dynamic constant.
+     *
+     * @param <T> the type of the dynamic constant
+     * @param bootstrapMethod The bootstrap method for the constant
+     * @param name The name that would appear in the {@code NameAndType} operand
+     *             of the {@code LDC} for this constant
+     * @param type The type that would appear in the {@code NameAndType} operand
+     *             of the {@code LDC} for this constant
+     * @param bootstrapArgs The static arguments to the bootstrap, that would
+     *                      appear in the {@code BootstrapMethods} attribute
+     * @return the nominal reference
+     * @throws NullPointerException if any argument is null
+     * @throws IllegalArgumentException if {@code name.length()} is zero
+     */
+    @Foldable
+    public static<T> DynamicConstantRef<T> of(MethodHandleRef bootstrapMethod, String name, ClassRef type, ConstantRef<?>[] bootstrapArgs) {
+        return new DynamicConstantRefImpl<>(bootstrapMethod, name, type, bootstrapArgs);
+    }
+
+    /**
+     * Return a nominal reference for a dynamic constant whose bootstrap has
+     * no static arguments.
+     *
+     * @param <T> the type of the dynamic constant
+     * @param bootstrapMethod The bootstrap method for the constant
+     * @param name The name that would appear in the {@code NameAndType} operand
+     *             of the {@code LDC} for this constant
+     * @param type The type that would appear in the {@code NameAndType} operand
+     *             of the {@code LDC} for this constant
+     * @return the nominal reference
+     * @throws NullPointerException if any argument is null
+     * @throws IllegalArgumentException if {@code name.length()} is zero
+     */
+    @Foldable
+    public static<T> DynamicConstantRef<T> of(MethodHandleRef bootstrapMethod, String name, ClassRef type) {
+        return new DynamicConstantRefImpl<>(bootstrapMethod, name, type);
+    }
+
+    /**
+     * Return a nominal reference for a dynamic constant whose bootstrap has
+     * no static arguments, and whose name parameter is ignored by the bootstrap
+     *
+     * @param <T> the type of the dynamic constant
+     * @param bootstrapMethod The bootstrap method for the constant
+     * @param type The type that would appear in the {@code NameAndType} operand
+     *             of the {@code LDC} for this constant
+     * @return the nominal reference
+     * @throws NullPointerException if any argument is null
+     * @throws IllegalArgumentException if {@code name.length()} is zero
+     */
+    @Foldable
+    public static<T> DynamicConstantRef<T> of(MethodHandleRef bootstrapMethod, ClassRef type) {
+        return of(bootstrapMethod, "_", type);
+    }
+
+    /**
+     * Return a nominal reference for a dynamic constant whose bootstrap has
+     * no static arguments, and whose type parameter is always the same as the
+     * bootstrap method return type.
+     *
+     * @param <T> the type of the dynamic constant
+     * @param bootstrapMethod The bootstrap method for the constant
+     * @param name The name that would appear in the {@code NameAndType} operand
+     *             of the {@code LDC} for this constant
+     * @return the nominal reference
+     * @throws NullPointerException if any argument is null
+     * @throws IllegalArgumentException if {@code name.length()} is zero
+     */
+    @Foldable
+    public static<T> DynamicConstantRef<T> of(MethodHandleRef bootstrapMethod, String name) {
+        return of(bootstrapMethod, name, bootstrapMethod.methodType().returnType());
+    }
+
+    /**
+     * Return a nominal reference for a dynamic constant whose bootstrap has
+     * no static arguments, whose name parameter is ignored, and whose type
+     * parameter is always the same as the bootstrap method return type.
+     *
+     * @param <T> the type of the dynamic constant
+     * @param bootstrapMethod The bootstrap method for the constant
+     * @return the nominal reference
+     * @throws NullPointerException if any argument is null
+     * @throws IllegalArgumentException if {@code name.length()} is zero
+     */
+    @Foldable
+    public static<T> DynamicConstantRef<T> of(MethodHandleRef bootstrapMethod) {
+        return of(bootstrapMethod, "_");
+    }
+
+    /**
+     * returns The name that would appear in the {@code NameAndType} operand
+     *             of the {@code LDC} for this constant
+     * @return the name
+     */
+    @Foldable
+    public String constantName() {
+        return name;
+    }
+
+    /**
+     * returns The type that would appear in the {@code NameAndType} operand
+     *             of the {@code LDC} for this constant
+     * @return the type
+     */
+    @Foldable
+    public ClassRef constantType() {
+        return type;
+    }
+
+    /**
+     * Returns the bootstrap method for this constant
+     * @return the bootstrap method
+     */
+    @Foldable
+    public MethodHandleRef bootstrapMethod() { return bootstrapMethod; }
+
+    /**
+     * Returns the bootstrap arguments for this constant
+     * @return the bootstrap arguments
+     */
+    public ConstantRef<?>[] bootstrapArgs() { return bootstrapArgs.clone(); }
+
+    private static Object[] resolveArgs(MethodHandles.Lookup lookup, ConstantRef<?>[] args)
+            throws ReflectiveOperationException {
+        try {
+            return Stream.of(args)
+                    .map(arg -> {
+                        try {
+                            return arg.resolveConstantRef(lookup);
+                        }
+                        catch (ReflectiveOperationException e) {
+                            throw new RuntimeException(e);
+                        }
+                    })
+                    .toArray();
+        }
+        catch (RuntimeException e) {
+            if (e.getCause() instanceof ReflectiveOperationException) {
+                throw (ReflectiveOperationException) e.getCause();
+            }
+            else {
+                throw e;
+            }
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public T resolveConstantRef(MethodHandles.Lookup lookup) throws ReflectiveOperationException {
+        return (T) ConstantBootstraps.makeConstant(bootstrapMethod.resolveConstantRef(lookup),
+                                                   name,
+                                                   type.resolveConstantRef(lookup),
+                                                   resolveArgs(lookup, bootstrapArgs),
+                                                   // TODO pass lookup
+                                                   lookup.lookupClass());
+    }
+
+    @Override
+    public Optional<? extends ConstantRef<? super ConstantRef<T>>> toConstantRef(MethodHandles.Lookup lookup) {
+        ConstantRef<?>[] args = new ConstantRef<?>[bootstrapArgs.length + 5];
+        args[0] = bootstrapMethod.owner().descriptorString();
+        args[1] = bootstrapMethod.methodName();
+        args[2] = bootstrapMethod.methodType().descriptorString();
+        args[3] = name;
+        args[4] = type.descriptorString();
+        System.arraycopy(bootstrapArgs, 0, args, 5, bootstrapArgs.length);
+        return Optional.of(DynamicConstantRef.of(RefBootstraps.BSM_DYNAMICCONSTANTREF, "_", CR_DynamicConstantRef, args));
+    }
+
+    /**
+     * Produce a {@linkplain DynamicConstantRef} describing the invocation of
+     * the specified bootstrap with the specified arguments.
+     *
+     * @param bootstrap nominal reference for the bootstrap method
+     * @param type nominal reference for the type of the resulting constant
+     * @param args nominal references for the bootstrap arguments
+     * @param <T> the type of the resulting constant
+     * @return the dynamic constant reference
+     */
+    protected static<T> DynamicConstantRef<T> ofInvoke(MethodHandleRef bootstrap,
+                                                       ClassRef type,
+                                                       ConstantRef<?>... args) {
+        ConstantRef<?>[] quotedArgs = new ConstantRef<?>[args.length + 1];
+        quotedArgs[0] = bootstrap;
+        System.arraycopy(args, 0, quotedArgs, 1, args.length);
+        return DynamicConstantRef.of(ConstantRefs.BSM_INVOKE, "_", type, quotedArgs);
+    }
+
+    /**
+     * Produce an {@code Optional<DynamicConstantRef<T>>} describing the invocation
+     * of the specified bootstrap with the specified arguments.  The arguments will
+     * be converted to nominal references using the provided lookup.
+     *
+     * @param lookup A {@link MethodHandles.Lookup} to be used to perform
+     *               access control determinations
+     * @param bootstrap nominal reference for the bootstrap method
+     * @param type nominal reference for the type of the resulting constant
+     * @param args nominal references for the bootstrap arguments
+     * @param <T> the type of the resulting constant
+     * @return the dynamic constant reference
+     */
+    static<T> Optional<DynamicConstantRef<T>> symbolizeHelper(MethodHandles.Lookup lookup,
+                                                              MethodHandleRef bootstrap,
+                                                              ClassRef type,
+                                                              Constable<?>... args) {
+        try {
+            ConstantRef<?>[] quotedArgs = new ConstantRef<?>[args.length + 1];
+            quotedArgs[0] = bootstrap;
+            for (int i=0; i<args.length; i++)
+                quotedArgs[i+1] = args[i].toConstantRef(lookup).orElseThrow();
+            return Optional.of(DynamicConstantRef.of(ConstantRefs.BSM_INVOKE, "_", type, quotedArgs));
+        }
+        catch (NoSuchElementException e) {
+            return Optional.empty();
+        }
+    }
+
+    @Override
+    public final boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof DynamicConstantRef)) return false;
+        DynamicConstantRef<?> ref = (DynamicConstantRef<?>) o;
+        return Objects.equals(bootstrapMethod, ref.bootstrapMethod) &&
+               Arrays.equals(bootstrapArgs, ref.bootstrapArgs) &&
+               Objects.equals(name, ref.name) &&
+               Objects.equals(type, ref.type);
+    }
+
+    @Override
+    public final int hashCode() {
+        int result = Objects.hash(bootstrapMethod, name, type);
+        result = 31 * result + Arrays.hashCode(bootstrapArgs);
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("DynamicConstantRef[%s::%s(%s%s)%s]",
+                             bootstrapMethod.owner().simpleName(),
+                             bootstrapMethod.methodName(),
+                             name.equals("_") ? "" : name + "/",
+                             Stream.of(bootstrapArgs).map(Object::toString).collect(joining(",")),
+                             type.simpleName());
+    }
+
+    private static final class DynamicConstantRefImpl<T> extends DynamicConstantRef<T> {
+        DynamicConstantRefImpl(MethodHandleRef bootstrapMethod, String name, ClassRef type, ConstantRef<?>... bootstrapArgs) {
+            super(bootstrapMethod, name, type, bootstrapArgs);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/EnumRef.java	Wed Mar 07 16:34:02 2018 -0500
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2012, 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.invoke.constant;
+
+import jdk.internal.lang.annotation.Foldable;
+
+import java.lang.invoke.MethodHandles;
+import java.util.Optional;
+
+import static java.lang.invoke.constant.ConstantRefs.CR_ClassRef;
+import static java.lang.invoke.constant.ConstantRefs.CR_EnumRef;
+import static java.lang.invoke.constant.ConstantRefs.CR_String;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * A symbolic reference for an {@code enum} constant.
+ *
+ * @param <E> the type of the enum constant
+ */
+public final class EnumRef<E extends Enum<E>> extends DynamicConstantRef<E> {
+
+    /**
+     * Construct a symbolic reference for the specified enum class and name
+     *
+     * @param constantType the enum class
+     * @param constantName the name of the enum constant
+     * @throws NullPointerException if any argument is null
+     */
+    private EnumRef(ClassRef constantType, String constantName) {
+        super(ConstantRefs.BSM_ENUM_CONSTANT, requireNonNull(constantName), requireNonNull(constantType));
+    }
+
+    /**
+     * Return a symbolic reference for the specified enum class and name
+     *
+     * @param <E> the type of the enum constant
+     * @param enumClass the enum class
+     * @param constantName the name of the enum constant
+     * @return the symbolic reference
+     * @throws NullPointerException if any argument is null
+     */
+    @Foldable
+    public static<E extends Enum<E>> EnumRef<E> of(ClassRef enumClass, String constantName) {
+        return new EnumRef<>(enumClass, constantName);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public E resolveConstantRef(MethodHandles.Lookup lookup) throws ReflectiveOperationException {
+        return Enum.valueOf((Class<E>) constantType().resolveConstantRef(lookup), constantName());
+    }
+
+    @Override
+    public Optional<? extends ConstantRef<? super ConstantRef<E>>> toConstantRef(MethodHandles.Lookup lookup) {
+        return Optional.of(DynamicConstantRef.of(RefBootstraps.BSM_ENUMREF, CR_EnumRef).withArgs(constantType().descriptorString(), constantName()));
+    }
+
+    @Override
+    public String toString() {
+        return String.format("EnumRef[%s.%s]", constantType().simpleName(), constantName());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/MethodHandleRef.java	Wed Mar 07 16:34:02 2018 -0500
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2012, 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.invoke.constant;
+
+import jdk.internal.lang.annotation.Foldable;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandleInfo;
+import java.lang.invoke.MethodType;
+
+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.invoke.constant.MethodHandleRef.Kind.STATIC;
+import static java.lang.invoke.constant.ConstantRefs.CR_void;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * A symbolic reference for a {@link MethodHandle} constant.
+ */
+public interface MethodHandleRef
+        extends ConstantRef<MethodHandle>, Constable<ConstantRef<MethodHandle>> {
+    /**
+     * Kinds of method handle refs
+     */
+    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 invokevirtual} */
+        @Foldable VIRTUAL(REF_invokeVirtual),
+        /** A method handle for a method invoked as with {@code invokeinterface} */
+        @Foldable INTERFACE_VIRTUAL(REF_invokeInterface),
+        /** A method handle for a method invoked as with {@code invokespecial} */
+        @Foldable SPECIAL(REF_invokeSpecial),
+        /** 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;
+
+        Kind(int refKind) {
+            this.refKind = refKind;
+        }
+    }
+
+
+    /**
+     * Return a {@code MethodHandleRef} corresponding to an invocation of a
+     * declared method or an accessor for a field
+     *
+     * @param kind The kind of method handle to be described
+     * @param clazz the class declaring the method
+     * @param name the name of the method (ignored if {@code kind} is {@code CONSTRUCTOR})
+     * @param type the method type of the method
+     * @return the {@code MethodHandleRef}
+     * @throws NullPointerException if any of the non-ignored arguments are null
+     */
+    @Foldable
+    static ConstantMethodHandleRef of(Kind kind, ClassRef clazz, String name, MethodTypeRef type) {
+        return new ConstantMethodHandleRef(kind, clazz, name, type);
+    }
+
+    /**
+     * Return a {@code MethodHandleRef} corresponding to an invocation of a
+     * declared method or an accessor for a field
+     *
+     * @param kind The kind of method handle to be described
+     * @param clazz the class declaring the method
+     * @param name the name of the method (ignored if {@code kind} is {@code CONSTRUCTOR})
+     * @param descriptorString descriptor string of the method
+     * @return the {@code MethodHandleRef}
+     * @throws NullPointerException if any of the non-ignored arguments are null
+     */
+    @Foldable
+    static ConstantMethodHandleRef of(Kind kind, ClassRef clazz, String name, String descriptorString) {
+        return of(kind, clazz, name, MethodTypeRef.ofDescriptor(descriptorString));
+    }
+
+    /**
+     * Return a {@code MethodHandleRef} corresponding to an invocation of a
+     * declared method or an accessor for a field
+     *
+     * @param kind The kind of method handle to be described
+     * @param clazz the class declaring the method
+     * @param name the name of the method (ignored if {@code kind} is {@code CONSTRUCTOR})
+     * @param returnType the return type of the method
+     * @param paramTypes the parameter types of the method
+     * @return the {@code MethodHandleRef}
+     * @throws NullPointerException if any of the non-ignored arguments are null
+     */
+    @Foldable
+    static ConstantMethodHandleRef of(Kind kind, ClassRef clazz, String name, ClassRef returnType, ClassRef... paramTypes) {
+        return of(kind, clazz, name, MethodTypeRef.of(returnType, paramTypes));
+    }
+
+    /**
+     * Return a {@code MethodHandleRef} corresponding to a bootstrap method for
+     * an {@code invokedynamic} callsite, which is a static method whose leading
+     * parameter types are {@code Lookup}, {@code String}, and {@code MethodType}
+     * @param clazz the class declaring the method
+     * @param name the name of the method
+     * @param returnType the return type of the method
+     * @param paramTypes the parameter types of the method that follow the three
+     *                   standard leading arguments, if any
+     * @return the {@code MethodHandleRef}
+     * @throws NullPointerException if any of the arguments are null
+     */
+    @Foldable
+    static ConstantMethodHandleRef ofDynamicCallsite(ClassRef clazz, String name, ClassRef returnType, ClassRef... paramTypes) {
+        return of(STATIC, clazz, name, MethodTypeRef.of(returnType, paramTypes).insertParameterTypes(0, ConstantRefs.INDY_BOOTSTRAP_ARGS));
+    }
+
+    /**
+     * Return a {@code MethodHandleRef} corresponding to a bootstrap method for a
+     * dynamic constant, which is a static method whose leading arguments are
+     * {@code Lookup}, {@code String}, and {@code Class}
+     * @param clazz the class declaring the method
+     * @param name the name of the method
+     * @param returnType the return type of the method
+     * @param paramTypes the parameter types of the method that follow the three
+     *                   standard leading arguments, if any
+     * @return the {@code MethodHandleRef}
+     * @throws NullPointerException if any of the arguments are null
+     */
+    @Foldable
+    static ConstantMethodHandleRef ofDynamicConstant(ClassRef clazz, String name, ClassRef returnType, ClassRef... paramTypes) {
+        return of(STATIC, clazz, name, MethodTypeRef.of(returnType, paramTypes).insertParameterTypes(0, ConstantRefs.CONDY_BOOTSTRAP_ARGS));
+    }
+
+    /**
+     * Return a {@code MethodHandleRef} corresponding to accessing a field
+     * @param kind the kind of the method handle; must be one of {@code GETTER},
+     *             {@code SETTER}, {@code STATIC_GETTER}, or {@code STATIC_SETTER}
+     * @param clazz the class declaring the field
+     * @param name the name of the field
+     * @param type the type of the field
+     * @return the {@code MethodHandleRef}
+     * @throws NullPointerException if any of the arguments are null
+     */
+    @Foldable
+    static ConstantMethodHandleRef ofField(Kind kind, ClassRef clazz, String name, ClassRef type) {
+        MethodTypeRef mtr;
+        switch (kind) {
+            case GETTER: mtr = MethodTypeRef.of(type, clazz); break;
+            case SETTER: mtr = MethodTypeRef.of(CR_void, clazz, type); break;
+            case STATIC_GETTER: mtr = MethodTypeRef.of(type); break;
+            case STATIC_SETTER: mtr = MethodTypeRef.of(CR_void, type); break;
+            default:
+                throw new IllegalArgumentException(kind.toString());
+        }
+        return new ConstantMethodHandleRef(kind, clazz, name, mtr);
+    }
+
+    /**
+     * Return the type of the method described by this symbolic reference
+     * @return the method type
+     */
+    @Foldable
+    MethodTypeRef methodType();
+
+    /**
+     * Return a {@linkplain MethodHandleRef} that describes this method handle
+     * adapted to a different type, as if by {@link MethodHandle#asType(MethodType)}.
+     *
+     * @param type the new type
+     * @return the adapted method handle reference
+     */
+    @Foldable
+    default MethodHandleRef asType(MethodTypeRef type) {
+        return (methodType().equals(type)) ? this : new AsTypeMethodHandleRef(this, type);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/MethodTypeRef.java	Wed Mar 07 16:34:02 2018 -0500
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2012, 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.invoke.constant;
+
+import jdk.internal.lang.annotation.Foldable;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * A symbolic reference for a {@linkplain MethodType} constant.
+ */
+public interface MethodTypeRef extends ConstantRef<MethodType>, Constable<ConstantRef<MethodType>> {
+    /**
+     * Create a {@linkplain MethodTypeRef} from a method descriptor string
+     *
+     * @param descriptor the method descriptor string
+     * @return a {@linkplain MethodTypeRef} describing the desired method type
+     * @throws IllegalArgumentException if the descriptor string is not a valid
+     * method descriptor
+     */
+    @Foldable
+    static MethodTypeRef ofDescriptor(String descriptor) {
+        return ConstantMethodTypeRef.ofDescriptor(descriptor);
+    }
+
+    /**
+     * Returns a {@linkplain MethodTypeRef} for the specified return type and
+     * parameter types.
+     *
+     * @param returnDescriptor a {@linkplain ClassRef} describing the return type
+     * @param paramDescriptors {@linkplain ClassRef}s describing the argument types
+     * @return a {@linkplain MethodTypeRef} describing the desired method type
+     */
+    @Foldable
+    static MethodTypeRef of(ClassRef returnDescriptor, ClassRef... paramDescriptors) {
+        return new ConstantMethodTypeRef(returnDescriptor, paramDescriptors);
+    }
+
+    /**
+     * Get the return type of the method type described by this {@linkplain MethodTypeRef}
+     * @return the return type
+     */
+    @Foldable
+    ClassRef returnType();
+
+    /**
+     * Get the number of parameters of the method type described by
+     * this {@linkplain MethodTypeRef}
+     * @return the number of parameters
+     */
+    @Foldable
+    int parameterCount();
+
+    /**
+     * Get the parameter type of the {@code index}'th parameter of the method type
+     * described by this {@linkplain MethodTypeRef}
+     *
+     * @param index the index of the parameter to retrieve
+     * @return the parameter type
+     * @throws IndexOutOfBoundsException if the index is outside the half-open
+     * range {[0, parameterCount())}
+     */
+    @Foldable
+    ClassRef parameterType(int index);
+
+    /**
+     * Get the parameter types as a {@link List}
+     *
+     * @return the parameter types
+     */
+    List<ClassRef> parameterList();
+
+    /**
+     * Get the parameter types as an array
+     *
+     * @return the parameter types
+     */
+    ClassRef[] parameterArray();
+
+    /**
+     * Return a {@linkplain MethodTypeRef} that is identical to
+     * this one, except with the specified return type
+     *
+     * @param returnType the new return type
+     * @return the new method type descriptor
+     */
+    @Foldable
+    MethodTypeRef changeReturnType(ClassRef returnType);
+
+    /**
+     * Return a {@linkplain MethodTypeRef} that is identical to this one,
+     * except that a single parameter type has been changed to the provided
+     * value
+     *
+     * @param index the index of the parameter to change
+     * @param paramType the new parameter type
+     * @return the new method type descriptor
+     * @throws IndexOutOfBoundsException if the index is outside the half-open
+     * range {[0, parameterCount)}
+     */
+    @Foldable
+    MethodTypeRef changeParameterType(int index, ClassRef paramType);
+
+    /**
+     * Return a {@linkplain MethodTypeRef} that is identical to this one,
+     * except that a range of parameter types have been removed
+     *
+     * @param start the index of the first parameter to remove
+     * @param end the index after the last parameter to remove
+     * @return the new method type descriptor
+     * @throws IndexOutOfBoundsException if {@code start} is outside the half-open
+     * range {[0, parameterCount)}, or {@code end} is outside the closed range
+     * {@code [0, parameterCount]}
+     */
+    @Foldable
+    MethodTypeRef dropParameterTypes(int start, int end);
+
+    /**
+     * Return a {@linkplain MethodTypeRef} that is identical to this one,
+     * except that a range of additional parameter types have been inserted
+     *
+     * @param pos the index at which to insert the first inserted parameter
+     * @param paramTypes the new parameter types to insert
+     * @return the new method type descriptor
+     * @throws IndexOutOfBoundsException if {@code pos} is outside the closed
+     * range {[0, parameterCount]}
+     */
+    @Foldable
+    MethodTypeRef insertParameterTypes(int pos, ClassRef... paramTypes);
+
+    /**
+     * Return the method type descriptor string
+     * @return the method type descriptor string
+     */
+    default String descriptorString() {
+        return String.format("(%s)%s",
+                             Stream.of(parameterArray())
+                                   .map(ClassRef::descriptorString)
+                                   .collect(Collectors.joining()),
+                             returnType().descriptorString());
+    }
+
+    /**
+     * Return a human-readable descriptor for this method type, using the
+     * canonical names for parameter and return types
+     * @return the human-readable descriptor for this method type
+     */
+    default String simpleDescriptor() {
+        return String.format("(%s)%s",
+                             Stream.of(parameterArray())
+                                   .map(ClassRef::simpleName)
+                                   .collect(Collectors.joining(",")),
+                             returnType().simpleName());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/PrimitiveClassRef.java	Wed Mar 07 16:34:02 2018 -0500
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2012, 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.invoke.constant;
+
+import java.lang.invoke.MethodHandles;
+import java.util.Optional;
+
+import sun.invoke.util.Wrapper;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * PrimitiveClassRef
+ *
+ * @author Brian Goetz
+ */
+final class PrimitiveClassRef extends DynamicConstantRef<Class<?>> implements ClassRef {
+    private final String descriptor;
+
+    /**
+     * Create a {@linkplain ClassRef} from a descriptor string for a primitive type
+     *
+     * @param descriptor the descriptor string
+     * @throws IllegalArgumentException if the descriptor string does not
+     * describe a valid primitive type
+     */
+    PrimitiveClassRef(String descriptor) {
+        super(ConstantRefs.BSM_PRIMITIVE_CLASS, requireNonNull(descriptor), ConstantRefs.CR_Class);
+        if (descriptor.length() != 1
+            || "VIJCSBFDZ".indexOf(descriptor.charAt(0)) < 0)
+            throw new IllegalArgumentException(String.format("%s is not a valid primitive type descriptor", descriptor));
+        this.descriptor = descriptor;
+    }
+
+    @Override
+    public String descriptorString() {
+        return descriptor;
+    }
+
+    @Override
+    public Class<?> resolveConstantRef(MethodHandles.Lookup lookup) {
+        return Wrapper.forBasicType(descriptorString().charAt(0)).primitiveType();
+    }
+
+    @Override
+    public Optional<? extends ConstantRef<? super ConstantRef<Class<?>>>> toConstantRef(MethodHandles.Lookup lookup) {
+        return DynamicConstantRef.symbolizeHelper(lookup, ConstantRefs.MHR_CLASSREF_FACTORY, ConstantRefs.CR_ClassRef, descriptorString());
+    }
+
+    @Override
+    public String toString() {
+        return String.format("PrimitiveClassRef[%s]", simpleName());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/RefBootstraps.java	Wed Mar 07 16:34:02 2018 -0500
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2012, 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.invoke.constant;
+
+import jdk.internal.lang.annotation.Foldable;
+
+import java.lang.invoke.MethodHandles;
+
+import static java.lang.invoke.constant.ConstantRefs.CR_ClassRef;
+import static java.lang.invoke.constant.ConstantRefs.CR_ConstantRef;
+import static java.lang.invoke.constant.ConstantRefs.CR_DynamicConstantRef;
+import static java.lang.invoke.constant.ConstantRefs.CR_EnumRef;
+import static java.lang.invoke.constant.ConstantRefs.CR_MethodHandleRef;
+import static java.lang.invoke.constant.ConstantRefs.CR_MethodTypeRef;
+import static java.lang.invoke.constant.ConstantRefs.CR_String;
+
+/**
+ * RefBoostraps
+ *
+ * @author Brian Goetz
+ */
+public final class RefBootstraps {
+    private RefBootstraps() { }
+
+    @Foldable
+    private static final ClassRef THIS_CLASS = ClassRef.of("java.lang.invoke.constant.RefBootstraps");
+
+    /** Bootstrap for ClassRef */
+    @Foldable
+    public static final MethodHandleRef BSM_CLASSREF = MethodHandleRef.ofDynamicConstant(THIS_CLASS, "classRef", CR_ClassRef,
+                                                                                         CR_String);
+
+    /** Bootstrap for MethodTypeRef */
+    @Foldable
+    public static final MethodHandleRef BSM_METHODTYPEREF = MethodHandleRef.ofDynamicConstant(THIS_CLASS, "methodTypeRef", CR_MethodTypeRef,
+                                                                                              CR_String);
+
+    /** Bootstrap for MethodHandleRef */
+    @Foldable
+    public static final MethodHandleRef BSM_METHODHANDLEREF = MethodHandleRef.ofDynamicConstant(THIS_CLASS, "methodHandleRef", CR_MethodHandleRef,
+                                                                                                CR_String, CR_String, CR_String, CR_String);
+
+    /** Bootstrap for DynamicConstantRef */
+    @Foldable
+    public static final MethodHandleRef BSM_DYNAMICCONSTANTREF = MethodHandleRef.ofDynamicConstant(THIS_CLASS, "dynamicConstantRef", CR_DynamicConstantRef,
+                                                                                                   CR_String, CR_String, CR_String, CR_String, CR_String,
+
+                                                                                                   CR_ConstantRef.array());
+
+    /** Bootstrap for ClassRef */
+    @Foldable
+    public static final MethodHandleRef BSM_ENUMREF = MethodHandleRef.ofDynamicConstant(THIS_CLASS, "enumRef", CR_EnumRef,
+                                                                                        CR_String, CR_String);
+    /**
+     * Bootstrap for ClassRef
+     *
+     * @param lookup ignored
+     * @param name ignored
+     * @param clazz ignored
+     * @param descriptor descriptor for class
+     * @return the ClassRef
+     */
+    public static ClassRef classRef(MethodHandles.Lookup lookup, String name, Class<ClassRef> clazz,
+                                    String descriptor) {
+        // @@@ Can fold descriptor into name channel, with encoding from BytecodeName
+        return ClassRef.ofDescriptor(descriptor);
+    }
+
+    /**
+     * Bootstrap for MethodTypeRef
+     *
+     * @param lookup ignored
+     * @param name ignored
+     * @param clazz ignored
+     * @param descriptor descriptor for method
+     * @return the MethodTypeRef
+     */
+    public static MethodTypeRef methodTypeRef(MethodHandles.Lookup lookup, String name, Class<ClassRef> clazz,
+                                              String descriptor) {
+        // @@@ Can fold descriptor into name channel, with encoding from BytecodeName
+        return MethodTypeRef.ofDescriptor(descriptor);
+    }
+
+    /**
+     * Bootstrap for MethodHandleRef
+     *
+     * @param lookup ignored
+     * @param name ignored
+     * @param clazz ignored
+     * @param bsmKindName kind
+     * @param bsmOwner owner
+     * @param bsmName name
+     * @param bsmDesc desc
+     * @return the MethodHandleRef
+     */
+    public static MethodHandleRef methodHandleRef(MethodHandles.Lookup lookup, String name, Class<ClassRef> clazz,
+                                                  String bsmKindName, String bsmOwner, String bsmName, String bsmDesc) {
+        return MethodHandleRef.of(MethodHandleRef.Kind.valueOf(bsmKindName), ClassRef.ofDescriptor(bsmOwner), bsmName, MethodTypeRef.ofDescriptor(bsmDesc));
+    }
+
+    /**
+     * Bootstrap for DynamicConstantRef
+     *
+     * @param lookup ignored
+     * @param name ignored
+     * @param clazz ignored
+     * @param bsmOwner owner
+     * @param bsmName name
+     * @param bsmDesc desc
+     * @param invName invName
+     * @param invType invType
+     * @param args bsm args
+     * @return the DynamicConstantRef
+     */
+    public static DynamicConstantRef<?> dynamicConstantRef(MethodHandles.Lookup lookup, String name, Class<ClassRef> clazz,
+                                                           String bsmOwner, String bsmName, String bsmDesc,
+                                                           String invName, String invType,
+                                                           ConstantRef<?>... args) {
+        return DynamicConstantRef.of(MethodHandleRef.of(MethodHandleRef.Kind.STATIC, ClassRef.ofDescriptor(bsmOwner), bsmName, MethodTypeRef.ofDescriptor(bsmDesc)),
+                                     invName, ClassRef.ofDescriptor(invType), args);
+
+    }
+
+    /**
+     * Bootstrap for EnumRef
+     *
+     * @param lookup ignored
+     * @param name ignored
+     * @param clazz ignored
+     * @param classDescriptor enum class
+     * @param constantName enum constant
+     * @return the EnumRef
+     */
+    public static EnumRef<?> enumRef(MethodHandles.Lookup lookup, String name, Class<ClassRef> clazz,
+                                     String classDescriptor, String constantName) {
+        return EnumRef.of(ClassRef.ofDescriptor(classDescriptor), constantName);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/VarHandleRef.java	Wed Mar 07 16:34:02 2018 -0500
@@ -0,0 +1,234 @@
+/*
+ * 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.invoke.constant;
+
+import jdk.internal.lang.annotation.Foldable;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.util.Optional;
+
+import static java.lang.invoke.constant.ConstantRefs.CR_ClassRef;
+import static java.lang.invoke.constant.ConstantRefs.CR_String;
+import static java.lang.invoke.constant.ConstantRefs.CR_VarHandleRef;
+
+/**
+ * A symbolic reference for a {@link VarHandle} constant.
+ */
+public final class VarHandleRef extends DynamicConstantRef<VarHandle>
+        implements Constable<ConstantRef<VarHandle>> {
+
+    private static final ConstantRef<?>[] EMPTY_ARGS = new ConstantRef<?>[0];
+
+    /**
+     * Kinds of variable handle refs
+     */
+    private enum Kind {
+        @Foldable
+        FIELD(ConstantRefs.BSM_VARHANDLE_FIELD, ConstantRefs.MHR_VARHANDLEREF_OFFIELD),
+        @Foldable
+        STATIC_FIELD(ConstantRefs.BSM_VARHANDLE_STATIC_FIELD, ConstantRefs.MHR_VARHANDLEREF_OFSTATIC),
+        @Foldable
+        ARRAY(ConstantRefs.BSM_VARHANDLE_ARRAY, ConstantRefs.MHR_VARHANDLEREF_OFARRAY);
+
+        final MethodHandleRef bootstrapMethod;
+        final MethodHandleRef refFactory;
+
+        Kind(MethodHandleRef bootstrapMethod, MethodHandleRef refFactory) {
+            this.bootstrapMethod = bootstrapMethod;
+            this.refFactory = refFactory;
+        }
+
+        List<ConstantRef<?>> toBSMArgs(ClassRef declaringClass, String name, ClassRef varType) {
+            switch (this) {
+                case FIELD:
+                case STATIC_FIELD:
+                    return List.of(declaringClass, name, varType);
+                case ARRAY:
+                    return List.of(declaringClass);
+                default:
+                    throw new InternalError("Cannot reach here");
+            }
+        }
+    }
+
+    private final Kind kind;
+    private final ClassRef declaringClass;
+    private final ClassRef varType;
+
+    /**
+     * Construct a {@linkplain VarHandleRef}
+     *
+     * @param kind the kind of of the var handle
+     * @param name the name of the field, for field var handles
+     * @param declaringClass the name of the declaring class, for field var handles
+     * @param varType the type of the variable
+     * @throws NullPointerException if any required argument is null
+     */
+    private VarHandleRef(Kind kind, String name, ClassRef declaringClass, ClassRef varType) {
+        super(kind.bootstrapMethod, name,
+              ConstantRefs.CR_VarHandle,
+              kind.toBSMArgs(declaringClass, name, varType).toArray(EMPTY_ARGS));
+        this.kind = kind;
+        this.declaringClass = declaringClass;
+        this.varType = varType;
+    }
+
+    /**
+     * Returns a {@code VarHandleRef} corresponding to a {@link VarHandle}
+     * for an instance field.
+     *
+     * @param declaringClass the class in which the field is declared
+     * @param name the name of the field
+     * @param fieldType the type of the field
+     * @return the {@code VarHandleRef}
+     * @throws NullPointerException if any of the arguments are null
+     */
+    @Foldable
+    public static VarHandleRef ofField(ClassRef declaringClass, String name, ClassRef fieldType) {
+        Objects.requireNonNull(declaringClass);
+        Objects.requireNonNull(name);
+        Objects.requireNonNull(fieldType);
+        return new VarHandleRef(Kind.FIELD, name, declaringClass, fieldType);
+    }
+
+    /**
+     * Returns a {@code VarHandleRef} corresponding to a {@link VarHandle}
+     * for a static field.
+     *
+     * @param declaringClass the class in which the field is declared
+     * @param name the name of the field
+     * @param fieldType the type of the field
+     * @return the {@code VarHandleRef}
+     * @throws NullPointerException if any of the arguments are null
+     */
+    @Foldable
+    public static VarHandleRef ofStaticField(ClassRef declaringClass, String name, ClassRef fieldType) {
+        Objects.requireNonNull(declaringClass);
+        Objects.requireNonNull(name);
+        Objects.requireNonNull(fieldType);
+        return new VarHandleRef(Kind.STATIC_FIELD, name, declaringClass, fieldType);
+    }
+
+    /**
+     * Returns a {@code VarHandleRef} corresponding to a {@link VarHandle}
+     * for for an array type.
+     *
+     * @param arrayClass the type of the array
+     * @return the {@code VarHandleRef}
+     * @throws NullPointerException if any of the arguments are null
+     */
+    @Foldable
+    public static VarHandleRef ofArray(ClassRef arrayClass) {
+        Objects.requireNonNull(arrayClass);
+        if (!arrayClass.isArray())
+            throw new IllegalArgumentException("Array class argument not an array: " + arrayClass);
+        return new VarHandleRef(Kind.ARRAY, "_", arrayClass, arrayClass.componentType());
+    }
+
+    /**
+     * Returns the type of the variable described by this symbolic reference.
+     *
+     * @return the variable type
+     */
+    @Foldable
+    public ClassRef varType() { return varType; }
+
+    // @@@ should this be the of co-ordinate types? there by better mirroring
+    // VarHandle this makes it slightly more involved since the array VH has
+    // to inject it's index
+    /**
+     * Returns the declaring class of the variable described by this symbolic
+     * reference.
+     *
+     * <p>If the declaring class is an array type then the declaring class
+     * will be the component type of the array type.
+     *
+     * @return the declaring class
+     */
+    @Foldable
+    public ClassRef declaringClass() { return declaringClass; }
+
+    /* @@@
+    MethodTypeRef accessModeTypeRef(AccessMode accessMode)
+     */
+
+    /* @@@
+    MethodHandleRef toMethodHandleRef(AccessMode accessMode)
+     */
+
+    @Override
+    public VarHandle resolveConstantRef(MethodHandles.Lookup lookup) throws ReflectiveOperationException {
+        switch (kind) {
+            case FIELD:
+                return lookup.findVarHandle(declaringClass.resolveConstantRef(lookup),
+                                            constantName(),
+                                            varType.resolveConstantRef(lookup));
+            case STATIC_FIELD:
+                return lookup.findStaticVarHandle(declaringClass.resolveConstantRef(lookup),
+                                                  constantName(),
+                                                  varType.resolveConstantRef(lookup));
+            case ARRAY:
+                return MethodHandles.arrayElementVarHandle(declaringClass.resolveConstantRef(lookup));
+            default:
+                throw new InternalError("Cannot reach here");
+        }
+    }
+
+    @Override
+    public Optional<ConstantRef<ConstantRef<VarHandle>>> toConstantRef(MethodHandles.Lookup lookup) {
+        try {
+            ArrayList<ConstantRef<?>> args = new ArrayList<>();
+            args.add(declaringClass.toConstantRef(lookup).orElseThrow());
+            if (kind != Kind.ARRAY) {
+                args.add(constantName());
+                args.add(varType.toConstantRef(lookup).orElseThrow());
+            }
+            return Optional.of(DynamicConstantRef.ofInvoke(kind.refFactory, CR_VarHandleRef,
+                                                           args.toArray(EMPTY_ARGS)));
+        } catch (NoSuchElementException e) {
+            return Optional.empty();
+        }
+    }
+
+    @Override
+    public String toString() {
+        switch (kind) {
+            case FIELD:
+            case STATIC_FIELD:
+                return String.format("VarHandleRef[%s%s.%s:%s]",
+                                     (kind == Kind.STATIC_FIELD) ? "static " : "",
+                                     declaringClass.simpleName(), constantName(), varType.simpleName());
+            case ARRAY:
+                return String.format("VarHandleRef[%s[]]", declaringClass.simpleName());
+            default:
+                throw new InternalError("Cannot reach here");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/constant/package-info.java	Wed Mar 07 16:34:02 2018 -0500
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+
+/**
+ * Classes and interfaces to represent <em>nominal references</em> to run-time
+ * 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(java.lang.invoke.constant.ConstantRef)}),
+ * or compile- and link-time program analysis.
+ *
+ * <p>Every API that reads and writes bytecode instructions needs to model the
+ * operands to these instructions, or other classfile structures such as entries
+ * in the bootstrap methods table or stack maps, which frequently correspond to
+ * entries in the classfile constant pool. Such entries can denote values of
+ * fundamental types, such as strings or integers; parts of a program, such as
+ * classes or method handles; or values of arbitrary user-defined types.  The
+ * {@link java.lang.invoke.constant.ConstantRef} hierarchy provides a representation of
+ * constant pool entries in nominal form that is convenient for APIs to model
+ * operands of bytecode instructions.
+ *
+ * <p>A {@link java.lang.invoke.constant.ConstantRef} is a description of a constant
+ * value.  Such a description is the <em>nominal form</em> of the constant value;
+ * it is not hte value itself, but rather a "recipe" for storing the value in
+ * a constant pool entry, or reconstituting the value given a class loading
+ * context.  Every {@link java.lang.invoke.constant.ConstantRef} knows how to <em>resolve</em>
+ * itself -- compute the value that it describes -- via the
+ * {@link java.lang.invoke.constant.ConstantRef#resolveConstantRef(java.lang.invoke.MethodHandles.Lookup)}
+ * method.  This allows an API which accepts {@link java.lang.invoke.constant.ConstantRef}
+ * objects to evaluate them reflectively, provided that the classes and methods
+ * referenced in their nominal description are present and accessible.
+ *
+ * <p>The subtypes of of {@link java.lang.invoke.constant.ConstantRef} describe various kinds
+ * of constant values.  For each type of constant pool entry defined in JVMS 4.4,
+ * there is a corresponding subtype of {@link java.lang.invoke.constant.ConstantRef}:
+ * {@code ConstantClassRef}, {@code ConstantMethodTypeRef},
+ * {@code ConstantMethodHandleRef}, {@code String}, {@code Integer}, {@code Long},
+ * {@code Float}, {@code Double}, and {@code DynamicConstantRef}.  These classes
+ * provides accessor methods to extrac the information needed to store a value
+ * in the constant pool.  When a bytecode-writing API encounters a {@link java.lang.invoke.constant.ConstantRef},
+ * it should case over these types to represent it in the constant pool.
+ * When a bytecode-reading API encounters a constant pool entry, it can
+ * convert it to the appropriate type of nominal reference.  For dynamic
+ * constants, bytecode-reading APIs may wish to use the factory
+ * {@link java.lang.invoke.constant.DynamicConstantRef#ofCanonical(java.lang.invoke.constant.MethodHandleRef, java.lang.String, java.lang.invoke.constant.ClassRef, java.lang.invoke.constant.ConstantRef[])},
+ * which will inspect the bootstrap and, for well-known bootstraps, instantiate
+ * a more specific subtype of {@link java.lang.invoke.constant.DynamicConstantRef}, such as
+ * {@link java.lang.invoke.constant.EnumRef}.
+ *
+ * <p>Another way to obtain the nominal description of a value is to ask the value
+ * itself.  A {@link java.lang.invoke.constant.Constable} is a type whose values can describe
+ * themselves in nominal form as a {@link java.lang.invoke.constant.ConstantRef}.  Fundamental
+ * types such as {@link java.lang.String} and {@link java.lang.Class} implement
+ * {@link java.lang.invoke.constant.Constable}, and every instance of these classes can
+ * provide itself in nominal form.  User-defined classes can also implement
+ * {@link java.lang.invoke.constant.Constable}.
+ *
+ * <p>This package also includes the {@link java.lang.invoke.constant.DynamicCallSiteRef}
+ * class, which is a representation of a constant pool entry that is never an
+ * argument to bytecode instructions.  Instead, it is a description of the
+ * bootstrap method, invocation name and type, and static arguments associated
+ * with an {@code invokedynamic} instruction, and is used by the
+ * {@link java.lang.invoke.Intrinsics#invokedynamic(java.lang.invoke.constant.DynamicCallSiteRef, java.lang.Object...)}
+ * API for expressing {@code invokedynamic} call sites in Java source files.
+ *
+ */
+package java.lang.invoke.constant;
+
--- a/src/java.base/share/classes/java/lang/sym/AsTypeMethodHandleRef.java	Wed Mar 07 14:59:03 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2012, 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.sym;
-
-import jdk.internal.lang.annotation.Foldable;
-
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-import java.util.Optional;
-
-import static java.lang.sym.ConstantRefs.BSM_INVOKE;
-import static java.lang.sym.ConstantRefs.CR_MethodHandle;
-import static java.util.Objects.requireNonNull;
-
-/**
- * AsTypeMethodHandleRef
- *
- * @author Brian Goetz
- */
-final class AsTypeMethodHandleRef extends DynamicConstantRef<MethodHandle>
-        implements MethodHandleRef {
-
-    private final MethodHandleRef underlying;
-    private final MethodTypeRef type;
-
-    AsTypeMethodHandleRef(MethodHandleRef underlying, MethodTypeRef type) {
-        super(BSM_INVOKE, "_", CR_MethodHandle,
-              ConstantRefs.MHR_METHODHANDLE_ASTYPE, underlying, type);
-        // Any type checking we can do?
-        this.underlying = requireNonNull(underlying);
-        this.type = requireNonNull(type);
-    }
-
-    @Override
-    @Foldable
-    public MethodTypeRef methodType() {
-        return type;
-    }
-
-    @Override
-    public MethodHandle resolveConstantRef(MethodHandles.Lookup lookup) throws ReflectiveOperationException {
-        MethodHandle handle = underlying.resolveConstantRef(lookup);
-        MethodType methodType = type.resolveConstantRef(lookup);
-        return handle.asType(methodType);
-    }
-
-    @Override
-    public Optional<? extends ConstantRef<? super ConstantRef<MethodHandle>>> toConstantRef(MethodHandles.Lookup lookup) {
-        return DynamicConstantRef.symbolizeHelper(lookup, ConstantRefs.MHR_METHODHANDLEREF_ASTYPE, ConstantRefs.CR_MethodHandleRef,
-                                                  underlying, type);
-    }
-
-    @Override
-    public String toString() {
-        return underlying.toString() + String.format(".asType%s", type.simpleDescriptor());
-    }
-
-    // @@@ canonical?
-}
--- a/src/java.base/share/classes/java/lang/sym/ClassRef.java	Wed Mar 07 14:59:03 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,206 +0,0 @@
-/*
- * Copyright (c) 2012, 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.sym;
-
-import jdk.internal.lang.annotation.Foldable;
-
-import java.util.stream.Stream;
-
-import sun.invoke.util.Wrapper;
-
-import static java.util.Objects.requireNonNull;
-import static java.util.stream.Collectors.joining;
-
-/**
- * A nominal reference for a {@link Class}.
- */
-public interface ClassRef extends ConstantRef<Class<?>>, Constable<ConstantRef<Class<?>>> {
-    /**
-     * Create a {@linkplain ClassRef} from a fully-qualified, dot-separated
-     * class name
-     *
-     * @param name the fully qualified class name, dot-separated
-     * @return a {@linkplain ClassRef} describing the desired class
-     * @throws IllegalArgumentException if the name string does not
-     * describe a valid class name
-     */
-    @Foldable
-    static ClassRef of(String name) {
-        return ClassRef.ofDescriptor("L" + name.replace('.', '/') + ";");
-    }
-
-    /**
-     * Create a {@linkplain ClassRef} from a dot-separated package name and an
-     * unqualified class name
-     *
-     * @param packageName the package name, dot-separated
-     * @param className the unqualified class name
-     * @return a {@linkplain ClassRef} describing the desired class
-     * @throws IllegalArgumentException if the package name or class name are
-     * not in the correct format
-     */
-    @Foldable
-    static ClassRef of(String packageName, String className) {
-        if (className.contains("."))
-            throw new IllegalArgumentException(className);
-        return ofDescriptor("L" + packageName.replace('.', '/')
-                            + (packageName.length() > 0 ? "/" : "")
-                            + className + ";");
-    }
-
-    /**
-     * Create a {@linkplain ClassRef} from a descriptor string for a class
-     *
-     * @param descriptor the descriptor string
-     * @return a {@linkplain ClassRef} describing the desired class
-     * @throws NullPointerException if the descriptor string is null
-     * @throws IllegalArgumentException if the descriptor string is not
-     * a valid class descriptor
-     */
-    @Foldable
-    static ClassRef ofDescriptor(String descriptor) {
-        requireNonNull(descriptor);
-        return (descriptor.length() == 1)
-               ? new PrimitiveClassRef(descriptor)
-               : new ConstantClassRef(descriptor);
-    }
-
-    /**
-     * Create a {@linkplain ClassRef} describing an array of the type
-     * described by this {@linkplain ClassRef}
-     *
-     * @return a {@linkplain ClassRef} describing the array type
-     */
-    @Foldable
-    default ClassRef array() {
-        return ClassRef.ofDescriptor("[" + descriptorString());
-    }
-
-    /**
-     * Create a {@linkplain ClassRef} describing an inner class of the
-     * non-array reference type described by this {@linkplain ClassRef}
-     * @param innerName the name of the inner class
-     * @return a {@linkplain ClassRef} describing the inner class
-     */
-    @Foldable
-    default ClassRef inner(String innerName) {
-        if (!descriptorString().startsWith("L"))
-            throw new IllegalStateException("Outer class is not a non-array reference type");
-        return ClassRef.ofDescriptor(descriptorString().substring(0, descriptorString().length() - 1) + "$" + innerName + ";");
-    }
-
-    /**
-     * Create a {@linkplain ClassRef} describing a multiply nested inner class of the
-     * non-array reference type described by this {@linkplain ClassRef}
-     *
-     * @param firstInnerName the name of the first level of inner class
-     * @param moreInnerNames the name(s) of the remaining levels of inner class
-     * @return a {@linkplain ClassRef} describing the inner class
-     */
-    @Foldable
-    default ClassRef inner(String firstInnerName, String... moreInnerNames) {
-        if (!descriptorString().startsWith("L"))
-            throw new IllegalStateException("Outer class is not a non-array reference type");
-        return moreInnerNames.length == 0
-               ? inner(firstInnerName)
-               : ClassRef.ofDescriptor(descriptorString().substring(0, descriptorString().length() - 1) + "$" + firstInnerName
-                                       + Stream.of(moreInnerNames).collect(joining("$", "$", "")) + ";");
-    }
-
-    /**
-     * Returns whether this {@linkplain ClassRef} describes an array type
-     *
-     * @return whether this {@linkplain ClassRef} describes an array type
-     */
-    default boolean isArray() {
-        return descriptorString().startsWith("[");
-    }
-
-    /**
-     * Returns whether this {@linkplain ClassRef} describes a primitive type
-     *
-     * @return whether this {@linkplain ClassRef} describes a primitive type
-     */
-    default boolean isPrimitive() {
-        return descriptorString().length() == 1;
-    }
-
-    /**
-     * Returns the component type of this {@linkplain ClassRef}, if it describes
-     * an array type
-     *
-     * @return a {@linkplain ClassRef} describing the component type
-     * @throws IllegalStateException if this {@linkplain ClassRef} does not
-     * describe an array type
-     */
-    @Foldable
-    default ClassRef componentType() {
-        if (!isArray())
-            throw new IllegalStateException();
-        return ClassRef.ofDescriptor(descriptorString().substring(1));
-    }
-
-    /**
-     * Returns a human-readable name for the type described by this descriptor
-     *
-     * @return a human-readable name for the type described by this descriptor
-     */
-    default String simpleName() {
-        if (descriptorString().length() == 1)
-            return Wrapper.forBasicType(descriptorString().charAt(0)).primitiveSimpleName();
-        else if (descriptorString().startsWith("L")) {
-            return descriptorString().substring(Math.max(1, descriptorString().lastIndexOf('/') + 1),
-                                                descriptorString().length() - 1);
-        }
-        else if (descriptorString().startsWith(("["))) {
-            int depth=arrayDepth();
-            ClassRef c = this;
-            for (int i=0; i<depth; i++)
-                c = c.componentType();
-            String name = c.simpleName();
-            StringBuilder sb = new StringBuilder(name.length() + 2*depth);
-            sb.append(name);
-            for (int i=0; i<depth; i++)
-                sb.append("[]");
-            return sb.toString();
-        }
-        else
-            throw new IllegalStateException(descriptorString());
-    }
-
-    private int arrayDepth() {
-        int depth = 0;
-        while (descriptorString().charAt(depth) == '[')
-            depth++;
-        return depth;
-    }
-
-    /**
-     * Return the type descriptor string
-     * @return the type descriptor string
-     */
-    @Foldable
-    String descriptorString();
-}
--- a/src/java.base/share/classes/java/lang/sym/Constable.java	Wed Mar 07 14:59:03 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2012, 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.sym;
-
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-import java.lang.invoke.VarHandle;
-import java.util.Optional;
-
-/**
- * Represents a type which is <em>constable</em>.  A constable type is one whose
- * values can be represented in the constant pool of a Java classfile.
- *
- * <p>The basic constable types are types whose values have a native representation
- * in the constant pool: ({@link String}, {@link Integer}, {@link Long}, {@link Float},
- * {@link Double}, {@link Class}, {@link MethodType}, and {@link MethodHandle}).
- *
- * <p>Other reference types can be constable if their instances can describe
- * themselves in nominal form as a {@link ConstantRef}. Examples in the Java SE
- * Platform API are types that support Java language features, such as {@link Enum},
- * and runtime support classes, such as {@link VarHandle}.
- *
- * <p>The nominal form of an instance of a constable type is obtained via
- * {@link #toConstantRef(MethodHandles.Lookup)}. A {@linkplain Constable} need
- * not be able to (or may choose not to) render all its instances in the form of
- * a {@link ConstantRef}; this method returns an {@link Optional} to indicate
- * whether a nominal reference could be created for a particular instance. (For
- * example, {@link MethodHandle} will produce nominal references for direct
- * method handles, but not necessarily for method handles resulting from method
- * handle combinators such as {@link MethodHandle#asType(MethodType)}.)
- *
- * @param <T> the type of the class implementing {@linkplain Constable}
- */
-public interface Constable<T> {
-    /**
-     * Return a nominal reference for this instance, if one can be
-     * constructed.
-     *
-     * @implSpec This method behaves as if {@link #toConstantRef(MethodHandles.Lookup)}
-     * were called with a lookup parameter of {@code MethodHandles.publicLookup()}.
-     *
-     * @return An {@link Optional} describing the resulting nominal reference,
-     * or an empty {@link Optional} if one cannot be constructed
-     */
-    default Optional<? extends ConstantRef<? super T>> toConstantRef() {
-        return toConstantRef(MethodHandles.publicLookup());
-    }
-
-    /**
-     * Return a nominal reference for this instance, if one can be
-     * constructed.  This object (and any classes needed to construct its
-     * nominal description) must be accessible from the class described by the
-     * {@code lookup} parameter.
-     *
-     * @param lookup A {@link MethodHandles.Lookup} to be used to perform
-     *               access control determinations
-     * @return An {@link Optional} describing the resulting nominal reference,
-     * or an empty {@link Optional} if one cannot be constructed or this object
-     * is not accessible from {@code lookup}
-     */
-    Optional<? extends ConstantRef<? super T>> toConstantRef(MethodHandles.Lookup lookup);
-}
--- a/src/java.base/share/classes/java/lang/sym/ConstantClassRef.java	Wed Mar 07 14:59:03 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2012, 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.sym;
-
-import java.lang.invoke.MethodHandles;
-import java.lang.reflect.Array;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.regex.Pattern;
-
-import static java.lang.sym.ConstantRefs.CR_ClassRef;
-
-/**
- * ConstantClassRef
- *
- * @author Brian Goetz
- */
-public class ConstantClassRef implements ClassRef {
-    private static final Pattern TYPE_DESC = Pattern.compile("(\\[*)(V|I|J|S|B|C|F|D|Z|L[^/.\\[;][^.\\[;]*;)");
-
-    private final String descriptor;
-
-    /**
-     * Create a {@linkplain ClassRef} from a descriptor string for a reference
-     * type
-     *
-     * @param descriptor the descriptor string
-     * @throws IllegalArgumentException if the descriptor string does not
-     * describe a valid reference type name
-     */
-    ConstantClassRef(String descriptor) {
-        // @@@ Replace validation with a lower-overhead mechanism than regex
-        // Follow the trail from MethodType.fromMethodDescriptorString to
-        // parsing code in sun/invoke/util/BytecodeDescriptor.java which could
-        // be extracted and/or shared
-        if (descriptor == null
-            || !TYPE_DESC.matcher(descriptor).matches())
-            throw new IllegalArgumentException(String.format("%s is not a valid type descriptor", descriptor));
-        this.descriptor = descriptor;
-    }
-
-    @Override
-    public String descriptorString() {
-        return descriptor;
-    }
-
-    private int arrayDepth() {
-        int depth = 0;
-        while (descriptorString().charAt(depth) == '[')
-            depth++;
-        return depth;
-    }
-
-    @Override
-    public Class<?> resolveConstantRef(MethodHandles.Lookup lookup) throws ReflectiveOperationException {
-        ClassRef c = this;
-        int depth = arrayDepth();
-        for (int i=0; i<depth; i++)
-            c = c.componentType();
-
-        if (c.descriptorString().length() == 1)
-            return Class.forName(descriptorString(), true, lookup.lookupClass().getClassLoader());
-        else {
-            Class<?> clazz = Class.forName(c.descriptorString().substring(1, c.descriptorString().length() - 1)
-                                            .replace('/', '.'), true, lookup.lookupClass().getClassLoader());
-            for (int i = 0; i < depth; i++)
-                clazz = Array.newInstance(clazz, 0).getClass();
-            return clazz;
-        }
-    }
-
-    @Override
-    public Optional<? extends ConstantRef<? super ConstantRef<Class<?>>>> toConstantRef(MethodHandles.Lookup lookup) {
-        return Optional.of(DynamicConstantRef.of(RefBootstraps.BSM_CLASSREF, CR_ClassRef).withArgs(descriptor));
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        ClassRef constant = (ClassRef) o;
-        return Objects.equals(descriptor, constant.descriptorString());
-    }
-
-    @Override
-    public int hashCode() {
-        return descriptor != null ? descriptor.hashCode() : 0;
-    }
-
-    @Override
-    public String toString() {
-        return String.format("ClassRef[%s]", simpleName());
-    }
-}
--- a/src/java.base/share/classes/java/lang/sym/ConstantMethodHandleRef.java	Wed Mar 07 14:59:03 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,202 +0,0 @@
-/*
- * Copyright (c) 2012, 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.sym;
-
-import jdk.internal.lang.annotation.Foldable;
-
-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 static java.lang.sym.ConstantRefs.CR_MethodTypeRef;
-import static java.lang.sym.MethodHandleRef.Kind.CONSTRUCTOR;
-import static java.lang.sym.ConstantRefs.CR_MethodHandleRef;
-import static java.util.Objects.requireNonNull;
-
-/**
- * DirectMethodHandleRef
- *
- * @author Brian Goetz
- */
-public class ConstantMethodHandleRef implements MethodHandleRef {
-
-    private final Kind kind;
-    private final ClassRef owner;
-    private final String name;
-    private final MethodTypeRef type;
-
-    /**
-     * Construct a {@linkplain ConstantMethodHandleRef} from a kind, owner, name, and type
-     * @param kind the kind of the method handle
-     * @param owner the declaring class for the method
-     * @param name the name of the method (ignored if {@code kind} is {@code CONSTRUCTOR})
-     * @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
-     */
-    ConstantMethodHandleRef(Kind kind, ClassRef owner, String name, MethodTypeRef type) {
-        super();
-        if (kind == CONSTRUCTOR)
-            name = "<init>";
-
-        requireNonNull(kind);
-        requireNonNull(owner);
-        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(MethodTypeRef 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(MethodTypeRef 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 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; }
-
-    /**
-     * Return the {@code kind} of the method handle described by this nominal reference
-     * @return the {@link Kind}
-     */
-    @Foldable
-    public Kind kind() { return kind; }
-
-    /**
-     * Return the class which declares the method or field described by
-     * this nominal reference
-     *
-     * @return the class in which the method or field is declared
-     */
-    @Foldable
-    public ClassRef owner() {
-        return owner;
-    }
-
-    /**
-     * Return the name of the method described by this nominal reference
-     *
-     * @return the name of the method
-     */
-    @Foldable
-    public String methodName() {
-        return name;
-    }
-
-    /**
-     * Return the type of the method described by this nominal reference
-     * @return the method type
-     */
-    @Foldable
-    public MethodTypeRef methodType() {
-        return type;
-    }
-
-    public MethodHandle resolveConstantRef(MethodHandles.Lookup lookup) throws ReflectiveOperationException {
-        Class<?> resolvedOwner = owner.resolveConstantRef(lookup);
-        MethodType resolvedType = this.type.resolveConstantRef(lookup);
-        switch (kind) {
-            case STATIC:
-                return lookup.findStatic(resolvedOwner, name, resolvedType);
-            case INTERFACE_VIRTUAL:
-            case VIRTUAL:
-                return lookup.findVirtual(resolvedOwner, name, resolvedType);
-            case 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 ConstantRef<? super ConstantRef<MethodHandle>>> toConstantRef(MethodHandles.Lookup lookup) {
-        return Optional.of(DynamicConstantRef.of(RefBootstraps.BSM_METHODHANDLEREF, CR_MethodHandleRef)
-                                             .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;
-        ConstantMethodHandleRef ref = (ConstantMethodHandleRef) o;
-        return kind == ref.kind &&
-               Objects.equals(owner, ref.owner) &&
-               Objects.equals(name, ref.name) &&
-               Objects.equals(type, ref.type);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(kind, owner, name, type);
-    }
-
-    @Override
-    public String toString() {
-        return String.format("MethodHandleRef[%s/%s::%s%s]", kind, owner.simpleName(), name, type.simpleDescriptor());
-    }
-}
--- a/src/java.base/share/classes/java/lang/sym/ConstantMethodTypeRef.java	Wed Mar 07 14:59:03 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,204 +0,0 @@
-/*
- * Copyright (c) 2012, 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.sym;
-
-import jdk.internal.lang.annotation.Foldable;
-
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Optional;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import static java.lang.sym.ConstantRefs.CR_ClassRef;
-import static java.lang.sym.ConstantRefs.CR_MethodTypeRef;
-import static java.util.Objects.requireNonNull;
-
-/**
- * ConstantMethodTypeRef
- *
- * @author Brian Goetz
- */
-public final class ConstantMethodTypeRef implements MethodTypeRef {
-
-    private static final Pattern TYPE_DESC = Pattern.compile("(\\[*)(V|I|J|S|B|C|F|D|Z|L[^/.\\[;][^.\\[;]*;)");
-    private static final Pattern pattern = Pattern.compile("\\((.*)\\)(.*)");
-
-    private final ClassRef returnType;
-    private final ClassRef[] argTypes;
-
-    /**
-     * Construct a {@linkplain MethodTypeRef} with the specified return type
-     * and parameter types
-     *
-     * @param returnType a {@link ClassRef} describing the return type
-     * @param argTypes {@link ClassRef}s describing the parameter types
-     */
-    ConstantMethodTypeRef(ClassRef returnType, ClassRef[] argTypes) {
-        this.returnType = requireNonNull(returnType);
-        this.argTypes = requireNonNull(argTypes);
-
-        for (ClassRef cr : argTypes)
-            if (cr.isPrimitive() && cr.descriptorString().equals("V"))
-                throw new IllegalArgumentException("Void parameters not permitted");
-    }
-
-    /**
-     * Create a {@linkplain ConstantMethodTypeRef} from a method descriptor string
-     *
-     * @param descriptor the method descriptor string
-     * @return a {@linkplain ConstantMethodTypeRef} describing the desired method type
-     * @throws IllegalArgumentException if the descriptor string is not a valid
-     * method descriptor
-     */
-    @Foldable
-    static MethodTypeRef ofDescriptor(String descriptor) {
-        // @@@ Replace validation with a lower-overhead mechanism than regex
-        // Follow the trail from MethodType.fromMethodDescriptorString to
-        // parsing code in sun/invoke/util/BytecodeDescriptor.java which could
-        // be extracted and/or shared
-        Matcher matcher = pattern.matcher(descriptor);
-        if (!matcher.matches())
-            throw new IllegalArgumentException(String.format("%s is not a valid method descriptor", descriptor));
-        String paramTypes = matcher.group(1);
-        String returnType = matcher.group(2);
-        if (!TYPE_DESC.matcher(returnType).matches())
-            throw new IllegalArgumentException(String.format("Invalid return type %s", returnType));
-        List<String> params = new ArrayList<>();
-        matcher = TYPE_DESC.matcher(paramTypes);
-        while (matcher.regionStart() < paramTypes.length()) {
-            if (matcher.lookingAt()) {
-                params.add(matcher.group());
-                matcher.region(matcher.end(), matcher.regionEnd());
-            }
-            else
-                throw new IllegalArgumentException(String.format("Invalid parameter type: %s", paramTypes.substring(matcher.regionStart(), matcher.regionEnd())));
-        }
-        return new ConstantMethodTypeRef(ClassRef.ofDescriptor(returnType), params.stream().map(ClassRef::ofDescriptor).toArray(ClassRef[]::new));
-    }
-
-    @Foldable
-    @Override
-    public ClassRef returnType() {
-        return returnType;
-    }
-
-    @Foldable
-    @Override
-    public int parameterCount() {
-        return argTypes.length;
-    }
-
-    @Foldable
-    @Override
-    public ClassRef parameterType(int index) {
-        return argTypes[index];
-    }
-
-    @Override
-    public List<ClassRef> parameterList() {
-        return List.of(argTypes);
-    }
-
-    @Override
-    public ClassRef[] parameterArray() {
-        return argTypes.clone();
-    }
-
-    @Foldable
-    @Override
-    public MethodTypeRef changeReturnType(ClassRef returnType) {
-        return MethodTypeRef.of(returnType, argTypes);
-    }
-
-    @Foldable
-    @Override
-    public MethodTypeRef changeParameterType(int index, ClassRef paramType) {
-        ClassRef[] newArgs = argTypes.clone();
-        newArgs[index] = paramType;
-        return MethodTypeRef.of(returnType, newArgs);
-    }
-
-    @Foldable
-    @Override
-    public MethodTypeRef 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));
-        ClassRef[] newArgs = new ClassRef[argTypes.length - (end - start)];
-        System.arraycopy(argTypes, 0, newArgs, 0, start);
-        System.arraycopy(argTypes, end, newArgs, start, argTypes.length - end);
-        return MethodTypeRef.of(returnType, newArgs);
-    }
-
-    @Foldable
-    @Override
-    public MethodTypeRef insertParameterTypes(int pos, ClassRef... paramTypes) {
-        if (pos < 0 || pos > argTypes.length)
-            throw new IndexOutOfBoundsException(pos);
-        ClassRef[] newArgs = new ClassRef[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 MethodTypeRef.of(returnType, newArgs);
-    }
-
-    @Override
-    public MethodType resolveConstantRef(MethodHandles.Lookup lookup) {
-        return MethodType.fromMethodDescriptorString(descriptorString(), lookup.lookupClass().getClassLoader());
-    }
-
-    @Override
-    public Optional<? extends ConstantRef<? super ConstantRef<MethodType>>> toConstantRef(MethodHandles.Lookup lookup) {
-        return Optional.of(DynamicConstantRef.of(RefBootstraps.BSM_METHODTYPEREF, CR_MethodTypeRef).withArgs(descriptorString()));
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        ConstantMethodTypeRef constant = (ConstantMethodTypeRef) 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("MethodTypeRef[%s]", simpleDescriptor());
-    }
-}
--- a/src/java.base/share/classes/java/lang/sym/ConstantRef.java	Wed Mar 07 14:59:03 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2012, 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.sym;
-
-import java.lang.invoke.Intrinsics;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-
-/**
- * A nominal reference to a loadable constant value, as defined in JVMS 4.4.
- * Such a nominal reference can be stored in the constant pool of a classfile
- * and resolved to yield the constant value itself.
- *
- * <p>Static constants that are expressible natively in the constant pool ({@link String},
- * {@link Integer}, {@link Long}, {@link Float}, and {@link Double}) implement
- * {@link ConstantRef}, serve as nominal references for themselves.
- * Native linkable constants ({@link Class}, {@link MethodType}, and
- * {@link MethodHandle}) have counterpart {@linkplain ConstantRef} types:
- * {@link ClassRef}, {@link MethodTypeRef}, and {@link MethodHandleRef}.
- * Other constants are represented by subtypes of {@link DynamicConstantRef}.
- *
- * <p>Non-platform classes should not implement {@linkplain ConstantRef} directly.
- * Instead, they should extend {@link DynamicConstantRef} (as {@link EnumRef}
- * and {@link VarHandleRef} do.)
- *
- * <p>Constants can be reflectively resolved via {@link ConstantRef#resolveConstantRef(MethodHandles.Lookup)}.
- *
- * <p>Constants describing various useful nominal references (such as {@link ClassRef}
- * instances for platform classes) can be found in {@link ConstantRefs}.
- *
- * <p>APIs that perform generation or parsing of bytecode are encouraged to use
- * {@linkplain ConstantRef} to describe the operand of an {@code ldc} instruction
- * (including dynamic constants), the static bootstrap arguments of
- * dynamic constants and {@code invokedynamic} instructions, and other
- * bytecodes or classfile structures that make use of the constant pool.
- *
- * <p>The {@linkplain ConstantRef} types are also used by {@link Intrinsics}
- * to express {@code ldc} instructions.
- *
- * <p>Implementations of {@linkplain ConstantRef} must be
- * <a href="../doc-files/ValueBased.html">value-based</a> classes.
- *
- * @apiNote In the future, if the Java language permits, {@linkplain ConstantRef}
- * may become a {@code sealed} interface, which would prohibit subclassing except by
- * explicitly permitted types.  Bytecode libraries can assume that the following
- * is an exhaustive set of direct subtypes: {@link String}, {@link Integer},
- * {@link Long}, {@link Float}, {@link Double}, {@link ClassRef},
- * {@link MethodTypeRef}, {@link MethodHandleRef}, and {@link DynamicConstantRef}.
- *
- * @see Constable
- * @see ConstantRef
- * @see Intrinsics
- * @see ConstantRefs
- *
- */
-public interface ConstantRef<T> {
-    /**
-     * Resolve this reference reflectively, using a {@link MethodHandles.Lookup}
-     * to resolve any type names into classes.
-     *
-     * @param lookup The {@link MethodHandles.Lookup} to be used in name resolution
-     * @return the resolved object
-     * @throws ReflectiveOperationException if this nominal reference refers
-     * (directly or indirectly) to a class, method, or field that cannot be
-     * resolved
-     */
-    T resolveConstantRef(MethodHandles.Lookup lookup) throws ReflectiveOperationException;
-}
--- a/src/java.base/share/classes/java/lang/sym/ConstantRefs.java	Wed Mar 07 14:59:03 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,324 +0,0 @@
-/*
- * Copyright (c) 2012, 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.sym;
-
-import jdk.internal.lang.annotation.Foldable;
-
-import java.lang.invoke.CallSite;
-import java.lang.invoke.ConstantBootstraps;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodHandles.Lookup;
-import java.lang.invoke.MethodType;
-import java.lang.invoke.VarHandle;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Predefined constants for common nominal references to constants.  Includes
- * class references for primitive types and common platform types, and method
- * handle references for standard bootstrap methods.
- *
- * @see ConstantRef
- */
-public final class ConstantRefs {
-    // No instances
-    private ConstantRefs() { }
-
-    // Don't change the order of these declarations!
-
-    /** {@link ClassRef} representing {@link Object} */
-    @Foldable
-    public static final ClassRef CR_Object = ClassRef.of("java.lang.Object");
-
-    /** {@link ClassRef} representing {@link String} */
-    @Foldable
-    public static final ClassRef CR_String = ClassRef.of("java.lang.String");
-
-    /** {@link ClassRef} representing {@link Class} */
-    @Foldable
-    public static final ClassRef CR_Class = ClassRef.of("java.lang.Class");
-
-    /** {@link ClassRef} representing {@link Number} */
-    @Foldable
-    public static final ClassRef CR_Number = ClassRef.of("java.lang.Number");
-
-    /** {@link ClassRef} representing {@link Integer} */
-    @Foldable
-    public static final ClassRef CR_Integer = ClassRef.of("java.lang.Integer");
-
-    /** {@link ClassRef} representing {@link Long} */
-    @Foldable
-    public static final ClassRef CR_Long = ClassRef.of("java.lang.Long");
-
-    /** {@link ClassRef} representing {@link Float} */
-    @Foldable
-    public static final ClassRef CR_Float = ClassRef.of("java.lang.Float");
-
-    /** {@link ClassRef} representing {@link Double} */
-    @Foldable
-    public static final ClassRef CR_Double = ClassRef.of("java.lang.Double");
-
-    /** {@link ClassRef} representing {@link Short} */
-    @Foldable
-    public static final ClassRef CR_Short = ClassRef.of("java.lang.Short");
-
-    /** {@link ClassRef} representing {@link Byte} */
-    @Foldable
-    public static final ClassRef CR_Byte = ClassRef.of("java.lang.Byte");
-
-    /** {@link ClassRef} representing {@link Character} */
-    @Foldable
-    public static final ClassRef CR_Character = ClassRef.of("java.lang.Character");
-
-    /** {@link ClassRef} representing {@link Boolean} */
-    @Foldable
-    public static final ClassRef CR_Boolean = ClassRef.of("java.lang.Boolean");
-
-    /** {@link ClassRef} representing {@link Void} */
-    @Foldable
-    public static final ClassRef CR_Void = ClassRef.of("java.lang.Void");
-
-    /** {@link ClassRef} representing {@link Throwable} */
-    @Foldable
-    public static final ClassRef CR_Throwable = ClassRef.of("java.lang.Throwable");
-
-    /** {@link ClassRef} representing {@link Exception} */
-    @Foldable
-    public static final ClassRef CR_Exception = ClassRef.of("java.lang.Exception");
-
-    /** {@link ClassRef} representing {@link Enum} */
-    @Foldable
-    public static final ClassRef CR_Enum = ClassRef.of("java.lang.Enum");
-
-    /** {@link ClassRef} representing {@link VarHandle} */
-    @Foldable
-    public static final ClassRef CR_VarHandle = ClassRef.of("java.lang.invoke.VarHandle");
-
-    /** {@link ClassRef} representing {@link MethodHandles} */
-    @Foldable
-    public static final ClassRef CR_MethodHandles = ClassRef.of("java.lang.invoke.MethodHandles");
-
-    /** {@link ClassRef} representing {@link MethodHandles.Lookup} */
-    @Foldable
-    public static final ClassRef CR_MethodHandles_Lookup = CR_MethodHandles.inner("Lookup");
-
-    /** {@link ClassRef} representing {@link MethodHandle} */
-    @Foldable
-    public static final ClassRef CR_MethodHandle = ClassRef.of("java.lang.invoke.MethodHandle");
-
-    /** {@link ClassRef} representing {@link MethodType} */
-    @Foldable
-    public static final ClassRef CR_MethodType = ClassRef.of("java.lang.invoke.MethodType");
-
-    /** {@link ClassRef} representing {@link CallSite} */
-    @Foldable
-    public static final ClassRef CR_CallSite = ClassRef.of("java.lang.invoke.CallSite");
-
-    /** {@link ClassRef} representing {@link Collection} */
-    @Foldable
-    public static final ClassRef CR_Collection = ClassRef.of("java.util.Collection");
-
-    /** {@link ClassRef} representing {@link List} */
-    @Foldable
-    public static final ClassRef CR_List = ClassRef.of("java.util.List");
-
-    /** {@link ClassRef} representing {@link Set} */
-    @Foldable
-    public static final ClassRef CR_Set = ClassRef.of("java.util.Set");
-
-    /** {@link ClassRef} representing {@link Map} */
-    @Foldable
-    public static final ClassRef CR_Map = ClassRef.of("java.util.Map");
-
-    /** {@link ClassRef} representing {@link ConstantRef} */
-    @Foldable
-    static final ClassRef CR_ConstantRef = ClassRef.of("java.lang.sym.ConstantRef");
-
-    /** {@link ClassRef} representing {@link ClassRef} */
-    @Foldable
-    static final ClassRef CR_ClassRef = ClassRef.of("java.lang.sym.ClassRef");
-
-    /** {@link ClassRef} representing {@link EnumRef} */
-    @Foldable
-    static final ClassRef CR_EnumRef = ClassRef.of("java.lang.sym.EnumRef");
-
-    /** {@link ClassRef} representing {@link MethodTypeRef} */
-    @Foldable
-    static final ClassRef CR_MethodTypeRef = ClassRef.of("java.lang.sym.MethodTypeRef");
-
-    /** {@link ClassRef} representing {@link MethodHandleRef} */
-    @Foldable
-    static final ClassRef CR_MethodHandleRef = ClassRef.of("java.lang.sym.MethodHandleRef");
-
-    /** {@link ClassRef} representing {@link VarHandleRef} */
-    @Foldable
-    static final ClassRef CR_VarHandleRef = ClassRef.of("java.lang.sym.VarHandleRef");
-
-    /** {@link ClassRef} representing {@link MethodHandleRef.Kind} */
-    @Foldable
-    static final ClassRef CR_MethodHandleRef_Kind = CR_MethodHandleRef.inner("Kind");
-
-    /** {@link ClassRef} representing {@link DynamicConstantRef} */
-    @Foldable
-    static final ClassRef CR_DynamicConstantRef = ClassRef.of("java.lang.sym.DynamicConstantRef");
-
-    /** {@link ClassRef} representing {@link DynamicCallSiteRef} */
-    @Foldable
-    static final ClassRef CR_DynamicCallSiteRef = ClassRef.of("java.lang.sym.DynamicCallSiteRef");
-
-    /** {@link ClassRef} representing {@link ConstantBootstraps} */
-    @Foldable
-    static final ClassRef CR_ConstantBootstraps = ClassRef.of("java.lang.invoke.ConstantBootstraps");
-
-    // Used by MethodHandleRef, but initialized here before reference to
-    // MethodHandleRef to avoid static initalization circularities
-    static final ClassRef[] INDY_BOOTSTRAP_ARGS = {
-            ConstantRefs.CR_MethodHandles_Lookup,
-            ConstantRefs.CR_String,
-            ConstantRefs.CR_MethodType };
-
-    static final ClassRef[] CONDY_BOOTSTRAP_ARGS = {
-            ConstantRefs.CR_MethodHandles_Lookup,
-            ConstantRefs.CR_String,
-            ConstantRefs.CR_Class };
-
-    /** {@link MethodHandleRef} representing {@link ConstantBootstraps#primitiveClass(Lookup, String, Class)} */
-    @Foldable
-    public static final MethodHandleRef BSM_PRIMITIVE_CLASS
-            = MethodHandleRef.ofDynamicConstant(CR_ConstantBootstraps, "primitiveClass", CR_Class);
-
-    /** {@link MethodHandleRef} representing {@link ConstantBootstraps#enumConstant(Lookup, String, Class)} */
-    @Foldable
-    public static final MethodHandleRef BSM_ENUM_CONSTANT
-            = MethodHandleRef.ofDynamicConstant(CR_ConstantBootstraps, "enumConstant", CR_Enum);
-
-    /** {@link MethodHandleRef} representing {@link ConstantBootstraps#nullConstant(Lookup, String, Class)} */
-    @Foldable
-    public static final MethodHandleRef BSM_NULL_CONSTANT
-            = MethodHandleRef.ofDynamicConstant(CR_ConstantBootstraps, "nullConstant", ConstantRefs.CR_Object);
-
-    /** {@link MethodHandleRef} representing {@link ConstantBootstraps#fieldVarHandle(Lookup, String, Class, Class, Class)} */
-    @Foldable
-    public static final MethodHandleRef BSM_VARHANDLE_FIELD
-            = MethodHandleRef.ofDynamicConstant(CR_ConstantBootstraps, "fieldVarHandle", CR_VarHandle, CR_Class, CR_Class);
-
-    /** {@link MethodHandleRef} representing {@link ConstantBootstraps#staticFieldVarHandle(Lookup, String, Class, Class, Class)} */
-    @Foldable
-    public static final MethodHandleRef BSM_VARHANDLE_STATIC_FIELD
-            = MethodHandleRef.ofDynamicConstant(CR_ConstantBootstraps, "staticFieldVarHandle", CR_VarHandle, CR_Class, CR_Class);
-
-    /** {@link MethodHandleRef} representing {@link ConstantBootstraps#arrayVarHandle(Lookup, String, Class, Class)} */
-    @Foldable
-    public static final MethodHandleRef BSM_VARHANDLE_ARRAY
-            = MethodHandleRef.ofDynamicConstant(CR_ConstantBootstraps, "arrayVarHandle", CR_VarHandle, CR_Class);
-
-    /** {@link MethodHandleRef} representing {@link ConstantBootstraps#invoke(Lookup, String, Class, MethodHandle, Object...)} */
-    @Foldable
-    public static final MethodHandleRef BSM_INVOKE
-            = MethodHandleRef.ofDynamicConstant(CR_ConstantBootstraps, "invoke", CR_Object, CR_MethodHandle, CR_Object.array());
-
-    /** {@link ClassRef} representing the primitive type {@code int} */
-    @Foldable
-    public static final ClassRef CR_int = ClassRef.ofDescriptor("I");
-
-    /** {@link ClassRef} representing the primitive type {@code long} */
-    @Foldable
-    public static final ClassRef CR_long = ClassRef.ofDescriptor("J");
-
-    /** {@link ClassRef} representing the primitive type {@code float} */
-    @Foldable
-    public static final ClassRef CR_float = ClassRef.ofDescriptor("F");
-
-    /** {@link ClassRef} representing the primitive type {@code double} */
-    @Foldable
-    public static final ClassRef CR_double = ClassRef.ofDescriptor("D");
-
-    /** {@link ClassRef} representing the primitive type {@code short} */
-    @Foldable
-    public static final ClassRef CR_short = ClassRef.ofDescriptor("S");
-
-    /** {@link ClassRef} representing the primitive type {@code byte} */
-    @Foldable
-    public static final ClassRef CR_byte = ClassRef.ofDescriptor("B");
-
-    /** {@link ClassRef} representing the primitive type {@code char} */
-    @Foldable
-    public static final ClassRef CR_char = ClassRef.ofDescriptor("C");
-
-    /** {@link ClassRef} representing the primitive type {@code boolean} */
-    @Foldable
-    public static final ClassRef CR_boolean = ClassRef.ofDescriptor("Z");
-
-    /** {@link ClassRef} representing the primitive type {@code void} */
-    @Foldable
-    public static final ClassRef CR_void = ClassRef.ofDescriptor("V");
-
-    /** Nominal reference representing the constant {@code null} */
-    @Foldable
-    public static final ConstantRef<?> NULL = DynamicConstantRef.of(ConstantRefs.BSM_NULL_CONSTANT, ConstantRefs.CR_Object);
-
-    // Used by XxxRef classes, but need to be hear to avoid bootstrap cycles
-    static final MethodHandleRef MHR_METHODTYPEREF_FACTORY
-            = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_MethodTypeRef, "ofDescriptor", CR_MethodTypeRef, CR_String);
-
-    static final MethodHandleRef MHR_CLASSREF_FACTORY
-            = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_ClassRef, "ofDescriptor", CR_ClassRef, CR_String);
-
-    static final MethodHandleRef MHR_METHODHANDLEREF_FACTORY
-            = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_MethodHandleRef, "of",
-                                 CR_MethodHandleRef, CR_MethodHandleRef_Kind, CR_ClassRef, CR_String, CR_MethodTypeRef);
-
-    static final MethodHandleRef MHR_METHODHANDLE_ASTYPE
-            = MethodHandleRef.of(MethodHandleRef.Kind.VIRTUAL, CR_MethodHandle, "asType", CR_MethodHandle, CR_MethodType);
-
-    static final MethodHandleRef MHR_METHODHANDLEREF_ASTYPE
-            = MethodHandleRef.of(MethodHandleRef.Kind.VIRTUAL, CR_MethodHandleRef, "asType", CR_MethodHandleRef, CR_MethodTypeRef);
-
-    static final MethodHandleRef MHR_DYNAMICCONSTANTREF_FACTORY
-            = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_DynamicConstantRef, "of",
-                                 CR_DynamicConstantRef, CR_MethodHandleRef, CR_String, CR_ClassRef);
-
-    static final MethodHandleRef MHR_DYNAMICCONSTANTREF_WITHARGS
-            = MethodHandleRef.of(MethodHandleRef.Kind.VIRTUAL, CR_DynamicConstantRef, "withArgs",
-                                 CR_DynamicConstantRef, CR_ConstantRef.array());
-
-    static final MethodHandleRef MHR_ENUMREF_FACTORY
-            = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_EnumRef, "of", CR_EnumRef, CR_ClassRef, CR_String);
-
-    static final MethodHandleRef MHR_VARHANDLEREF_OFFIELD
-            = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_VarHandleRef, "ofField",
-                                 CR_VarHandleRef, CR_ClassRef, CR_String, CR_ClassRef);
-
-    static final MethodHandleRef MHR_VARHANDLEREF_OFSTATIC
-            = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_VarHandleRef, "ofStaticField",
-                                 CR_VarHandleRef, CR_ClassRef, CR_String, CR_ClassRef);
-
-    static final MethodHandleRef MHR_VARHANDLEREF_OFARRAY
-            = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_VarHandleRef, "ofArray",
-                                 CR_VarHandleRef, CR_ClassRef);
-}
--- a/src/java.base/share/classes/java/lang/sym/DynamicCallSiteRef.java	Wed Mar 07 14:59:03 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,257 +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.sym;
-
-import jdk.internal.lang.annotation.Foldable;
-
-import java.lang.invoke.CallSite;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.util.Arrays;
-import java.util.Objects;
-
-import static java.lang.sym.ConstantRefs.CR_String;
-
-/**
- * A nominal reference for an {@code invokedynamic} call site.
- */
-@SuppressWarnings("rawtypes")
-public final class DynamicCallSiteRef {
-    private static final ConstantRef<?>[] EMPTY_ARGS = new ConstantRef<?>[0];
-
-    private final MethodHandleRef bootstrapMethod;
-    private final ConstantRef<?>[] bootstrapArgs;
-    private final String name;
-    private final MethodTypeRef type;
-
-    /**
-     * Construct a nominal reference for an {@code invokedynamic} call site
-     *
-     * @param bootstrapMethod The bootstrap method for the {@code invokedynamic}
-     * @param name The name that would appear in the {@code NameAndType} operand
-     *             of the {@code invokedynamic}
-     * @param type The invocation type that would appear in the {@code NameAndType} operand
-     *             of the {@code invokedynamic}
-     * @param bootstrapArgs The static arguments to the bootstrap, that would
-     *                      appear in the {@code BootstrapMethods} attribute
-     * @throws NullPointerException if any parameter is null
-     */
-    private DynamicCallSiteRef(MethodHandleRef bootstrapMethod,
-                               String name,
-                               MethodTypeRef type,
-                               ConstantRef<?>[] bootstrapArgs) {
-        this.name = Objects.requireNonNull(name);
-        this.type = Objects.requireNonNull(type);
-        this.bootstrapMethod = Objects.requireNonNull(bootstrapMethod);
-        this.bootstrapArgs = Objects.requireNonNull(bootstrapArgs.clone());
-    }
-
-    /**
-     * Return a nominal reference for an {@code invokedynamic} call site.  If
-     * the bootstrap method corresponds to a well-known bootstrap, for which a
-     * more specific nominal reference type exists, the more specific nominal
-     * reference type is returned.
-     *
-     * @param bootstrapMethod The bootstrap method for the {@code invokedynamic}
-     * @param name The name that would appear in the {@code NameAndType} operand
-     *             of the {@code invokedynamic}
-     * @param type The invocation type that would appear in the {@code NameAndType} operand
-     *             of the {@code invokedynamic}
-     * @param bootstrapArgs The static arguments to the bootstrap, that would
-     *                      appear in the {@code BootstrapMethods} attribute
-     * @return the nominal reference
-     * @throws NullPointerException if any parameter is null
-     */
-    @Foldable
-    public static DynamicCallSiteRef ofCanonical(MethodHandleRef bootstrapMethod, String name, MethodTypeRef type, ConstantRef<?>... bootstrapArgs) {
-        DynamicCallSiteRef ref = new DynamicCallSiteRef(bootstrapMethod, name, type, bootstrapArgs);
-        return ref.canonicalize();
-    }
-
-    /**
-     * Return a nominal reference for an {@code invokedynamic} call site.
-     *
-     * @param bootstrapMethod The bootstrap method for the {@code invokedynamic}
-     * @param name The name that would appear in the {@code NameAndType} operand
-     *             of the {@code invokedynamic}
-     * @param type The invocation type that would appear in the {@code NameAndType} operand
-     *             of the {@code invokedynamic}
-     * @param bootstrapArgs The static arguments to the bootstrap, that would
-     *                      appear in the {@code BootstrapMethods} attribute
-     * @return the nominal reference
-     * @throws NullPointerException if any parameter is null
-     */
-    @Foldable
-    public static DynamicCallSiteRef of(MethodHandleRef bootstrapMethod, String name, MethodTypeRef type, ConstantRef<?>... bootstrapArgs) {
-        return new DynamicCallSiteRef(bootstrapMethod, name, type, bootstrapArgs);
-    }
-
-    /**
-     * Return a nominal reference for an {@code invokedynamic} call site whose
-     * bootstrap method has no static arguments.
-     *
-     * @param bootstrapMethod The bootstrap method for the {@code invokedynamic}
-     * @param name The name that would appear in the {@code NameAndType} operand
-     *             of the {@code invokedynamic}
-     * @param type The invocation type that would appear in the {@code NameAndType} operand
-     *             of the {@code invokedynamic}
-     * @return the nominal reference
-     * @throws NullPointerException if any parameter is null
-     */
-    @Foldable
-    public static DynamicCallSiteRef of(MethodHandleRef bootstrapMethod, String name, MethodTypeRef type) {
-        return new DynamicCallSiteRef(bootstrapMethod, name, type, EMPTY_ARGS);
-    }
-
-    /**
-     * Return a nominal reference for an {@code invokedynamic} call site whose
-     * bootstrap method has no static arguments and whose name parameter is ignored.
-     *
-     * @param bootstrapMethod The bootstrap method for the {@code invokedynamic}
-     * @param type The invocation type that would appear in the {@code NameAndType} operand
-     *             of the {@code invokedynamic}
-     * @return the nominal reference
-     * @throws NullPointerException if any parameter is null
-     */
-    @Foldable
-    public static DynamicCallSiteRef of(MethodHandleRef bootstrapMethod, MethodTypeRef type) {
-        return of(bootstrapMethod, "_", type);
-    }
-
-    /**
-     * Return a nominal reference for an {@code invokedynamic} call site whose
-     * bootstrap method, name, and invocation type are the same as this one, but
-     * with the specified bootstrap arguments.
-     *
-     * @param bootstrapArgs The static arguments to the bootstrap, that would
-     *                      appear in the {@code BootstrapMethods} attribute
-     * @return the nominal reference
-     * @throws NullPointerException if any parameter is null
-     */
-    @Foldable
-    public DynamicCallSiteRef withArgs(ConstantRef<?>... bootstrapArgs) {
-        return new DynamicCallSiteRef(bootstrapMethod, name, type, bootstrapArgs);
-    }
-
-    /**
-     * Return a nominal reference for an {@code invokedynamic} call site whose
-     * bootstrap and bootstrap arguments are the same as this one, but with the
-     * specified name and invocation type
-     *
-     * @param name The name that would appear in the {@code NameAndType} operand
-     *             of the {@code invokedynamic}
-     * @param type The invocation type that would appear in the {@code NameAndType} operand
-     *             of the {@code invokedynamic}
-     * @return the nominal reference
-     * @throws NullPointerException if any parameter is null
-     */
-    @Foldable
-    public DynamicCallSiteRef withNameAndType(String name, MethodTypeRef type) {
-        return new DynamicCallSiteRef(bootstrapMethod, name, type, bootstrapArgs);
-    }
-
-    private DynamicCallSiteRef canonicalize() {
-        // @@@ MethodRef
-        return this;
-    }
-
-    /**
-     * Returns the invocation name that would appear in the {@code NameAndType} operand
-     * of the {@code invokedynamic}
-     * @return the invocation name
-     */
-    @Foldable
-    public String name() {
-        return name;
-    }
-
-    /**
-     * Returns the invocation type that would appear in the {@code NameAndType} operand
-     * of the {@code invokedynamic}
-     * @return the invocation type
-     */
-    @Foldable
-    public MethodTypeRef type() {
-        return type;
-    }
-
-    /**
-     * Returns the bootstrap method for the {@code invokedynamic}
-     * @return the bootstrap method for the {@code invokedynamic}
-     */
-    @Foldable
-    public MethodHandleRef bootstrapMethod() { return bootstrapMethod; }
-
-    /**
-     * Returns the bootstrap arguments for the {@code invokedynamic}
-     * @return the bootstrap arguments for the {@code invokedynamic}
-     */
-    public ConstantRef<?>[] bootstrapArgs() { return bootstrapArgs.clone(); }
-
-    /**
-     * Reflectively invokes the bootstrap method, and returns a dynamic invoker
-     * {@link MethodHandle} for the returned {@link CallSite}
-     *
-     * @param lookup The {@link MethodHandles.Lookup} used to resolve class names
-     * @return the dynamic invoker
-     * @throws Throwable if any exception is thrown by the bootstrap method
-     *
-     * @see CallSite#dynamicInvoker()
-     */
-    public MethodHandle dynamicInvoker(MethodHandles.Lookup lookup) throws Throwable {
-        assert bootstrapMethod.methodType().parameterType(1).equals(CR_String);
-        MethodHandle bsm = bootstrapMethod.resolveConstantRef(lookup);
-        Object[] args = new Object[bootstrapArgs.length + 3];
-        args[0] = lookup;
-        args[1] = name;
-        args[2] = type.resolveConstantRef(lookup);
-        System.arraycopy(bootstrapArgs, 0, args, 3, bootstrapArgs.length);
-        CallSite callSite = (CallSite) bsm.invokeWithArguments(args);
-        return callSite.dynamicInvoker();
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-        DynamicCallSiteRef specifier = (DynamicCallSiteRef) o;
-        return Objects.equals(bootstrapMethod, specifier.bootstrapMethod) &&
-               Arrays.equals(bootstrapArgs, specifier.bootstrapArgs) &&
-               Objects.equals(name, specifier.name) &&
-               Objects.equals(type, specifier.type);
-    }
-
-    @Override
-    public int hashCode() {
-        int result = Objects.hash(bootstrapMethod, name, type);
-        result = 31 * result + Arrays.hashCode(bootstrapArgs);
-        return result;
-    }
-
-    @Override
-    public String toString() {
-        return String.format("DynamicCallSiteRef[%s(%s) %s%s]", bootstrapMethod, Arrays.toString(bootstrapArgs), name, type);
-    }
-}
--- a/src/java.base/share/classes/java/lang/sym/DynamicConstantRef.java	Wed Mar 07 14:59:03 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,403 +0,0 @@
-/*
- * Copyright (c) 2012, 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.sym;
-
-import jdk.internal.lang.annotation.Foldable;
-
-import java.lang.invoke.ConstantBootstraps;
-import java.lang.invoke.MethodHandles;
-import java.util.Arrays;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.function.Function;
-import java.util.stream.Stream;
-
-import static java.lang.sym.ConstantRefs.CR_DynamicConstantRef;
-import static java.util.Objects.requireNonNull;
-import static java.util.stream.Collectors.joining;
-
-/**
- * A nominal reference for a dynamic constant (one described in the constant
- * pool with {@code Constant_Dynamic_info}.)
- *
- * <p>Concrete subtypes of {@linkplain DynamicConstantRef} must be
- * <a href="../doc-files/ValueBased.html">value-based</a>.
- *
- * @param <T> the type of the dynamic constant
- */
-public abstract class DynamicConstantRef<T> implements ConstantRef<T>, Constable<ConstantRef<T>> {
-    private final ConstantMethodHandleRef bootstrapMethod;
-    private final ConstantRef<?>[] bootstrapArgs;
-    private final String name;
-    private final ClassRef type;
-
-    @SuppressWarnings("rawtypes")
-    private static final Map<MethodHandleRef, Function<DynamicConstantRef, ConstantRef<?>>> canonicalMap
-            = Map.ofEntries(Map.entry(ConstantRefs.BSM_PRIMITIVE_CLASS, d -> ClassRef.ofDescriptor(d.name)),
-                            Map.entry(ConstantRefs.BSM_ENUM_CONSTANT, d -> EnumRef.of(d.type, d.name)),
-                            Map.entry(ConstantRefs.BSM_NULL_CONSTANT, d -> ConstantRefs.NULL),
-                            Map.entry(ConstantRefs.BSM_VARHANDLE_STATIC_FIELD,
-                                      d -> VarHandleRef.ofStaticField((ClassRef) d.bootstrapArgs[0],
-                                                                      (String) d.bootstrapArgs[1],
-                                                                      (ClassRef) d.bootstrapArgs[2])),
-                            Map.entry(ConstantRefs.BSM_VARHANDLE_FIELD,
-                                      d -> VarHandleRef.ofField((ClassRef) d.bootstrapArgs[0],
-                                                                (String) d.bootstrapArgs[1],
-                                                                (ClassRef) d.bootstrapArgs[2])),
-                            Map.entry(ConstantRefs.BSM_VARHANDLE_ARRAY,
-                                      d -> VarHandleRef.ofArray((ClassRef) d.bootstrapArgs[0]))
-    );
-
-    /**
-     * Construct a nominal reference for a dynamic constant
-     *
-     * @param bootstrapMethod The bootstrap method for the constant
-     * @param name The name that would appear in the {@code NameAndType} operand
-     *             of the {@code LDC} for this constant
-     * @param type The type that would appear in the {@code NameAndType} operand
-     *             of the {@code LDC} for this constant
-     * @param bootstrapArgs The static arguments to the bootstrap, that would
-     *                      appear in the {@code BootstrapMethods} attribute
-     * @throws NullPointerException if any argument is null
-     * @throws IllegalArgumentException if the bootstrap method is not a
-     * {@link ConstantMethodHandleRef}
-     * @throws IllegalArgumentException if {@code name.length()} is zero
-     */
-    protected DynamicConstantRef(MethodHandleRef bootstrapMethod, String name, ClassRef type, ConstantRef<?>... bootstrapArgs) {
-        requireNonNull(bootstrapMethod);
-        if (!(bootstrapMethod instanceof ConstantMethodHandleRef))
-            throw new IllegalArgumentException("bootstrap method must be a ConstantMethodHandleRef");
-        this.bootstrapMethod = (ConstantMethodHandleRef) bootstrapMethod;
-        this.name = requireNonNull(name);
-        this.type = requireNonNull(type);
-        this.bootstrapArgs = requireNonNull(bootstrapArgs).clone();
-
-        if (name.length() == 0)
-            throw new IllegalArgumentException("Illegal invocation name: " + name);
-    }
-
-    /**
-     * Return a nominal reference for a dynamic constant whose bootstrap, invocation
-     * name, and invocation type are the same as this one, but with the specified
-     * bootstrap arguments
-     *
-     * @param bootstrapArgs the bootstrap arguments
-     * @return the nominal reference
-     * @throws NullPointerException if any argument is null
-     */
-    @Foldable
-    public DynamicConstantRef<T> withArgs(ConstantRef<?>... bootstrapArgs) {
-        return new DynamicConstantRefImpl<>(bootstrapMethod, name, type, bootstrapArgs);
-    }
-
-    /**
-     * Return a nominal reference for a dynamic constant.  If  the bootstrap
-     * corresponds to a well-known bootstrap, for which a more specific nominal
-     * reference type (e.g., ClassRef) is available, then the more specific
-     * nominal reference will be returned.
-     *
-     * @param <T> the type of the dynamic constant
-     * @param bootstrapMethod The bootstrap method for the constant
-     * @param name The name that would appear in the {@code NameAndType} operand
-     *             of the {@code LDC} for this constant
-     * @param type The type that would appear in the {@code NameAndType} operand
-     *             of the {@code LDC} for this constant
-     * @param bootstrapArgs The static arguments to the bootstrap, that would
-     *                      appear in the {@code BootstrapMethods} attribute
-     * @return the nominal reference
-     * @throws NullPointerException if any argument is null
-     * @throws IllegalArgumentException if {@code name.length()} is zero
-     */
-    @Foldable
-    public static<T> ConstantRef<T> ofCanonical(MethodHandleRef bootstrapMethod, String name, ClassRef type, ConstantRef<?>[] bootstrapArgs) {
-        DynamicConstantRef<T> dcr = new DynamicConstantRefImpl<>(bootstrapMethod, name, type, bootstrapArgs);
-        return dcr.canonicalize();
-    }
-
-    private ConstantRef<T> canonicalize() {
-        // @@@ Existing map-based approach is cute but not very robust; need to add more checking of target DCRef
-        @SuppressWarnings("rawtypes")
-        Function<DynamicConstantRef, ConstantRef<?>> f = canonicalMap.get(bootstrapMethod);
-        if (f != null) {
-            @SuppressWarnings("unchecked")
-            ConstantRef<T> converted = (ConstantRef<T>) f.apply(this);
-            return converted;
-        }
-        return this;
-    }
-
-    /**
-     * Return a nominal reference for a dynamic constant.
-     *
-     * @param <T> the type of the dynamic constant
-     * @param bootstrapMethod The bootstrap method for the constant
-     * @param name The name that would appear in the {@code NameAndType} operand
-     *             of the {@code LDC} for this constant
-     * @param type The type that would appear in the {@code NameAndType} operand
-     *             of the {@code LDC} for this constant
-     * @param bootstrapArgs The static arguments to the bootstrap, that would
-     *                      appear in the {@code BootstrapMethods} attribute
-     * @return the nominal reference
-     * @throws NullPointerException if any argument is null
-     * @throws IllegalArgumentException if {@code name.length()} is zero
-     */
-    @Foldable
-    public static<T> DynamicConstantRef<T> of(MethodHandleRef bootstrapMethod, String name, ClassRef type, ConstantRef<?>[] bootstrapArgs) {
-        return new DynamicConstantRefImpl<>(bootstrapMethod, name, type, bootstrapArgs);
-    }
-
-    /**
-     * Return a nominal reference for a dynamic constant whose bootstrap has
-     * no static arguments.
-     *
-     * @param <T> the type of the dynamic constant
-     * @param bootstrapMethod The bootstrap method for the constant
-     * @param name The name that would appear in the {@code NameAndType} operand
-     *             of the {@code LDC} for this constant
-     * @param type The type that would appear in the {@code NameAndType} operand
-     *             of the {@code LDC} for this constant
-     * @return the nominal reference
-     * @throws NullPointerException if any argument is null
-     * @throws IllegalArgumentException if {@code name.length()} is zero
-     */
-    @Foldable
-    public static<T> DynamicConstantRef<T> of(MethodHandleRef bootstrapMethod, String name, ClassRef type) {
-        return new DynamicConstantRefImpl<>(bootstrapMethod, name, type);
-    }
-
-    /**
-     * Return a nominal reference for a dynamic constant whose bootstrap has
-     * no static arguments, and whose name parameter is ignored by the bootstrap
-     *
-     * @param <T> the type of the dynamic constant
-     * @param bootstrapMethod The bootstrap method for the constant
-     * @param type The type that would appear in the {@code NameAndType} operand
-     *             of the {@code LDC} for this constant
-     * @return the nominal reference
-     * @throws NullPointerException if any argument is null
-     * @throws IllegalArgumentException if {@code name.length()} is zero
-     */
-    @Foldable
-    public static<T> DynamicConstantRef<T> of(MethodHandleRef bootstrapMethod, ClassRef type) {
-        return of(bootstrapMethod, "_", type);
-    }
-
-    /**
-     * Return a nominal reference for a dynamic constant whose bootstrap has
-     * no static arguments, and whose type parameter is always the same as the
-     * bootstrap method return type.
-     *
-     * @param <T> the type of the dynamic constant
-     * @param bootstrapMethod The bootstrap method for the constant
-     * @param name The name that would appear in the {@code NameAndType} operand
-     *             of the {@code LDC} for this constant
-     * @return the nominal reference
-     * @throws NullPointerException if any argument is null
-     * @throws IllegalArgumentException if {@code name.length()} is zero
-     */
-    @Foldable
-    public static<T> DynamicConstantRef<T> of(MethodHandleRef bootstrapMethod, String name) {
-        return of(bootstrapMethod, name, bootstrapMethod.methodType().returnType());
-    }
-
-    /**
-     * Return a nominal reference for a dynamic constant whose bootstrap has
-     * no static arguments, whose name parameter is ignored, and whose type
-     * parameter is always the same as the bootstrap method return type.
-     *
-     * @param <T> the type of the dynamic constant
-     * @param bootstrapMethod The bootstrap method for the constant
-     * @return the nominal reference
-     * @throws NullPointerException if any argument is null
-     * @throws IllegalArgumentException if {@code name.length()} is zero
-     */
-    @Foldable
-    public static<T> DynamicConstantRef<T> of(MethodHandleRef bootstrapMethod) {
-        return of(bootstrapMethod, "_");
-    }
-
-    /**
-     * returns The name that would appear in the {@code NameAndType} operand
-     *             of the {@code LDC} for this constant
-     * @return the name
-     */
-    @Foldable
-    public String constantName() {
-        return name;
-    }
-
-    /**
-     * returns The type that would appear in the {@code NameAndType} operand
-     *             of the {@code LDC} for this constant
-     * @return the type
-     */
-    @Foldable
-    public ClassRef constantType() {
-        return type;
-    }
-
-    /**
-     * Returns the bootstrap method for this constant
-     * @return the bootstrap method
-     */
-    @Foldable
-    public MethodHandleRef bootstrapMethod() { return bootstrapMethod; }
-
-    /**
-     * Returns the bootstrap arguments for this constant
-     * @return the bootstrap arguments
-     */
-    public ConstantRef<?>[] bootstrapArgs() { return bootstrapArgs.clone(); }
-
-    private static Object[] resolveArgs(MethodHandles.Lookup lookup, ConstantRef<?>[] args)
-            throws ReflectiveOperationException {
-        try {
-            return Stream.of(args)
-                    .map(arg -> {
-                        try {
-                            return arg.resolveConstantRef(lookup);
-                        }
-                        catch (ReflectiveOperationException e) {
-                            throw new RuntimeException(e);
-                        }
-                    })
-                    .toArray();
-        }
-        catch (RuntimeException e) {
-            if (e.getCause() instanceof ReflectiveOperationException) {
-                throw (ReflectiveOperationException) e.getCause();
-            }
-            else {
-                throw e;
-            }
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    public T resolveConstantRef(MethodHandles.Lookup lookup) throws ReflectiveOperationException {
-        return (T) ConstantBootstraps.makeConstant(bootstrapMethod.resolveConstantRef(lookup),
-                                                   name,
-                                                   type.resolveConstantRef(lookup),
-                                                   resolveArgs(lookup, bootstrapArgs),
-                                                   // TODO pass lookup
-                                                   lookup.lookupClass());
-    }
-
-    @Override
-    public Optional<? extends ConstantRef<? super ConstantRef<T>>> toConstantRef(MethodHandles.Lookup lookup) {
-        ConstantRef<?>[] args = new ConstantRef<?>[bootstrapArgs.length + 5];
-        args[0] = bootstrapMethod.owner().descriptorString();
-        args[1] = bootstrapMethod.methodName();
-        args[2] = bootstrapMethod.methodType().descriptorString();
-        args[3] = name;
-        args[4] = type.descriptorString();
-        System.arraycopy(bootstrapArgs, 0, args, 5, bootstrapArgs.length);
-        return Optional.of(DynamicConstantRef.of(RefBootstraps.BSM_DYNAMICCONSTANTREF, "_", CR_DynamicConstantRef, args));
-    }
-
-    /**
-     * Produce a {@linkplain DynamicConstantRef} describing the invocation of
-     * the specified bootstrap with the specified arguments.
-     *
-     * @param bootstrap nominal reference for the bootstrap method
-     * @param type nominal reference for the type of the resulting constant
-     * @param args nominal references for the bootstrap arguments
-     * @param <T> the type of the resulting constant
-     * @return the dynamic constant reference
-     */
-    protected static<T> DynamicConstantRef<T> ofInvoke(MethodHandleRef bootstrap,
-                                                       ClassRef type,
-                                                       ConstantRef<?>... args) {
-        ConstantRef<?>[] quotedArgs = new ConstantRef<?>[args.length + 1];
-        quotedArgs[0] = bootstrap;
-        System.arraycopy(args, 0, quotedArgs, 1, args.length);
-        return DynamicConstantRef.of(ConstantRefs.BSM_INVOKE, "_", type, quotedArgs);
-    }
-
-    /**
-     * Produce an {@code Optional<DynamicConstantRef<T>>} describing the invocation
-     * of the specified bootstrap with the specified arguments.  The arguments will
-     * be converted to nominal references using the provided lookup.
-     *
-     * @param lookup A {@link MethodHandles.Lookup} to be used to perform
-     *               access control determinations
-     * @param bootstrap nominal reference for the bootstrap method
-     * @param type nominal reference for the type of the resulting constant
-     * @param args nominal references for the bootstrap arguments
-     * @param <T> the type of the resulting constant
-     * @return the dynamic constant reference
-     */
-    static<T> Optional<DynamicConstantRef<T>> symbolizeHelper(MethodHandles.Lookup lookup,
-                                                              MethodHandleRef bootstrap,
-                                                              ClassRef type,
-                                                              Constable<?>... args) {
-        try {
-            ConstantRef<?>[] quotedArgs = new ConstantRef<?>[args.length + 1];
-            quotedArgs[0] = bootstrap;
-            for (int i=0; i<args.length; i++)
-                quotedArgs[i+1] = args[i].toConstantRef(lookup).orElseThrow();
-            return Optional.of(DynamicConstantRef.of(ConstantRefs.BSM_INVOKE, "_", type, quotedArgs));
-        }
-        catch (NoSuchElementException e) {
-            return Optional.empty();
-        }
-    }
-
-    @Override
-    public final boolean equals(Object o) {
-        if (this == o) return true;
-        if (!(o instanceof DynamicConstantRef)) return false;
-        DynamicConstantRef<?> ref = (DynamicConstantRef<?>) o;
-        return Objects.equals(bootstrapMethod, ref.bootstrapMethod) &&
-               Arrays.equals(bootstrapArgs, ref.bootstrapArgs) &&
-               Objects.equals(name, ref.name) &&
-               Objects.equals(type, ref.type);
-    }
-
-    @Override
-    public final int hashCode() {
-        int result = Objects.hash(bootstrapMethod, name, type);
-        result = 31 * result + Arrays.hashCode(bootstrapArgs);
-        return result;
-    }
-
-    @Override
-    public String toString() {
-        return String.format("DynamicConstantRef[%s::%s(%s%s)%s]",
-                             bootstrapMethod.owner().simpleName(),
-                             bootstrapMethod.methodName(),
-                             name.equals("_") ? "" : name + "/",
-                             Stream.of(bootstrapArgs).map(Object::toString).collect(joining(",")),
-                             type.simpleName());
-    }
-
-    private static final class DynamicConstantRefImpl<T> extends DynamicConstantRef<T> {
-        DynamicConstantRefImpl(MethodHandleRef bootstrapMethod, String name, ClassRef type, ConstantRef<?>... bootstrapArgs) {
-            super(bootstrapMethod, name, type, bootstrapArgs);
-        }
-    }
-}
--- a/src/java.base/share/classes/java/lang/sym/EnumRef.java	Wed Mar 07 14:59:03 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2012, 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.sym;
-
-import jdk.internal.lang.annotation.Foldable;
-
-import java.lang.invoke.MethodHandles;
-import java.util.Optional;
-
-import static java.lang.sym.ConstantRefs.CR_ClassRef;
-import static java.lang.sym.ConstantRefs.CR_EnumRef;
-import static java.lang.sym.ConstantRefs.CR_String;
-import static java.util.Objects.requireNonNull;
-
-/**
- * A symbolic reference for an {@code enum} constant.
- *
- * @param <E> the type of the enum constant
- */
-public final class EnumRef<E extends Enum<E>> extends DynamicConstantRef<E> {
-
-    /**
-     * Construct a symbolic reference for the specified enum class and name
-     *
-     * @param constantType the enum class
-     * @param constantName the name of the enum constant
-     * @throws NullPointerException if any argument is null
-     */
-    private EnumRef(ClassRef constantType, String constantName) {
-        super(ConstantRefs.BSM_ENUM_CONSTANT, requireNonNull(constantName), requireNonNull(constantType));
-    }
-
-    /**
-     * Return a symbolic reference for the specified enum class and name
-     *
-     * @param <E> the type of the enum constant
-     * @param enumClass the enum class
-     * @param constantName the name of the enum constant
-     * @return the symbolic reference
-     * @throws NullPointerException if any argument is null
-     */
-    @Foldable
-    public static<E extends Enum<E>> EnumRef<E> of(ClassRef enumClass, String constantName) {
-        return new EnumRef<>(enumClass, constantName);
-    }
-
-    @Override
-    @SuppressWarnings("unchecked")
-    public E resolveConstantRef(MethodHandles.Lookup lookup) throws ReflectiveOperationException {
-        return Enum.valueOf((Class<E>) constantType().resolveConstantRef(lookup), constantName());
-    }
-
-    @Override
-    public Optional<? extends ConstantRef<? super ConstantRef<E>>> toConstantRef(MethodHandles.Lookup lookup) {
-        return Optional.of(DynamicConstantRef.of(RefBootstraps.BSM_ENUMREF, CR_EnumRef).withArgs(constantType().descriptorString(), constantName()));
-    }
-
-    @Override
-    public String toString() {
-        return String.format("EnumRef[%s.%s]", constantType().simpleName(), constantName());
-    }
-}
--- a/src/java.base/share/classes/java/lang/sym/MethodHandleRef.java	Wed Mar 07 14:59:03 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,210 +0,0 @@
-/*
- * Copyright (c) 2012, 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.sym;
-
-import jdk.internal.lang.annotation.Foldable;
-
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandleInfo;
-import java.lang.invoke.MethodType;
-
-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.sym.MethodHandleRef.Kind.STATIC;
-import static java.lang.sym.ConstantRefs.CR_void;
-import static java.util.Objects.requireNonNull;
-
-/**
- * A symbolic reference for a {@link MethodHandle} constant.
- */
-public interface MethodHandleRef
-        extends ConstantRef<MethodHandle>, Constable<ConstantRef<MethodHandle>> {
-    /**
-     * Kinds of method handle refs
-     */
-    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 invokevirtual} */
-        @Foldable VIRTUAL(REF_invokeVirtual),
-        /** A method handle for a method invoked as with {@code invokeinterface} */
-        @Foldable INTERFACE_VIRTUAL(REF_invokeInterface),
-        /** A method handle for a method invoked as with {@code invokespecial} */
-        @Foldable SPECIAL(REF_invokeSpecial),
-        /** 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;
-
-        Kind(int refKind) {
-            this.refKind = refKind;
-        }
-    }
-
-
-    /**
-     * Return a {@code MethodHandleRef} corresponding to an invocation of a
-     * declared method or an accessor for a field
-     *
-     * @param kind The kind of method handle to be described
-     * @param clazz the class declaring the method
-     * @param name the name of the method (ignored if {@code kind} is {@code CONSTRUCTOR})
-     * @param type the method type of the method
-     * @return the {@code MethodHandleRef}
-     * @throws NullPointerException if any of the non-ignored arguments are null
-     */
-    @Foldable
-    static ConstantMethodHandleRef of(Kind kind, ClassRef clazz, String name, MethodTypeRef type) {
-        return new ConstantMethodHandleRef(kind, clazz, name, type);
-    }
-
-    /**
-     * Return a {@code MethodHandleRef} corresponding to an invocation of a
-     * declared method or an accessor for a field
-     *
-     * @param kind The kind of method handle to be described
-     * @param clazz the class declaring the method
-     * @param name the name of the method (ignored if {@code kind} is {@code CONSTRUCTOR})
-     * @param descriptorString descriptor string of the method
-     * @return the {@code MethodHandleRef}
-     * @throws NullPointerException if any of the non-ignored arguments are null
-     */
-    @Foldable
-    static ConstantMethodHandleRef of(Kind kind, ClassRef clazz, String name, String descriptorString) {
-        return of(kind, clazz, name, MethodTypeRef.ofDescriptor(descriptorString));
-    }
-
-    /**
-     * Return a {@code MethodHandleRef} corresponding to an invocation of a
-     * declared method or an accessor for a field
-     *
-     * @param kind The kind of method handle to be described
-     * @param clazz the class declaring the method
-     * @param name the name of the method (ignored if {@code kind} is {@code CONSTRUCTOR})
-     * @param returnType the return type of the method
-     * @param paramTypes the parameter types of the method
-     * @return the {@code MethodHandleRef}
-     * @throws NullPointerException if any of the non-ignored arguments are null
-     */
-    @Foldable
-    static ConstantMethodHandleRef of(Kind kind, ClassRef clazz, String name, ClassRef returnType, ClassRef... paramTypes) {
-        return of(kind, clazz, name, MethodTypeRef.of(returnType, paramTypes));
-    }
-
-    /**
-     * Return a {@code MethodHandleRef} corresponding to a bootstrap method for
-     * an {@code invokedynamic} callsite, which is a static method whose leading
-     * parameter types are {@code Lookup}, {@code String}, and {@code MethodType}
-     * @param clazz the class declaring the method
-     * @param name the name of the method
-     * @param returnType the return type of the method
-     * @param paramTypes the parameter types of the method that follow the three
-     *                   standard leading arguments, if any
-     * @return the {@code MethodHandleRef}
-     * @throws NullPointerException if any of the arguments are null
-     */
-    @Foldable
-    static ConstantMethodHandleRef ofDynamicCallsite(ClassRef clazz, String name, ClassRef returnType, ClassRef... paramTypes) {
-        return of(STATIC, clazz, name, MethodTypeRef.of(returnType, paramTypes).insertParameterTypes(0, ConstantRefs.INDY_BOOTSTRAP_ARGS));
-    }
-
-    /**
-     * Return a {@code MethodHandleRef} corresponding to a bootstrap method for a
-     * dynamic constant, which is a static method whose leading arguments are
-     * {@code Lookup}, {@code String}, and {@code Class}
-     * @param clazz the class declaring the method
-     * @param name the name of the method
-     * @param returnType the return type of the method
-     * @param paramTypes the parameter types of the method that follow the three
-     *                   standard leading arguments, if any
-     * @return the {@code MethodHandleRef}
-     * @throws NullPointerException if any of the arguments are null
-     */
-    @Foldable
-    static ConstantMethodHandleRef ofDynamicConstant(ClassRef clazz, String name, ClassRef returnType, ClassRef... paramTypes) {
-        return of(STATIC, clazz, name, MethodTypeRef.of(returnType, paramTypes).insertParameterTypes(0, ConstantRefs.CONDY_BOOTSTRAP_ARGS));
-    }
-
-    /**
-     * Return a {@code MethodHandleRef} corresponding to accessing a field
-     * @param kind the kind of the method handle; must be one of {@code GETTER},
-     *             {@code SETTER}, {@code STATIC_GETTER}, or {@code STATIC_SETTER}
-     * @param clazz the class declaring the field
-     * @param name the name of the field
-     * @param type the type of the field
-     * @return the {@code MethodHandleRef}
-     * @throws NullPointerException if any of the arguments are null
-     */
-    @Foldable
-    static ConstantMethodHandleRef ofField(Kind kind, ClassRef clazz, String name, ClassRef type) {
-        MethodTypeRef mtr;
-        switch (kind) {
-            case GETTER: mtr = MethodTypeRef.of(type, clazz); break;
-            case SETTER: mtr = MethodTypeRef.of(CR_void, clazz, type); break;
-            case STATIC_GETTER: mtr = MethodTypeRef.of(type); break;
-            case STATIC_SETTER: mtr = MethodTypeRef.of(CR_void, type); break;
-            default:
-                throw new IllegalArgumentException(kind.toString());
-        }
-        return new ConstantMethodHandleRef(kind, clazz, name, mtr);
-    }
-
-    /**
-     * Return the type of the method described by this symbolic reference
-     * @return the method type
-     */
-    @Foldable
-    MethodTypeRef methodType();
-
-    /**
-     * Return a {@linkplain MethodHandleRef} that describes this method handle
-     * adapted to a different type, as if by {@link MethodHandle#asType(MethodType)}.
-     *
-     * @param type the new type
-     * @return the adapted method handle reference
-     */
-    @Foldable
-    default MethodHandleRef asType(MethodTypeRef type) {
-        return (methodType().equals(type)) ? this : new AsTypeMethodHandleRef(this, type);
-    }
-}
--- a/src/java.base/share/classes/java/lang/sym/MethodTypeRef.java	Wed Mar 07 14:59:03 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,188 +0,0 @@
-/*
- * Copyright (c) 2012, 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.sym;
-
-import jdk.internal.lang.annotation.Foldable;
-
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Optional;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import static java.util.Objects.requireNonNull;
-
-/**
- * A symbolic reference for a {@linkplain MethodType} constant.
- */
-public interface MethodTypeRef extends ConstantRef<MethodType>, Constable<ConstantRef<MethodType>> {
-    /**
-     * Create a {@linkplain MethodTypeRef} from a method descriptor string
-     *
-     * @param descriptor the method descriptor string
-     * @return a {@linkplain MethodTypeRef} describing the desired method type
-     * @throws IllegalArgumentException if the descriptor string is not a valid
-     * method descriptor
-     */
-    @Foldable
-    static MethodTypeRef ofDescriptor(String descriptor) {
-        return ConstantMethodTypeRef.ofDescriptor(descriptor);
-    }
-
-    /**
-     * Returns a {@linkplain MethodTypeRef} for the specified return type and
-     * parameter types.
-     *
-     * @param returnDescriptor a {@linkplain ClassRef} describing the return type
-     * @param paramDescriptors {@linkplain ClassRef}s describing the argument types
-     * @return a {@linkplain MethodTypeRef} describing the desired method type
-     */
-    @Foldable
-    static MethodTypeRef of(ClassRef returnDescriptor, ClassRef... paramDescriptors) {
-        return new ConstantMethodTypeRef(returnDescriptor, paramDescriptors);
-    }
-
-    /**
-     * Get the return type of the method type described by this {@linkplain MethodTypeRef}
-     * @return the return type
-     */
-    @Foldable
-    ClassRef returnType();
-
-    /**
-     * Get the number of parameters of the method type described by
-     * this {@linkplain MethodTypeRef}
-     * @return the number of parameters
-     */
-    @Foldable
-    int parameterCount();
-
-    /**
-     * Get the parameter type of the {@code index}'th parameter of the method type
-     * described by this {@linkplain MethodTypeRef}
-     *
-     * @param index the index of the parameter to retrieve
-     * @return the parameter type
-     * @throws IndexOutOfBoundsException if the index is outside the half-open
-     * range {[0, parameterCount())}
-     */
-    @Foldable
-    ClassRef parameterType(int index);
-
-    /**
-     * Get the parameter types as a {@link List}
-     *
-     * @return the parameter types
-     */
-    List<ClassRef> parameterList();
-
-    /**
-     * Get the parameter types as an array
-     *
-     * @return the parameter types
-     */
-    ClassRef[] parameterArray();
-
-    /**
-     * Return a {@linkplain MethodTypeRef} that is identical to
-     * this one, except with the specified return type
-     *
-     * @param returnType the new return type
-     * @return the new method type descriptor
-     */
-    @Foldable
-    MethodTypeRef changeReturnType(ClassRef returnType);
-
-    /**
-     * Return a {@linkplain MethodTypeRef} that is identical to this one,
-     * except that a single parameter type has been changed to the provided
-     * value
-     *
-     * @param index the index of the parameter to change
-     * @param paramType the new parameter type
-     * @return the new method type descriptor
-     * @throws IndexOutOfBoundsException if the index is outside the half-open
-     * range {[0, parameterCount)}
-     */
-    @Foldable
-    MethodTypeRef changeParameterType(int index, ClassRef paramType);
-
-    /**
-     * Return a {@linkplain MethodTypeRef} that is identical to this one,
-     * except that a range of parameter types have been removed
-     *
-     * @param start the index of the first parameter to remove
-     * @param end the index after the last parameter to remove
-     * @return the new method type descriptor
-     * @throws IndexOutOfBoundsException if {@code start} is outside the half-open
-     * range {[0, parameterCount)}, or {@code end} is outside the closed range
-     * {@code [0, parameterCount]}
-     */
-    @Foldable
-    MethodTypeRef dropParameterTypes(int start, int end);
-
-    /**
-     * Return a {@linkplain MethodTypeRef} that is identical to this one,
-     * except that a range of additional parameter types have been inserted
-     *
-     * @param pos the index at which to insert the first inserted parameter
-     * @param paramTypes the new parameter types to insert
-     * @return the new method type descriptor
-     * @throws IndexOutOfBoundsException if {@code pos} is outside the closed
-     * range {[0, parameterCount]}
-     */
-    @Foldable
-    MethodTypeRef insertParameterTypes(int pos, ClassRef... paramTypes);
-
-    /**
-     * Return the method type descriptor string
-     * @return the method type descriptor string
-     */
-    default String descriptorString() {
-        return String.format("(%s)%s",
-                             Stream.of(parameterArray())
-                                   .map(ClassRef::descriptorString)
-                                   .collect(Collectors.joining()),
-                             returnType().descriptorString());
-    }
-
-    /**
-     * Return a human-readable descriptor for this method type, using the
-     * canonical names for parameter and return types
-     * @return the human-readable descriptor for this method type
-     */
-    default String simpleDescriptor() {
-        return String.format("(%s)%s",
-                             Stream.of(parameterArray())
-                                   .map(ClassRef::simpleName)
-                                   .collect(Collectors.joining(",")),
-                             returnType().simpleName());
-    }
-}
--- a/src/java.base/share/classes/java/lang/sym/PrimitiveClassRef.java	Wed Mar 07 14:59:03 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2012, 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.sym;
-
-import java.lang.invoke.MethodHandles;
-import java.util.Optional;
-
-import sun.invoke.util.Wrapper;
-
-import static java.util.Objects.requireNonNull;
-
-/**
- * PrimitiveClassRef
- *
- * @author Brian Goetz
- */
-final class PrimitiveClassRef extends DynamicConstantRef<Class<?>> implements ClassRef {
-    private final String descriptor;
-
-    /**
-     * Create a {@linkplain ClassRef} from a descriptor string for a primitive type
-     *
-     * @param descriptor the descriptor string
-     * @throws IllegalArgumentException if the descriptor string does not
-     * describe a valid primitive type
-     */
-    PrimitiveClassRef(String descriptor) {
-        super(ConstantRefs.BSM_PRIMITIVE_CLASS, requireNonNull(descriptor), ConstantRefs.CR_Class);
-        if (descriptor.length() != 1
-            || "VIJCSBFDZ".indexOf(descriptor.charAt(0)) < 0)
-            throw new IllegalArgumentException(String.format("%s is not a valid primitive type descriptor", descriptor));
-        this.descriptor = descriptor;
-    }
-
-    @Override
-    public String descriptorString() {
-        return descriptor;
-    }
-
-    @Override
-    public Class<?> resolveConstantRef(MethodHandles.Lookup lookup) {
-        return Wrapper.forBasicType(descriptorString().charAt(0)).primitiveType();
-    }
-
-    @Override
-    public Optional<? extends ConstantRef<? super ConstantRef<Class<?>>>> toConstantRef(MethodHandles.Lookup lookup) {
-        return DynamicConstantRef.symbolizeHelper(lookup, ConstantRefs.MHR_CLASSREF_FACTORY, ConstantRefs.CR_ClassRef, descriptorString());
-    }
-
-    @Override
-    public String toString() {
-        return String.format("PrimitiveClassRef[%s]", simpleName());
-    }
-}
--- a/src/java.base/share/classes/java/lang/sym/RefBootstraps.java	Wed Mar 07 14:59:03 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,160 +0,0 @@
-/*
- * Copyright (c) 2012, 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.sym;
-
-import jdk.internal.lang.annotation.Foldable;
-
-import java.lang.invoke.MethodHandles;
-
-import static java.lang.sym.ConstantRefs.CR_ClassRef;
-import static java.lang.sym.ConstantRefs.CR_ConstantRef;
-import static java.lang.sym.ConstantRefs.CR_DynamicConstantRef;
-import static java.lang.sym.ConstantRefs.CR_EnumRef;
-import static java.lang.sym.ConstantRefs.CR_MethodHandleRef;
-import static java.lang.sym.ConstantRefs.CR_MethodTypeRef;
-import static java.lang.sym.ConstantRefs.CR_String;
-
-/**
- * RefBoostraps
- *
- * @author Brian Goetz
- */
-public final class RefBootstraps {
-    private RefBootstraps() { }
-
-    @Foldable
-    private static final ClassRef THIS_CLASS = ClassRef.of("java.lang.sym.RefBootstraps");
-
-    /** Bootstrap for ClassRef */
-    @Foldable
-    public static final MethodHandleRef BSM_CLASSREF = MethodHandleRef.ofDynamicConstant(THIS_CLASS, "classRef", CR_ClassRef,
-                                                                                         CR_String);
-
-    /** Bootstrap for MethodTypeRef */
-    @Foldable
-    public static final MethodHandleRef BSM_METHODTYPEREF = MethodHandleRef.ofDynamicConstant(THIS_CLASS, "methodTypeRef", CR_MethodTypeRef,
-                                                                                              CR_String);
-
-    /** Bootstrap for MethodHandleRef */
-    @Foldable
-    public static final MethodHandleRef BSM_METHODHANDLEREF = MethodHandleRef.ofDynamicConstant(THIS_CLASS, "methodHandleRef", CR_MethodHandleRef,
-                                                                                                CR_String, CR_String, CR_String, CR_String);
-
-    /** Bootstrap for DynamicConstantRef */
-    @Foldable
-    public static final MethodHandleRef BSM_DYNAMICCONSTANTREF = MethodHandleRef.ofDynamicConstant(THIS_CLASS, "dynamicConstantRef", CR_DynamicConstantRef,
-                                                                                                   CR_String, CR_String, CR_String, CR_String, CR_String,
-
-                                                                                                   CR_ConstantRef.array());
-
-    /** Bootstrap for ClassRef */
-    @Foldable
-    public static final MethodHandleRef BSM_ENUMREF = MethodHandleRef.ofDynamicConstant(THIS_CLASS, "enumRef", CR_EnumRef,
-                                                                                        CR_String, CR_String);
-    /**
-     * Bootstrap for ClassRef
-     *
-     * @param lookup ignored
-     * @param name ignored
-     * @param clazz ignored
-     * @param descriptor descriptor for class
-     * @return the ClassRef
-     */
-    public static ClassRef classRef(MethodHandles.Lookup lookup, String name, Class<ClassRef> clazz,
-                                    String descriptor) {
-        // @@@ Can fold descriptor into name channel, with encoding from BytecodeName
-        return ClassRef.ofDescriptor(descriptor);
-    }
-
-    /**
-     * Bootstrap for MethodTypeRef
-     *
-     * @param lookup ignored
-     * @param name ignored
-     * @param clazz ignored
-     * @param descriptor descriptor for method
-     * @return the MethodTypeRef
-     */
-    public static MethodTypeRef methodTypeRef(MethodHandles.Lookup lookup, String name, Class<ClassRef> clazz,
-                                              String descriptor) {
-        // @@@ Can fold descriptor into name channel, with encoding from BytecodeName
-        return MethodTypeRef.ofDescriptor(descriptor);
-    }
-
-    /**
-     * Bootstrap for MethodHandleRef
-     *
-     * @param lookup ignored
-     * @param name ignored
-     * @param clazz ignored
-     * @param bsmKindName kind
-     * @param bsmOwner owner
-     * @param bsmName name
-     * @param bsmDesc desc
-     * @return the MethodHandleRef
-     */
-    public static MethodHandleRef methodHandleRef(MethodHandles.Lookup lookup, String name, Class<ClassRef> clazz,
-                                                  String bsmKindName, String bsmOwner, String bsmName, String bsmDesc) {
-        return MethodHandleRef.of(MethodHandleRef.Kind.valueOf(bsmKindName), ClassRef.ofDescriptor(bsmOwner), bsmName, MethodTypeRef.ofDescriptor(bsmDesc));
-    }
-
-    /**
-     * Bootstrap for DynamicConstantRef
-     *
-     * @param lookup ignored
-     * @param name ignored
-     * @param clazz ignored
-     * @param bsmOwner owner
-     * @param bsmName name
-     * @param bsmDesc desc
-     * @param invName invName
-     * @param invType invType
-     * @param args bsm args
-     * @return the DynamicConstantRef
-     */
-    public static DynamicConstantRef<?> dynamicConstantRef(MethodHandles.Lookup lookup, String name, Class<ClassRef> clazz,
-                                                           String bsmOwner, String bsmName, String bsmDesc,
-                                                           String invName, String invType,
-                                                           ConstantRef<?>... args) {
-        return DynamicConstantRef.of(MethodHandleRef.of(MethodHandleRef.Kind.STATIC, ClassRef.ofDescriptor(bsmOwner), bsmName, MethodTypeRef.ofDescriptor(bsmDesc)),
-                                     invName, ClassRef.ofDescriptor(invType), args);
-
-    }
-
-    /**
-     * Bootstrap for EnumRef
-     *
-     * @param lookup ignored
-     * @param name ignored
-     * @param clazz ignored
-     * @param classDescriptor enum class
-     * @param constantName enum constant
-     * @return the EnumRef
-     */
-    public static EnumRef<?> enumRef(MethodHandles.Lookup lookup, String name, Class<ClassRef> clazz,
-                                     String classDescriptor, String constantName) {
-        return EnumRef.of(ClassRef.ofDescriptor(classDescriptor), constantName);
-    }
-}
--- a/src/java.base/share/classes/java/lang/sym/VarHandleRef.java	Wed Mar 07 14:59:03 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,234 +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.sym;
-
-import jdk.internal.lang.annotation.Foldable;
-
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.VarHandle;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.NoSuchElementException;
-import java.util.Objects;
-import java.util.Optional;
-
-import static java.lang.sym.ConstantRefs.CR_ClassRef;
-import static java.lang.sym.ConstantRefs.CR_String;
-import static java.lang.sym.ConstantRefs.CR_VarHandleRef;
-
-/**
- * A symbolic reference for a {@link VarHandle} constant.
- */
-public final class VarHandleRef extends DynamicConstantRef<VarHandle>
-        implements Constable<ConstantRef<VarHandle>> {
-
-    private static final ConstantRef<?>[] EMPTY_ARGS = new ConstantRef<?>[0];
-
-    /**
-     * Kinds of variable handle refs
-     */
-    private enum Kind {
-        @Foldable
-        FIELD(ConstantRefs.BSM_VARHANDLE_FIELD, ConstantRefs.MHR_VARHANDLEREF_OFFIELD),
-        @Foldable
-        STATIC_FIELD(ConstantRefs.BSM_VARHANDLE_STATIC_FIELD, ConstantRefs.MHR_VARHANDLEREF_OFSTATIC),
-        @Foldable
-        ARRAY(ConstantRefs.BSM_VARHANDLE_ARRAY, ConstantRefs.MHR_VARHANDLEREF_OFARRAY);
-
-        final MethodHandleRef bootstrapMethod;
-        final MethodHandleRef refFactory;
-
-        Kind(MethodHandleRef bootstrapMethod, MethodHandleRef refFactory) {
-            this.bootstrapMethod = bootstrapMethod;
-            this.refFactory = refFactory;
-        }
-
-        List<ConstantRef<?>> toBSMArgs(ClassRef declaringClass, String name, ClassRef varType) {
-            switch (this) {
-                case FIELD:
-                case STATIC_FIELD:
-                    return List.of(declaringClass, name, varType);
-                case ARRAY:
-                    return List.of(declaringClass);
-                default:
-                    throw new InternalError("Cannot reach here");
-            }
-        }
-    }
-
-    private final Kind kind;
-    private final ClassRef declaringClass;
-    private final ClassRef varType;
-
-    /**
-     * Construct a {@linkplain VarHandleRef}
-     *
-     * @param kind the kind of of the var handle
-     * @param name the name of the field, for field var handles
-     * @param declaringClass the name of the declaring class, for field var handles
-     * @param varType the type of the variable
-     * @throws NullPointerException if any required argument is null
-     */
-    private VarHandleRef(Kind kind, String name, ClassRef declaringClass, ClassRef varType) {
-        super(kind.bootstrapMethod, name,
-              ConstantRefs.CR_VarHandle,
-              kind.toBSMArgs(declaringClass, name, varType).toArray(EMPTY_ARGS));
-        this.kind = kind;
-        this.declaringClass = declaringClass;
-        this.varType = varType;
-    }
-
-    /**
-     * Returns a {@code VarHandleRef} corresponding to a {@link VarHandle}
-     * for an instance field.
-     *
-     * @param declaringClass the class in which the field is declared
-     * @param name the name of the field
-     * @param fieldType the type of the field
-     * @return the {@code VarHandleRef}
-     * @throws NullPointerException if any of the arguments are null
-     */
-    @Foldable
-    public static VarHandleRef ofField(ClassRef declaringClass, String name, ClassRef fieldType) {
-        Objects.requireNonNull(declaringClass);
-        Objects.requireNonNull(name);
-        Objects.requireNonNull(fieldType);
-        return new VarHandleRef(Kind.FIELD, name, declaringClass, fieldType);
-    }
-
-    /**
-     * Returns a {@code VarHandleRef} corresponding to a {@link VarHandle}
-     * for a static field.
-     *
-     * @param declaringClass the class in which the field is declared
-     * @param name the name of the field
-     * @param fieldType the type of the field
-     * @return the {@code VarHandleRef}
-     * @throws NullPointerException if any of the arguments are null
-     */
-    @Foldable
-    public static VarHandleRef ofStaticField(ClassRef declaringClass, String name, ClassRef fieldType) {
-        Objects.requireNonNull(declaringClass);
-        Objects.requireNonNull(name);
-        Objects.requireNonNull(fieldType);
-        return new VarHandleRef(Kind.STATIC_FIELD, name, declaringClass, fieldType);
-    }
-
-    /**
-     * Returns a {@code VarHandleRef} corresponding to a {@link VarHandle}
-     * for for an array type.
-     *
-     * @param arrayClass the type of the array
-     * @return the {@code VarHandleRef}
-     * @throws NullPointerException if any of the arguments are null
-     */
-    @Foldable
-    public static VarHandleRef ofArray(ClassRef arrayClass) {
-        Objects.requireNonNull(arrayClass);
-        if (!arrayClass.isArray())
-            throw new IllegalArgumentException("Array class argument not an array: " + arrayClass);
-        return new VarHandleRef(Kind.ARRAY, "_", arrayClass, arrayClass.componentType());
-    }
-
-    /**
-     * Returns the type of the variable described by this symbolic reference.
-     *
-     * @return the variable type
-     */
-    @Foldable
-    public ClassRef varType() { return varType; }
-
-    // @@@ should this be the of co-ordinate types? there by better mirroring
-    // VarHandle this makes it slightly more involved since the array VH has
-    // to inject it's index
-    /**
-     * Returns the declaring class of the variable described by this symbolic
-     * reference.
-     *
-     * <p>If the declaring class is an array type then the declaring class
-     * will be the component type of the array type.
-     *
-     * @return the declaring class
-     */
-    @Foldable
-    public ClassRef declaringClass() { return declaringClass; }
-
-    /* @@@
-    MethodTypeRef accessModeTypeRef(AccessMode accessMode)
-     */
-
-    /* @@@
-    MethodHandleRef toMethodHandleRef(AccessMode accessMode)
-     */
-
-    @Override
-    public VarHandle resolveConstantRef(MethodHandles.Lookup lookup) throws ReflectiveOperationException {
-        switch (kind) {
-            case FIELD:
-                return lookup.findVarHandle(declaringClass.resolveConstantRef(lookup),
-                                            constantName(),
-                                            varType.resolveConstantRef(lookup));
-            case STATIC_FIELD:
-                return lookup.findStaticVarHandle(declaringClass.resolveConstantRef(lookup),
-                                                  constantName(),
-                                                  varType.resolveConstantRef(lookup));
-            case ARRAY:
-                return MethodHandles.arrayElementVarHandle(declaringClass.resolveConstantRef(lookup));
-            default:
-                throw new InternalError("Cannot reach here");
-        }
-    }
-
-    @Override
-    public Optional<ConstantRef<ConstantRef<VarHandle>>> toConstantRef(MethodHandles.Lookup lookup) {
-        try {
-            ArrayList<ConstantRef<?>> args = new ArrayList<>();
-            args.add(declaringClass.toConstantRef(lookup).orElseThrow());
-            if (kind != Kind.ARRAY) {
-                args.add(constantName());
-                args.add(varType.toConstantRef(lookup).orElseThrow());
-            }
-            return Optional.of(DynamicConstantRef.ofInvoke(kind.refFactory, CR_VarHandleRef,
-                                                           args.toArray(EMPTY_ARGS)));
-        } catch (NoSuchElementException e) {
-            return Optional.empty();
-        }
-    }
-
-    @Override
-    public String toString() {
-        switch (kind) {
-            case FIELD:
-            case STATIC_FIELD:
-                return String.format("VarHandleRef[%s%s.%s:%s]",
-                                     (kind == Kind.STATIC_FIELD) ? "static " : "",
-                                     declaringClass.simpleName(), constantName(), varType.simpleName());
-            case ARRAY:
-                return String.format("VarHandleRef[%s[]]", declaringClass.simpleName());
-            default:
-                throw new InternalError("Cannot reach here");
-        }
-    }
-}
--- a/src/java.base/share/classes/java/lang/sym/package-info.java	Wed Mar 07 14:59:03 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +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.
- */
-
-/**
- * Classes and interfaces to represent <em>nominal references</em> to run-time
- * 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(java.lang.sym.ConstantRef)}),
- * or compile- and link-time program analysis.
- *
- * <p>Every API that reads and writes bytecode instructions needs to model the
- * operands to these instructions, or other classfile structures such as entries
- * in the bootstrap methods table or stack maps, which frequently correspond to
- * entries in the classfile constant pool. Such entries can denote values of
- * fundamental types, such as strings or integers; parts of a program, such as
- * classes or method handles; or values of arbitrary user-defined types.  The
- * {@link java.lang.sym.ConstantRef} hierarchy provides a representation of
- * constant pool entries in nominal form that is convenient for APIs to model
- * operands of bytecode instructions.
- *
- * <p>A {@link java.lang.sym.ConstantRef} is a description of a constant
- * value.  Such a description is the <em>nominal form</em> of the constant value;
- * it is not hte value itself, but rather a "recipe" for storing the value in
- * a constant pool entry, or reconstituting the value given a class loading
- * context.  Every {@link java.lang.sym.ConstantRef} knows how to <em>resolve</em>
- * itself -- compute the value that it describes -- via the
- * {@link java.lang.sym.ConstantRef#resolveConstantRef(java.lang.invoke.MethodHandles.Lookup)}
- * method.  This allows an API which accepts {@link java.lang.sym.ConstantRef}
- * objects to evaluate them reflectively, provided that the classes and methods
- * referenced in their nominal description are present and accessible.
- *
- * <p>The subtypes of of {@link java.lang.sym.ConstantRef} describe various kinds
- * of constant values.  For each type of constant pool entry defined in JVMS 4.4,
- * there is a corresponding subtype of {@link java.lang.sym.ConstantRef}:
- * {@code ConstantClassRef}, {@code ConstantMethodTypeRef},
- * {@code ConstantMethodHandleRef}, {@code String}, {@code Integer}, {@code Long},
- * {@code Float}, {@code Double}, and {@code DynamicConstantRef}.  These classes
- * provides accessor methods to extrac the information needed to store a value
- * in the constant pool.  When a bytecode-writing API encounters a {@link java.lang.sym.ConstantRef},
- * it should case over these types to represent it in the constant pool.
- * When a bytecode-reading API encounters a constant pool entry, it can
- * convert it to the appropriate type of nominal reference.  For dynamic
- * constants, bytecode-reading APIs may wish to use the factory
- * {@link java.lang.sym.DynamicConstantRef#ofCanonical(java.lang.sym.MethodHandleRef, java.lang.String, java.lang.sym.ClassRef, java.lang.sym.ConstantRef[])},
- * which will inspect the bootstrap and, for well-known bootstraps, instantiate
- * a more specific subtype of {@link java.lang.sym.DynamicConstantRef}, such as
- * {@link java.lang.sym.EnumRef}.
- *
- * <p>Another way to obtain the nominal description of a value is to ask the value
- * itself.  A {@link java.lang.sym.Constable} is a type whose values can describe
- * themselves in nominal form as a {@link java.lang.sym.ConstantRef}.  Fundamental
- * types such as {@link java.lang.String} and {@link java.lang.Class} implement
- * {@link java.lang.sym.Constable}, and every instance of these classes can
- * provide itself in nominal form.  User-defined classes can also implement
- * {@link java.lang.sym.Constable}.
- *
- * <p>This package also includes the {@link java.lang.sym.DynamicCallSiteRef}
- * class, which is a representation of a constant pool entry that is never an
- * argument to bytecode instructions.  Instead, it is a description of the
- * bootstrap method, invocation name and type, and static arguments associated
- * with an {@code invokedynamic} instruction, and is used by the
- * {@link java.lang.invoke.Intrinsics#invokedynamic(java.lang.sym.DynamicCallSiteRef, java.lang.Object...)}
- * API for expressing {@code invokedynamic} call sites in Java source files.
- *
- */
-package java.lang.sym;
-
--- a/src/java.base/share/classes/jdk/internal/lang/annotation/Foldable.java	Wed Mar 07 14:59:03 2018 -0500
+++ b/src/java.base/share/classes/jdk/internal/lang/annotation/Foldable.java	Wed Mar 07 16:34:02 2018 -0500
@@ -26,8 +26,8 @@
 
 import java.lang.annotation.*;
 
-import java.lang.sym.Constable;
-import java.lang.sym.ConstantRef;
+import java.lang.invoke.constant.Constable;
+import java.lang.invoke.constant.ConstantRef;
 import java.lang.invoke.Intrinsics;
 
 /**
--- a/src/java.base/share/classes/module-info.java	Wed Mar 07 14:59:03 2018 -0500
+++ b/src/java.base/share/classes/module-info.java	Wed Mar 07 16:34:02 2018 -0500
@@ -83,7 +83,7 @@
     exports java.lang.module;
     exports java.lang.ref;
     exports java.lang.reflect;
-    exports java.lang.sym;
+    exports java.lang.invoke.constant;
     exports java.math;
     exports java.net;
     exports java.net.spi;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java	Wed Mar 07 14:59:03 2018 -0500
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java	Wed Mar 07 16:34:02 2018 -0500
@@ -499,8 +499,8 @@
         varHandleType = enterClass("java.lang.invoke.VarHandle");
         methodHandleType = enterClass("java.lang.invoke.MethodHandle");
         methodHandlesLookupType = enterClass("java.lang.invoke.MethodHandles$Lookup");
-        dynamicConstantRefType = enterClass("java.lang.sym.DynamicConstantRef");
-        classRefType = enterClass("java.lang.sym.ClassRef");
+        dynamicConstantRefType = enterClass("java.lang.invoke.constant.DynamicConstantRef");
+        classRefType = enterClass("java.lang.invoke.constant.ClassRef");
         intrinsicsType = enterClass("java.lang.invoke.Intrinsics");
         methodTypeType = enterClass("java.lang.invoke.MethodType");
         foldableType = enterClass("jdk.internal.lang.annotation.Foldable");
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Constables.java	Wed Mar 07 14:59:03 2018 -0500
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Constables.java	Wed Mar 07 16:34:02 2018 -0500
@@ -100,14 +100,14 @@
         log = Log.instance(context);
         constablesVisitor = ConstablesVisitor.instance(context);
         try {
-            directMethodHandleRefClass = Class.forName("java.lang.sym.ConstantMethodHandleRef", false, null);
-            methodTypeRefClass = Class.forName("java.lang.sym.MethodTypeRef", false, null);
-            classRefClass = Class.forName("java.lang.sym.ClassRef", false, null);
-            constantRefClass = Class.forName("java.lang.sym.ConstantRef", false, null);
-            constableClass = Class.forName("java.lang.sym.Constable", false, null);
-            dynamicCallsiteRefClass = Class.forName("java.lang.sym.DynamicCallSiteRef", false, null);
-            dynamicConstantClass = Class.forName("java.lang.sym.DynamicConstantRef", false, null);
-            symRefs = Class.forName("java.lang.sym.ConstantRefs", false, null);
+            directMethodHandleRefClass = Class.forName("java.lang.invoke.constant.ConstantMethodHandleRef", false, null);
+            methodTypeRefClass = Class.forName("java.lang.invoke.constant.MethodTypeRef", false, null);
+            classRefClass = Class.forName("java.lang.invoke.constant.ClassRef", false, null);
+            constantRefClass = Class.forName("java.lang.invoke.constant.ConstantRef", false, null);
+            constableClass = Class.forName("java.lang.invoke.constant.Constable", false, null);
+            dynamicCallsiteRefClass = Class.forName("java.lang.invoke.constant.DynamicCallSiteRef", false, null);
+            dynamicConstantClass = Class.forName("java.lang.invoke.constant.DynamicConstantRef", false, null);
+            symRefs = Class.forName("java.lang.invoke.constant.ConstantRefs", false, null);
         } catch (ClassNotFoundException ex) {
             directMethodHandleRefClass = null;
             methodTypeRefClass = null;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/invoke/constant/ClassRefTest.java	Wed Mar 07 16:34:02 2018 -0500
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2012, 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.
+ */
+
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.lang.invoke.constant.ClassRef;
+import java.lang.invoke.constant.ConstantRefs;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+/**
+ * @test
+ * @run testng ClassRefTest
+ * @summary unit tests for java.lang.invoke.constant.ClassRef
+ */
+@Test
+public class ClassRefTest extends SymbolicRefTest {
+
+    private void testClassRef(ClassRef r) throws ReflectiveOperationException {
+        testSymbolicRef(r);
+
+        // Test descriptor accessor, factory, equals
+        assertEquals(r, ClassRef.ofDescriptor(r.descriptorString()));
+
+        if (!r.descriptorString().equals("V")) {
+            assertEquals(r, r.array().componentType());
+            // Commutativity: array -> resolve -> componentType -> toSymbolic
+            assertEquals(r, r.array().resolveConstantRef(LOOKUP).getComponentType().toConstantRef(LOOKUP).orElseThrow());
+            // Commutativity: resolve -> array -> toSymbolic -> component type
+            assertEquals(r, Array.newInstance(r.resolveConstantRef(LOOKUP), 0).getClass().toConstantRef(LOOKUP).orElseThrow().componentType());
+        }
+
+        if (r.isArray()) {
+            assertEquals(r, r.componentType().array());
+            assertEquals(r, r.resolveConstantRef(LOOKUP).getComponentType().toConstantRef(LOOKUP).orElseThrow().array());
+            assertEquals(r, Array.newInstance(r.componentType().resolveConstantRef(LOOKUP), 0).getClass().toConstantRef(LOOKUP).orElseThrow());
+        }
+    }
+
+    private void testClassRef(ClassRef r, Class<?> c) throws ReflectiveOperationException {
+        testClassRef(r);
+
+        assertEquals(r.resolveConstantRef(LOOKUP), c);
+        assertEquals(c.toConstantRef(LOOKUP).orElseThrow(), r);
+        assertEquals(ClassRef.ofDescriptor(c.toDescriptorString()), r);
+    }
+
+    public void testSymbolicRefsConstants() throws ReflectiveOperationException {
+        int tested = 0;
+        Field[] fields = ConstantRefs.class.getDeclaredFields();
+        for (Field f : fields) {
+            try {
+                if (f.getType().equals(ClassRef.class)
+                    && ((f.getModifiers() & Modifier.STATIC) != 0)
+                    && ((f.getModifiers() & Modifier.PUBLIC) != 0)) {
+                    ClassRef cr = (ClassRef) f.get(null);
+                    Class c = cr.resolveConstantRef(MethodHandles.lookup());
+                    testClassRef(cr, c);
+                    ++tested;
+                }
+            }
+            catch (Throwable e) {
+                fail("Error testing field " + f.getName(), e);
+            }
+        }
+
+        assertTrue(tested > 0);
+    }
+
+    public void testPrimitiveClassRef() throws ReflectiveOperationException {
+        for (Primitives p : Primitives.values()) {
+            List<ClassRef> refs = List.of(ClassRef.ofDescriptor(p.descriptor),
+                                          p.classRef,
+                                          (ClassRef) p.clazz.toConstantRef().orElseThrow());
+            for (ClassRef c : refs) {
+                testClassRef(c, p.clazz);
+                assertTrue(c.isPrimitive());
+                assertEquals(p.descriptor, c.descriptorString());
+                assertEquals(p.name, c.simpleName());
+                refs.forEach(cc -> assertEquals(c, cc));
+                if (p != Primitives.VOID) {
+                    testClassRef(c.array(), p.arrayClass);
+                    assertEquals(c, ((ClassRef) p.arrayClass.toConstantRef().orElseThrow()).componentType());
+                    assertEquals(c, p.classRef.array().componentType());
+                }
+            }
+
+            for (Primitives other : Primitives.values()) {
+                ClassRef otherDescr = ClassRef.ofDescriptor(other.descriptor);
+                if (p != other)
+                    refs.forEach(c -> assertNotEquals(c, otherDescr));
+                else
+                    refs.forEach(c -> assertEquals(c, otherDescr));
+            }
+        }
+    }
+
+    public void testSimpleClassRef() throws ReflectiveOperationException {
+
+        List<ClassRef> stringClassRefs = Arrays.asList(ClassRef.ofDescriptor("Ljava/lang/String;"),
+                                                       ClassRef.of("java.lang", "String"),
+                                                       ClassRef.of("java.lang.String"),
+                                                       ClassRef.of("java.lang.String").array().componentType(),
+                                                       String.class.toConstantRef(LOOKUP).orElseThrow());
+        for (ClassRef r : stringClassRefs) {
+            testClassRef(r, String.class);
+            assertFalse(r.isPrimitive());
+            assertEquals("Ljava/lang/String;", r.descriptorString());
+            assertEquals("String", r.simpleName());
+            assertEquals(r.array().resolveConstantRef(LOOKUP), String[].class);
+            stringClassRefs.forEach(rr -> assertEquals(r, rr));
+        }
+
+        testClassRef(ClassRef.of("java.lang.String").array(), String[].class);
+        testClassRef(ClassRef.of("java.util.Map").inner("Entry"), Map.Entry.class);
+
+        ClassRef thisClassRef = ClassRef.ofDescriptor("LClassRefTest;");
+        assertEquals(thisClassRef, ClassRef.of("", "ClassRefTest"));
+        assertEquals(thisClassRef, ClassRef.of("ClassRefTest"));
+        assertEquals(thisClassRef.simpleName(), "ClassRefTest");
+        testClassRef(thisClassRef, ClassRefTest.class);
+    }
+
+    public void testArrayClassRef() throws ReflectiveOperationException {
+        for (String d : basicDescs) {
+            ClassRef a0 = ClassRef.ofDescriptor(d);
+            ClassRef a1 = a0.array();
+            ClassRef a2 = a1.array();
+
+            testClassRef(a0);
+            testClassRef(a1);
+            testClassRef(a2);
+            assertFalse(a0.isArray());
+            assertTrue(a1.isArray());
+            assertTrue(a2.isArray());
+            assertFalse(a1.isPrimitive());
+            assertFalse(a2.isPrimitive());
+            assertEquals(a0.descriptorString(), d);
+            assertEquals(a1.descriptorString(), "[" + a0.descriptorString());
+            assertEquals(a2.descriptorString(), "[[" + a0.descriptorString());
+
+            try {
+                assertEquals(a0, a0.componentType());
+                fail("Didn't throw ISE");
+            }
+            catch (IllegalStateException expected) {
+                // succeed
+            }
+            assertEquals(a0, a1.componentType());
+            assertEquals(a1, a2.componentType());
+
+            assertNotEquals(a0, a1);
+            assertNotEquals(a1, a2);
+
+            assertEquals(a1, ClassRef.ofDescriptor("[" + d));
+            assertEquals(a2, ClassRef.ofDescriptor("[[" + d));
+            assertEquals(classToDescriptor(a0.resolveConstantRef(LOOKUP)), a0.descriptorString());
+            assertEquals(classToDescriptor(a1.resolveConstantRef(LOOKUP)), a1.descriptorString());
+            assertEquals(classToDescriptor(a2.resolveConstantRef(LOOKUP)), a2.descriptorString());
+        }
+    }
+
+    public void testBadClassRefs() {
+        List<String> badDescriptors = List.of("II", "I;", "Q", "L",
+                                              "java.lang.String", "[]", "Ljava/lang/String",
+                                              "Ljava.lang.String;", "java/lang/String");
+
+        for (String d : badDescriptors) {
+            try {
+                ClassRef constant = ClassRef.ofDescriptor(d);
+                fail(d);
+            }
+            catch (IllegalArgumentException e) {
+                // good
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/invoke/constant/CondyRefTest.java	Wed Mar 07 16:34:02 2018 -0500
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2012, 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.
+ */
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.lang.invoke.constant.ClassRef;
+import java.lang.invoke.constant.ConstantRef;
+import java.lang.invoke.constant.DynamicConstantRef;
+import java.lang.invoke.constant.EnumRef;
+import java.lang.invoke.constant.MethodHandleRef;
+import java.lang.invoke.constant.ConstantRefs;
+import java.lang.invoke.constant.VarHandleRef;
+
+import org.testng.annotations.Test;
+
+import static java.lang.invoke.constant.ConstantRefs.CR_MethodHandle;
+import static java.lang.invoke.constant.ConstantRefs.CR_Object;
+import static java.lang.invoke.constant.ConstantRefs.CR_String;
+import static java.lang.invoke.constant.ConstantRefs.CR_VarHandle;
+import static java.lang.invoke.constant.ConstantRefs.CR_int;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotEquals;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+/**
+ * @test
+ * @run testng CondyRefTest
+ * @summary unit tests for java.lang.invoke.constant.CondyRefTest
+ */
+@Test
+public class CondyRefTest extends SymbolicRefTest {
+    private final static ConstantRef<?>[] EMPTY_ARGS = new ConstantRef<?>[0];
+    private final static ClassRef CR_ConstantBootstraps = ClassRef.of("java.lang.invoke.ConstantBootstraps");
+
+    private static<T> void testDCR(DynamicConstantRef<T> r, T c) throws ReflectiveOperationException {
+        assertEquals(r, DynamicConstantRef.of(r.bootstrapMethod(), r.constantName(), r.constantType(), r.bootstrapArgs()));
+        assertEquals(r.resolveConstantRef(LOOKUP), c);
+    }
+
+    private void testVarHandleRef(DynamicConstantRef<VarHandle> r, VarHandle vh) throws ReflectiveOperationException  {
+        testSymbolicRef(r);
+        assertEquals(r.resolveConstantRef(LOOKUP), vh);
+        assertEquals(vh.toConstantRef(LOOKUP).orElseThrow(), r);
+    }
+
+    private static<E extends Enum<E>> void testEnumRef(EnumRef<E> r, E e) throws ReflectiveOperationException {
+        testSymbolicRef(r);
+
+        assertEquals(r, EnumRef.of(r.constantType(), r.constantName()));
+        assertEquals(r.resolveConstantRef(LOOKUP), e);
+    }
+
+    public void testNullConstant() throws ReflectiveOperationException {
+        DynamicConstantRef<?> r = (DynamicConstantRef<?>) ConstantRefs.NULL;
+        assertEquals(r, DynamicConstantRef.of(r.bootstrapMethod(), r.constantName(), r.constantType(), r.bootstrapArgs()));
+        assertNull(r.resolveConstantRef(LOOKUP));
+    }
+
+    static String concatBSM(MethodHandles.Lookup lookup, String name, Class<?> type, String a, String b) {
+        return a + b;
+    }
+
+    public void testDynamicConstant() throws ReflectiveOperationException {
+        MethodHandleRef bsmRef = MethodHandleRef.ofDynamicConstant(ClassRef.of("CondyRefTest"), "concatBSM",
+                                                                   CR_String, CR_String, CR_String);
+        DynamicConstantRef<String> r = DynamicConstantRef.<String>of(bsmRef).withArgs("foo", "bar");
+        testDCR(r, "foobar");
+    }
+
+    public void testNested() throws Throwable {
+        MethodHandleRef invoker = MethodHandleRef.ofDynamicConstant(CR_ConstantBootstraps, "invoke", CR_Object, CR_MethodHandle, CR_Object.array());
+        MethodHandleRef format = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_String, "format", CR_String, CR_String, CR_Object.array());
+
+        String s = (String) invoker.resolveConstantRef(LOOKUP)
+                                   .invoke(LOOKUP, "", String.class,
+                                           format.resolveConstantRef(LOOKUP), "%s%s", "moo", "cow");
+        assertEquals(s, "moocow");
+
+        DynamicConstantRef<String> ref = DynamicConstantRef.<String>of(invoker).withArgs(format, "%s%s", "moo", "cow");
+        testDCR(ref, "moocow");
+
+        DynamicConstantRef<String> ref2 = DynamicConstantRef.<String>of(invoker).withArgs(format, "%s%s", ref, "cow");
+        testDCR(ref2, "moocowcow");
+    }
+
+    enum MyEnum { A, B, C }
+
+    public void testEnumRef() throws ReflectiveOperationException {
+        ClassRef enumClass = ClassRef.of("CondyRefTest").inner("MyEnum");
+
+        testEnumRef(EnumRef.of(enumClass, "A"), MyEnum.A);
+        testEnumRef(EnumRef.of(enumClass, "B"), MyEnum.B);
+        testEnumRef(EnumRef.of(enumClass, "C"), MyEnum.C);
+    }
+
+    static class MyClass {
+        static int sf;
+        int f;
+    }
+
+    public void testVarHandles() throws ReflectiveOperationException {
+        ClassRef testClass = ClassRef.of("CondyRefTest").inner("MyClass");
+        MyClass instance = new MyClass();
+
+        // static varHandle
+        VarHandleRef vhc = VarHandleRef.ofStaticField(testClass, "sf", CR_int);
+        VarHandle varHandle = LOOKUP.findStaticVarHandle(MyClass.class, "sf", int.class);
+        testVarHandleRef(vhc, varHandle);
+
+        assertEquals(varHandle.varType(), int.class);
+        varHandle.set(8);
+        assertEquals(8, (int) varHandle.get());
+        assertEquals(MyClass.sf, 8);
+
+        // static varHandle
+        vhc = VarHandleRef.ofField(testClass, "f", CR_int);
+        varHandle = LOOKUP.findVarHandle(MyClass.class, "f", int.class);
+        testVarHandleRef(vhc, varHandle);
+
+        assertEquals(varHandle.varType(), int.class);
+        varHandle.set(instance, 9);
+        assertEquals(9, (int) varHandle.get(instance));
+        assertEquals(instance.f, 9);
+
+        vhc = VarHandleRef.ofArray(CR_int.array());
+        varHandle = MethodHandles.arrayElementVarHandle(int[].class);
+        testVarHandleRef(vhc, varHandle);
+
+        int[] ints = new int[3];
+        varHandle.set(ints, 0, 1);
+        varHandle.set(ints, 1, 2);
+        varHandle.set(ints, 2, 3);
+
+        assertEquals(1, varHandle.get(ints, 0));
+        assertEquals(2, varHandle.get(ints, 1));
+        assertEquals(3, varHandle.get(ints, 2));
+        assertEquals(1, ints[0]);
+        assertEquals(2, ints[1]);
+        assertEquals(3, ints[2]);
+    }
+
+    private<T> void assertLifted(ConstantRef<T> prototype,
+                                 DynamicConstantRef<T> nonCanonical,
+                                 ConstantRef<T> canonical) {
+        Class<?> clazz = prototype.getClass();
+
+        assertTrue(canonical != nonCanonical);
+        assertTrue(clazz.isAssignableFrom(canonical.getClass()));
+        assertFalse(clazz.isAssignableFrom(nonCanonical.getClass()));
+        assertTrue(prototype.equals(canonical));
+        assertTrue(canonical.equals(prototype));
+        if (prototype instanceof DynamicConstantRef) {
+            assertTrue(canonical.equals(nonCanonical));
+            assertTrue(nonCanonical.equals(canonical));
+            assertTrue(prototype.equals(nonCanonical));
+            assertTrue(nonCanonical.equals(prototype));
+        }
+    }
+
+    public void testLifting() {
+        DynamicConstantRef<Object> unliftedNull = DynamicConstantRef.of(ConstantRefs.BSM_NULL_CONSTANT, "_", CR_Object, EMPTY_ARGS);
+        assertEquals(ConstantRefs.NULL, unliftedNull);
+        assertTrue(ConstantRefs.NULL != unliftedNull);
+        assertTrue(ConstantRefs.NULL == DynamicConstantRef.ofCanonical(ConstantRefs.BSM_NULL_CONSTANT, "_", CR_Object, EMPTY_ARGS));
+        assertTrue(ConstantRefs.NULL == DynamicConstantRef.ofCanonical(ConstantRefs.BSM_NULL_CONSTANT, "_", CR_String, EMPTY_ARGS));
+        assertTrue(ConstantRefs.NULL == DynamicConstantRef.ofCanonical(ConstantRefs.BSM_NULL_CONSTANT, "wahoo", CR_Object, EMPTY_ARGS));
+
+        assertLifted(CR_int,
+                     DynamicConstantRef.of(ConstantRefs.BSM_PRIMITIVE_CLASS, "I", ConstantRefs.CR_Class, EMPTY_ARGS),
+                     DynamicConstantRef.ofCanonical(ConstantRefs.BSM_PRIMITIVE_CLASS, "I", ConstantRefs.CR_Class, EMPTY_ARGS));
+
+        ClassRef enumClass = ClassRef.of("CondyRefTest").inner("MyEnum");
+        assertLifted(EnumRef.of(enumClass, "A"),
+                     DynamicConstantRef.of(ConstantRefs.BSM_ENUM_CONSTANT, "A", enumClass, EMPTY_ARGS),
+                     DynamicConstantRef.<MyEnum>ofCanonical(ConstantRefs.BSM_ENUM_CONSTANT, "A", enumClass, EMPTY_ARGS));
+
+        ClassRef testClass = ClassRef.of("CondyRefTest").inner("MyClass");
+        assertLifted(VarHandleRef.ofStaticField(testClass, "sf", CR_int),
+                     DynamicConstantRef.of(ConstantRefs.BSM_VARHANDLE_STATIC_FIELD, "sf", CR_VarHandle, new ConstantRef<?>[] {testClass, "sf", CR_int }),
+                     DynamicConstantRef.ofCanonical(ConstantRefs.BSM_VARHANDLE_STATIC_FIELD, "sf", CR_VarHandle, new ConstantRef<?>[] {testClass, "sf", CR_int }));
+        assertLifted(VarHandleRef.ofField(testClass, "f", CR_int),
+                     DynamicConstantRef.of(ConstantRefs.BSM_VARHANDLE_FIELD, "f", CR_VarHandle, new ConstantRef<?>[] {testClass, "f", CR_int }),
+                     DynamicConstantRef.ofCanonical(ConstantRefs.BSM_VARHANDLE_FIELD, "f", CR_VarHandle, new ConstantRef<?>[] {testClass, "f", CR_int }));
+        assertLifted(VarHandleRef.ofArray(CR_int.array()),
+                     DynamicConstantRef.of(ConstantRefs.BSM_VARHANDLE_ARRAY, "_", CR_VarHandle, new ConstantRef<?>[] {CR_int.array() }),
+                     DynamicConstantRef.ofCanonical(ConstantRefs.BSM_VARHANDLE_ARRAY, "_", CR_VarHandle, new ConstantRef<?>[] {CR_int.array() }));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/invoke/constant/IndyRefTest.java	Wed Mar 07 16:34:02 2018 -0500
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012, 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.
+ */
+
+import org.testng.annotations.Test;
+
+/**
+ * IndyRefTest
+ *
+ * @author Brian Goetz
+ */
+@Test
+public class IndyRefTest {
+    // @@@ non-intrinsified: get dynamic invoker, and invoke
+    // test toSymRef and back
+    // test canonicalization; StringConcat?
+    // @@@ intrinsified tests too
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/invoke/constant/IntrinsifiedRefTest.java	Wed Mar 07 16:34:02 2018 -0500
@@ -0,0 +1,364 @@
+/*
+ * 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.
+ */
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.constant.ClassRef;
+import java.lang.invoke.constant.Constable;
+import java.lang.invoke.constant.ConstantRef;
+import java.lang.invoke.constant.EnumRef;
+import java.lang.invoke.constant.MethodHandleRef;
+import java.lang.invoke.constant.MethodTypeRef;
+import java.lang.invoke.constant.ConstantRefs;
+import java.util.function.Supplier;
+
+import org.testng.annotations.Test;
+
+import static java.lang.invoke.Intrinsics.ldc;
+import static java.lang.invoke.constant.MethodHandleRef.Kind.GETTER;
+import static java.lang.invoke.constant.MethodHandleRef.Kind.SETTER;
+import static java.lang.invoke.constant.MethodHandleRef.Kind.STATIC_GETTER;
+import static java.lang.invoke.constant.MethodHandleRef.Kind.STATIC_SETTER;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.fail;
+
+/**
+ * @test
+ * @compile -XDdoConstantFold IntrinsifiedRefTest.java
+ * @run testng IntrinsifiedRefTest
+ * @summary Integration test for intrinsification of XxxRef
+ */
+@Test
+public class IntrinsifiedRefTest {
+    public static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
+
+    private static final ClassRef CR_THIS = ClassRef.of("IntrinsifiedRefTest");
+    private static final ClassRef CR_TESTCLASS = CR_THIS.inner("TestClass");
+    private static final ClassRef CR_TESTINTF = CR_THIS.inner("TestInterface");
+    private static final ClassRef CR_TESTSUPERCLASS = CR_THIS.inner("TestSuperclass");
+    private static final ClassRef CR_TESTENUM = CR_THIS.inner("TestEnum");
+    private static final String NONEXISTENT_CLASS = "foo.Bar";
+    private static final String INACCESSIBLE_CLASS = "java.lang.invoke.DirectMethodHandle";
+
+    private static final MethodHandleRef MHR_TESTCLASS_CTOR = MethodHandleRef.of(MethodHandleRef.Kind.CONSTRUCTOR, CR_TESTCLASS, "<ignored!>", MethodTypeRef.ofDescriptor("()V"));
+    private static final MethodHandleRef MHR_TESTCLASS_SM = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_TESTCLASS, "sm", "(I)I");
+    private static final MethodHandleRef MHR_TESTINTF_SM = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_TESTINTF, "sm", "(I)I");
+    private static final MethodHandleRef MHR_TESTCLASS_M = MethodHandleRef.of(MethodHandleRef.Kind.VIRTUAL, CR_TESTCLASS, "m", MethodTypeRef.ofDescriptor("(I)I"));
+    private static final MethodHandleRef MHR_TESTINTF_M = MethodHandleRef.of(MethodHandleRef.Kind.INTERFACE_VIRTUAL, CR_TESTINTF, "m", MethodTypeRef.ofDescriptor("(I)I"));
+    private static final MethodHandleRef MHR_TESTCLASS_PM_SPECIAL = MethodHandleRef.of(MethodHandleRef.Kind.SPECIAL, CR_TESTCLASS, "pm", MethodTypeRef.ofDescriptor("(I)I"));
+    private static final MethodHandleRef MHR_TESTINTF_PM_SPECIAL = MethodHandleRef.of(MethodHandleRef.Kind.SPECIAL, CR_TESTINTF, "pm", MethodTypeRef.ofDescriptor("(I)I"));
+    private static final MethodHandleRef MHR_TESTCLASS_PSM = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_TESTCLASS, "psm", MethodTypeRef.ofDescriptor("(I)I"));
+    private static final MethodHandleRef MHR_TESTINTF_PSM = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_TESTINTF, "psm", MethodTypeRef.ofDescriptor("(I)I"));
+    private static final MethodHandleRef MHR_TESTSUPER_M_SPECIAL = MethodHandleRef.of(MethodHandleRef.Kind.SPECIAL, CR_TESTSUPERCLASS, "m", "(I)I");
+    private static final MethodHandleRef MHR_TESTINTF_M_SPECIAL = MethodHandleRef.of(MethodHandleRef.Kind.SPECIAL, CR_TESTINTF, "m", "(I)I");
+    private static final MethodHandleRef MHR_TESTCLASS_SF_SETTER = MethodHandleRef.ofField(STATIC_SETTER, CR_TESTCLASS, "sf", ConstantRefs.CR_int);
+    private static final MethodHandleRef MHR_TESTCLASS_SF_GETTER = MethodHandleRef.ofField(STATIC_GETTER, CR_TESTCLASS, "sf", ConstantRefs.CR_int);
+    private static final MethodHandleRef MHR_TESTINTF_SF_GETTER = MethodHandleRef.ofField(STATIC_GETTER, CR_TESTINTF, "sf", ConstantRefs.CR_int);
+    private static final MethodHandleRef MHR_TESTCLASS_F_SETTER = MethodHandleRef.ofField(SETTER, CR_TESTCLASS, "f", ConstantRefs.CR_int);
+    private static final MethodHandleRef MHR_TESTCLASS_F_GETTER = MethodHandleRef.ofField(GETTER, CR_TESTCLASS, "f", ConstantRefs.CR_int);
+
+
+
+    private static <T extends Constable> void assertIntrinsic(ConstantRef<T> ref, T intrinsified, T target) throws ReflectiveOperationException {
+        assertEquals(target, intrinsified);
+        assertEquals(ref.resolveConstantRef(LOOKUP), intrinsified);
+        assertEquals(intrinsified.toConstantRef(LOOKUP).orElseThrow(), ref);
+    }
+
+    private static<T extends Constable> void assertIntrinsicFail(ConstantRef<T> ref, Supplier<T> supplier, Class<? extends Throwable> exception) {
+        try {
+            T t = supplier.get();
+            fail("Expected failure resolving " + ref);
+        } catch (Throwable e) {
+            if (exception.isAssignableFrom(e.getClass()))
+                return;
+            else if (e instanceof BootstrapMethodError) {
+                Throwable cause = e.getCause();
+                if (cause != null && exception.isAssignableFrom(cause.getClass()))
+                    return;
+            }
+            fail(String.format("Expected %s, found %s for %s", exception, e.getClass(), ref));
+        }
+    }
+
+    public void testLdcClass() throws ReflectiveOperationException {
+        ClassRef cr1 = ClassRef.ofDescriptor("Ljava/lang/String;");
+        ClassRef cr2 = ClassRef.of("java.lang.String");
+        ClassRef cr3 = ClassRef.of("java.lang", "String");
+
+        assertIntrinsic(cr1, ldc(cr1), String.class);
+        assertIntrinsic(cr2, ldc(cr2), String.class);
+        assertIntrinsic(cr3, ldc(cr3), String.class);
+
+        ClassRef cr4 = ClassRef.ofDescriptor("[Ljava/lang/String;");
+        ClassRef cr5 = cr2.array();
+        assertIntrinsic(cr4, ldc(cr4), String[].class);
+        assertIntrinsic(cr5, ldc(cr5), String[].class);
+
+        ClassRef cr6 = ClassRef.ofDescriptor("I");
+        assertIntrinsic(cr6, ldc(cr6), int.class);
+        assertIntrinsic(ConstantRefs.CR_int, ldc(ConstantRefs.CR_int), int.class);
+
+        ClassRef cr7 = ClassRef.ofDescriptor("[I");
+        ClassRef cr8 = ConstantRefs.CR_int.array();
+        assertIntrinsic(cr7, ldc(cr7), int[].class);
+        assertIntrinsic(cr8, ldc(cr8), int[].class);
+    }
+
+    public void negLdcClass() {
+        ClassRef cr = ClassRef.of(NONEXISTENT_CLASS);
+        assertIntrinsicFail(cr, () -> ldc(cr), NoClassDefFoundError.class);
+
+        ClassRef cr2 = ClassRef.of(INACCESSIBLE_CLASS);
+        assertIntrinsicFail(cr2, () -> ldc(cr2), IllegalAccessError.class);
+    }
+
+    public void testLdcMethodType() throws ReflectiveOperationException {
+        MethodTypeRef mtr1 = MethodTypeRef.ofDescriptor("()V");
+        MethodTypeRef mtr2 = MethodTypeRef.of(ConstantRefs.CR_void);
+        assertIntrinsic(mtr1, ldc(mtr1), MethodType.methodType(void.class));
+        assertIntrinsic(mtr2, ldc(mtr2), MethodType.methodType(void.class));
+
+        MethodTypeRef mtr3 = MethodTypeRef.ofDescriptor("(I)I");
+        MethodTypeRef mtr4 = MethodTypeRef.of(ConstantRefs.CR_int, ConstantRefs.CR_int);
+        assertIntrinsic(mtr3, ldc(mtr3), MethodType.methodType(int.class, int.class));
+        assertIntrinsic(mtr4, ldc(mtr4), MethodType.methodType(int.class, int.class));
+
+        MethodTypeRef mtr5 = MethodTypeRef.ofDescriptor("(Ljava/lang/String;)Ljava/lang/String;");
+        MethodTypeRef mtr6 = MethodTypeRef.of(ConstantRefs.CR_String, ConstantRefs.CR_String);
+        assertIntrinsic(mtr5, ldc(mtr5), MethodType.methodType(String.class, String.class));
+        assertIntrinsic(mtr6, ldc(mtr6), MethodType.methodType(String.class, String.class));
+
+        MethodTypeRef mtr7 = MethodTypeRef.ofDescriptor("([I)[Ljava/lang/String;");
+        assertIntrinsic(mtr7, ldc(mtr7), MethodType.methodType(String[].class, int[].class));
+    }
+
+    public void negLdcMethodType() {
+        MethodTypeRef mtr1 = MethodTypeRef.of(ClassRef.of(NONEXISTENT_CLASS));
+        assertIntrinsicFail(mtr1, () -> ldc(mtr1), NoClassDefFoundError.class);
+
+        MethodTypeRef mtr2 = MethodTypeRef.of(ClassRef.of(INACCESSIBLE_CLASS));
+        assertIntrinsicFail(mtr2, () -> ldc(mtr2), IllegalAccessError.class);
+    }
+
+    public void testLdcEnum() throws ReflectiveOperationException {
+        EnumRef<TestEnum> enr1 = EnumRef.of(CR_TESTENUM, "A");
+        assertIntrinsic(enr1, ldc(enr1), TestEnum.A);
+
+        EnumRef<TestEnum> enr2 = EnumRef.of(CR_TESTENUM, "B");
+        assertIntrinsic(enr2, ldc(enr2), TestEnum.B);
+    }
+
+    public void negLdcEnum() {
+        EnumRef<TestEnum> enr1 = EnumRef.of(CR_TESTENUM, "C");
+        assertIntrinsicFail(enr1, () -> ldc(enr1), IllegalArgumentException.class);
+
+        EnumRef<TestEnum> enr2 = EnumRef.of(ClassRef.of(NONEXISTENT_CLASS), "A");
+        assertIntrinsicFail(enr2, () -> ldc(enr2), NoClassDefFoundError.class);
+
+        EnumRef<TestEnum> enr3 = EnumRef.of(CR_THIS, "A");
+        assertIntrinsicFail(enr3, () -> ldc(enr3), IllegalArgumentException.class);
+
+        EnumRef<TestEnum> enr4 = EnumRef.of(ClassRef.of(INACCESSIBLE_CLASS), "A");
+        assertIntrinsicFail(enr4, () -> ldc(enr4), IllegalAccessError.class);
+    }
+
+    public void testLdcSelfConstants() throws ReflectiveOperationException {
+        assertIntrinsic("Foo", ldc("Foo"), "Foo");
+        assertIntrinsic(1, ldc(1), 1);
+        assertIntrinsic(1L, ldc(1L), 1L);
+        assertIntrinsic(2.0f, ldc(2.0f), 2.0f);
+        assertIntrinsic(3.0d, ldc(3.0d), 3.0d);
+    }
+
+    public void testLdcMethodHandleFromInner() throws Throwable {
+        TestClass.ldcMethodHandleFromInner();
+        TestClass.negLdcMethodHandleFromInner();
+        TestInterface.testLdcMethodHandleFromIntf(new TestInterface(){});
+    }
+
+    public void testLdcMethodHandle() throws Throwable {
+        TestClass instance = (TestClass) ldc(MHR_TESTCLASS_CTOR).invokeExact();
+
+        assertEquals(5, (int) ldc(MHR_TESTCLASS_SM).invokeExact(5));
+        assertEquals(0, (int) ldc(MHR_TESTINTF_SM).invokeExact(5));
+
+        assertEquals(5, (int) ldc(MHR_TESTCLASS_M).invokeExact(instance, 5));
+        assertEquals(5, (int) ldc(MHR_TESTINTF_M).invoke(instance, 5));
+
+        ldc(MHR_TESTCLASS_SF_SETTER).invokeExact(8);
+        assertEquals(TestClass.sf, 8);
+        assertEquals(8, (int) ldc(MHR_TESTCLASS_SF_GETTER).invokeExact());
+
+        assertEquals(3, (int) ldc(MHR_TESTINTF_SF_GETTER).invokeExact());
+
+        ldc(MHR_TESTCLASS_F_SETTER).invokeExact(instance, 9); assertEquals(instance.f, 9);
+        assertEquals(9, (int) ldc(MHR_TESTCLASS_F_GETTER).invokeExact(instance));
+    }
+
+    public void negLdcMethodHandle() {
+        // Accessible classes, inaccessible methods
+        assertIntrinsicFail(MHR_TESTCLASS_PM_SPECIAL, () -> ldc(MHR_TESTCLASS_PM_SPECIAL), IllegalAccessError.class);
+        assertIntrinsicFail(MHR_TESTINTF_PM_SPECIAL, () -> ldc(MHR_TESTINTF_PM_SPECIAL), IllegalAccessError.class);
+        assertIntrinsicFail(MHR_TESTCLASS_PSM, () -> ldc(MHR_TESTCLASS_PSM), IllegalAccessError.class);
+        assertIntrinsicFail(MHR_TESTINTF_PSM, () -> ldc(MHR_TESTINTF_PSM), IllegalAccessError.class);
+
+        // Accessible class and method, but illegal super access
+        assertIntrinsicFail(MHR_TESTSUPER_M_SPECIAL, () -> ldc(MHR_TESTSUPER_M_SPECIAL), IllegalAccessError.class);
+        assertIntrinsicFail(MHR_TESTINTF_M_SPECIAL, () -> ldc(MHR_TESTINTF_M_SPECIAL), IncompatibleClassChangeError.class);
+
+        // Method kind mismatches -- intf, virtual, static
+        MethodHandleRef intfMethodAsVirtual = MethodHandleRef.of(MethodHandleRef.Kind.VIRTUAL, CR_TESTINTF, "m", MethodTypeRef.ofDescriptor("(I)I"));
+        MethodHandleRef intfMethodAsStatic = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_TESTINTF, "m", MethodTypeRef.ofDescriptor("(I)I"));
+        MethodHandleRef virtualMethodAsIntf = MethodHandleRef.of(MethodHandleRef.Kind.INTERFACE_VIRTUAL, CR_TESTCLASS, "m", MethodTypeRef.ofDescriptor("(I)I"));
+        MethodHandleRef virtualMethodAsStatic = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_TESTCLASS, "m", MethodTypeRef.ofDescriptor("(I)I"));
+        MethodHandleRef staticMethodAsVirtual = MethodHandleRef.of(MethodHandleRef.Kind.VIRTUAL, CR_TESTCLASS, "sm", MethodTypeRef.ofDescriptor("(I)I"));
+        MethodHandleRef staticMethodAsIntf = MethodHandleRef.of(MethodHandleRef.Kind.INTERFACE_VIRTUAL, CR_TESTINTF, "sm", MethodTypeRef.ofDescriptor("(I)I"));
+
+        assertIntrinsicFail(intfMethodAsVirtual, () -> ldc(intfMethodAsVirtual), IncompatibleClassChangeError.class);
+        assertIntrinsicFail(intfMethodAsStatic, () -> ldc(intfMethodAsStatic), IncompatibleClassChangeError.class);
+        assertIntrinsicFail(virtualMethodAsIntf, () -> ldc(virtualMethodAsIntf), IncompatibleClassChangeError.class);
+        assertIntrinsicFail(virtualMethodAsStatic, () -> ldc(virtualMethodAsStatic), IncompatibleClassChangeError.class);
+        assertIntrinsicFail(staticMethodAsVirtual, () -> ldc(staticMethodAsVirtual), IncompatibleClassChangeError.class);
+        assertIntrinsicFail(staticMethodAsIntf, () -> ldc(staticMethodAsIntf), IncompatibleClassChangeError.class);
+
+        // Field kind mismatch -- instance/static
+        MethodHandleRef staticFieldAsInstance = MethodHandleRef.ofField(MethodHandleRef.Kind.GETTER, CR_TESTCLASS, "sf", ConstantRefs.CR_int);
+        MethodHandleRef instanceFieldAsStatic = MethodHandleRef.of(MethodHandleRef.Kind.STATIC_GETTER, CR_TESTCLASS, "f", ConstantRefs.CR_int);
+
+        assertIntrinsicFail(staticFieldAsInstance, () -> ldc(staticFieldAsInstance), IncompatibleClassChangeError.class);
+        assertIntrinsicFail(instanceFieldAsStatic, () -> ldc(instanceFieldAsStatic), IncompatibleClassChangeError.class);
+
+        // Setter for final field
+        MethodHandleRef finalStaticSetter = MethodHandleRef.ofField(MethodHandleRef.Kind.STATIC_SETTER, CR_TESTCLASS, "sff", ConstantRefs.CR_int);
+        MethodHandleRef finalSetter = MethodHandleRef.ofField(MethodHandleRef.Kind.SETTER, CR_TESTCLASS, "ff", ConstantRefs.CR_int);
+
+        assertIntrinsicFail(finalStaticSetter, () -> ldc(finalStaticSetter), IllegalAccessError.class);
+        assertIntrinsicFail(finalSetter, () -> ldc(finalSetter), IllegalAccessError.class);
+
+        // Nonexistent owner
+        MethodHandleRef r1 = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, ClassRef.of(NONEXISTENT_CLASS), "m", "()V");
+        assertIntrinsicFail(r1, () -> ldc(r1), NoClassDefFoundError.class);
+
+        // Inaccessible owner
+        MethodHandleRef r2 = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, ClassRef.of(INACCESSIBLE_CLASS), "m", "()V");
+        assertIntrinsicFail(r2, () -> ldc(r2), IllegalAccessError.class);
+
+        // Nonexistent method, ctor, field
+        MethodHandleRef r3 = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_TESTCLASS, "nonexistent", "()V");
+        MethodHandleRef r4 = MethodHandleRef.of(MethodHandleRef.Kind.VIRTUAL, CR_TESTCLASS, "nonexistent", "()V");
+        MethodHandleRef r5 = MethodHandleRef.of(MethodHandleRef.Kind.CONSTRUCTOR, CR_TESTCLASS, "<ignored>", "(I)V");
+        MethodHandleRef r6 = MethodHandleRef.ofField(MethodHandleRef.Kind.GETTER, CR_TESTCLASS, "nonexistent", ConstantRefs.CR_int);
+        MethodHandleRef r7 = MethodHandleRef.ofField(MethodHandleRef.Kind.SETTER, CR_TESTCLASS, "nonexistent", ConstantRefs.CR_int);
+        MethodHandleRef r8 = MethodHandleRef.ofField(MethodHandleRef.Kind.STATIC_GETTER, CR_TESTCLASS, "nonexistent", ConstantRefs.CR_int);
+        MethodHandleRef r9 = MethodHandleRef.ofField(MethodHandleRef.Kind.STATIC_SETTER, CR_TESTCLASS, "nonexistent", ConstantRefs.CR_int);
+
+        assertIntrinsicFail(r3, () -> ldc(r3), NoSuchMethodError.class);
+        assertIntrinsicFail(r4, () -> ldc(r4), NoSuchMethodError.class);
+        assertIntrinsicFail(r5, () -> ldc(r5), NoSuchMethodError.class);
+        assertIntrinsicFail(r6, () -> ldc(r6), NoSuchFieldError.class);
+        assertIntrinsicFail(r7, () -> ldc(r7), NoSuchFieldError.class);
+        assertIntrinsicFail(r8, () -> ldc(r8), NoSuchFieldError.class);
+        assertIntrinsicFail(r9, () -> ldc(r9), NoSuchFieldError.class);
+    }
+
+    public void testLdcDynamicConstants() throws ReflectiveOperationException {
+        assertNull(ldc(ConstantRefs.NULL));
+        assertIntrinsic(ConstantRefs.CR_int, ldc(ConstantRefs.CR_int), int.class);
+        // @@@ VarHandle
+        // @@@ invoke (including multiple deep)
+    }
+
+    public void negLdcDynamicConstants() {
+        // @@@ negative tests for nonexistent/inaccessible bootstrap
+        // @@@ negative tests for bootstrap parameter mismatch
+    }
+
+    private enum TestEnum {
+        A, B;
+    }
+
+    private interface TestInterface {
+        public static final int sf = 3;
+
+        static int sm(int x) { return 0; }
+        default int m(int x) { return 0; }
+        private int pm(int x) { return 1; }
+        private static int psm(int x) { return 2; }
+
+        static void testLdcMethodHandleFromIntf(TestInterface testInterface) throws Throwable {
+            assertEquals(1, ldc(MHR_TESTINTF_PM_SPECIAL).invoke(testInterface, 1));
+            assertEquals(2, ldc(MHR_TESTINTF_PSM).invoke(1));
+        }
+    }
+
+    private static class TestSuperclass {
+        public int m(int x) { return -1; }
+    }
+
+    private static class TestClass extends TestSuperclass implements TestInterface {
+
+        static final int sff = 7;
+        static final int ff = 8;
+
+        static int sf;
+        int f;
+
+        public TestClass()  {}
+
+        public static int sm(int x) { return x; }
+        public int m(int x) { return x; }
+        private static int psm(int x) { return x; }
+        private int pm(int x) { return x; }
+
+        private static void negLdcMethodHandleFromInner() {
+            // When we have nestmates, these will probably start succeeding,
+            // at which point we will need to find new negative tests for super-access.
+            assertIntrinsicFail(MHR_TESTINTF_PM_SPECIAL, () -> ldc(MHR_TESTINTF_PM_SPECIAL), IllegalAccessError.class);
+            assertIntrinsicFail(MHR_TESTINTF_PSM, () -> ldc(MHR_TESTINTF_PSM), IllegalAccessError.class);
+        }
+
+        private static void ldcMethodHandleFromInner() throws Throwable {
+            TestClass instance = (TestClass) ldc(MHR_TESTCLASS_CTOR).invokeExact();
+
+            assertEquals(-1, (int) ldc(MHR_TESTSUPER_M_SPECIAL).invokeExact(instance, 5));
+            assertEquals(0, (int) ldc(MHR_TESTINTF_M_SPECIAL).invokeExact(instance, 5));
+
+            assertEquals(5, (int) ldc(MHR_TESTCLASS_PM_SPECIAL).invokeExact(instance, 5));
+
+            assertEquals(5, (int) ldc(MHR_TESTCLASS_PSM).invokeExact(5));
+        }
+
+    }
+
+    private static int privateStaticMethod(int i) {
+        return i;
+    }
+
+    private int privateMethod(int i) {
+        return i;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/invoke/constant/MethodHandleRefTest.java	Wed Mar 07 16:34:02 2018 -0500
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2012, 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.
+ */
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandleInfo;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.WrongMethodTypeException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.lang.invoke.constant.ClassRef;
+import java.lang.invoke.constant.ConstantMethodHandleRef;
+import java.lang.invoke.constant.MethodHandleRef;
+import java.lang.invoke.constant.MethodTypeRef;
+import java.lang.invoke.constant.ConstantRefs;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Supplier;
+
+import org.testng.annotations.Test;
+
+import static java.lang.invoke.constant.MethodHandleRef.Kind.GETTER;
+import static java.lang.invoke.constant.MethodHandleRef.Kind.SETTER;
+import static java.lang.invoke.constant.MethodHandleRef.Kind.STATIC_GETTER;
+import static java.lang.invoke.constant.MethodHandleRef.Kind.STATIC_SETTER;
+import static java.lang.invoke.constant.ConstantRefs.CR_Integer;
+import static java.lang.invoke.constant.ConstantRefs.CR_List;
+import static java.lang.invoke.constant.ConstantRefs.CR_Object;
+import static java.lang.invoke.constant.ConstantRefs.CR_String;
+import static java.lang.invoke.constant.ConstantRefs.CR_int;
+import static java.lang.invoke.constant.ConstantRefs.CR_void;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+/**
+ * @test
+ * @run testng MethodHandleRefTest
+ * @summary unit tests for java.lang.invoke.constant.MethodHandleRefTest
+ */
+@Test
+public class MethodHandleRefTest extends SymbolicRefTest {
+    private static ClassRef thisClass = ClassRef.of("MethodHandleRefTest");
+    private static ClassRef testClass = thisClass.inner("TestClass");
+    private static ClassRef testInterface = thisClass.inner("TestInterface");
+    private static ClassRef testSuperclass = thisClass.inner("TestSuperclass");
+
+
+    private static void assertMHEquals(MethodHandle a, MethodHandle b) {
+        MethodHandleInfo ia = LOOKUP.revealDirect(a);
+        MethodHandleInfo ib = LOOKUP.revealDirect(b);
+        assertEquals(ia.getDeclaringClass(), ib.getDeclaringClass());
+        assertEquals(ia.getName(), ib.getName());
+        assertEquals(ia.getMethodType(), ib.getMethodType());
+        assertEquals(ia.getReferenceKind(), ib.getReferenceKind());
+    }
+
+    private void testMethodHandleRef(MethodHandleRef r) throws ReflectiveOperationException {
+        if (r instanceof ConstantMethodHandleRef) {
+            testSymbolicRef(r);
+
+            ConstantMethodHandleRef rr = (ConstantMethodHandleRef) r;
+            assertEquals(r, MethodHandleRef.of(rr.kind(), rr.owner(), rr.methodName(), r.methodType()));
+        }
+        else {
+            testSymbolicRefForwardOnly(r);
+        }
+    }
+
+    private void testMethodHandleRef(MethodHandleRef r, MethodHandle mh) throws ReflectiveOperationException {
+        testMethodHandleRef(r);
+
+        assertMHEquals(r.resolveConstantRef(LOOKUP), mh);
+        assertEquals(mh.toConstantRef(LOOKUP).orElseThrow(), r);
+
+        // compare extractable properties: refKind, owner, name, type
+        MethodHandleInfo mhi = LOOKUP.revealDirect(mh);
+        ConstantMethodHandleRef rr = (ConstantMethodHandleRef) r;
+        assertEquals(mhi.getDeclaringClass().toDescriptorString(), rr.owner().descriptorString());
+        assertEquals(mhi.getName(), rr.methodName());
+        assertEquals(mhi.getReferenceKind(), rr.kind().refKind);
+        assertEquals(mhi.getMethodType().toMethodDescriptorString(), r.methodType().descriptorString());
+    }
+
+    public void testSimpleMHs() throws ReflectiveOperationException {
+        testMethodHandleRef(MethodHandleRef.of(MethodHandleRef.Kind.VIRTUAL, CR_String, "isEmpty", "()Z"),
+                            LOOKUP.findVirtual(String.class, "isEmpty", MethodType.fromMethodDescriptorString("()Z", null)));
+        testMethodHandleRef(MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_String, "format", CR_String, CR_String, CR_Object.array()),
+                            LOOKUP.findStatic(String.class, "format", MethodType.methodType(String.class, String.class, Object[].class)));
+        testMethodHandleRef(MethodHandleRef.of(MethodHandleRef.Kind.INTERFACE_VIRTUAL, CR_List, "isEmpty", "()Z"),
+                            LOOKUP.findVirtual(List.class, "isEmpty", MethodType.fromMethodDescriptorString("()Z", null)));
+        testMethodHandleRef(MethodHandleRef.of(MethodHandleRef.Kind.CONSTRUCTOR, ClassRef.of("java.util.ArrayList"), "<init>", CR_void),
+                            LOOKUP.findConstructor(ArrayList.class, MethodType.methodType(void.class)));
+    }
+
+    public void testAsType() throws Throwable {
+        MethodHandleRef mhr = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, ClassRef.of("java.lang.Integer"), "valueOf",
+                                                 MethodTypeRef.of(CR_Integer, CR_int));
+            MethodHandleRef takesInteger = mhr.asType(MethodTypeRef.of(CR_Integer, CR_Integer));
+        testMethodHandleRef(takesInteger);
+        MethodHandle mh1 = takesInteger.resolveConstantRef(LOOKUP);
+        assertEquals((Integer) 3, (Integer) mh1.invokeExact((Integer) 3));
+
+        try {
+            Integer i = (Integer) mh1.invokeExact(3);
+            fail("Expected WMTE");
+        }
+        catch (WrongMethodTypeException ignored) { }
+
+        MethodHandleRef takesInt = takesInteger.asType(MethodTypeRef.of(CR_Integer, CR_int));
+        testMethodHandleRef(takesInt);
+        MethodHandle mh2 = takesInt.resolveConstantRef(LOOKUP);
+        assertEquals((Integer) 3, (Integer) mh2.invokeExact(3));
+
+        try {
+            Integer i = (Integer) mh2.invokeExact((Integer) 3);
+            fail("Expected WMTE");
+        }
+        catch (WrongMethodTypeException ignored) { }
+
+        // @@@ Test short-circuit optimization
+        // @@@ Test varargs adaptation
+        // @@@ Test bad adaptations and assert runtime error on resolution
+        // @@@ Test intrinsification of adapted MH
+    }
+
+    public void testMethodHandleRef() throws Throwable {
+        MethodHandleRef ctorRef = MethodHandleRef.of(MethodHandleRef.Kind.CONSTRUCTOR, testClass, "<ignored!>", CR_void);
+        MethodHandleRef staticMethodRef = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, testClass, "sm", "(I)I");
+        MethodHandleRef staticIMethodRef = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, testInterface, "sm", "(I)I");
+        MethodHandleRef instanceMethodRef = MethodHandleRef.of(MethodHandleRef.Kind.VIRTUAL, testClass, "m", "(I)I");
+        MethodHandleRef instanceIMethodRef = MethodHandleRef.of(MethodHandleRef.Kind.INTERFACE_VIRTUAL, testInterface, "m", "(I)I");
+        MethodHandleRef superMethodRef = MethodHandleRef.of(MethodHandleRef.Kind.SPECIAL, testSuperclass, "m", "(I)I");
+        MethodHandleRef superIMethodRef = MethodHandleRef.of(MethodHandleRef.Kind.SPECIAL, testInterface, "m", "(I)I");
+        MethodHandleRef privateMethodRef = MethodHandleRef.of(MethodHandleRef.Kind.SPECIAL, testClass, "pm", "(I)I");
+        MethodHandleRef privateIMethodRef = MethodHandleRef.of(MethodHandleRef.Kind.SPECIAL, testInterface, "pm", "(I)I");
+        MethodHandleRef privateStaticMethodRef = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, testClass, "psm", "(I)I");
+        MethodHandleRef privateStaticIMethodRef = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, testInterface, "psm", "(I)I");
+
+        for (MethodHandleRef r : List.of(ctorRef, staticMethodRef, staticIMethodRef, instanceMethodRef, instanceIMethodRef))
+            testMethodHandleRef(r);
+
+        TestClass instance = (TestClass) ctorRef.resolveConstantRef(LOOKUP).invokeExact();
+        TestClass instance2 = (TestClass) ctorRef.resolveConstantRef(TestClass.LOOKUP).invokeExact();
+        TestInterface instanceI = instance;
+
+        assertTrue(instance != instance2);
+
+        assertEquals(5, (int) staticMethodRef.resolveConstantRef(LOOKUP).invokeExact(5));
+        assertEquals(5, (int) staticMethodRef.resolveConstantRef(TestClass.LOOKUP).invokeExact(5));
+        assertEquals(0, (int) staticIMethodRef.resolveConstantRef(LOOKUP).invokeExact(5));
+        assertEquals(0, (int) staticIMethodRef.resolveConstantRef(TestClass.LOOKUP).invokeExact(5));
+
+        assertEquals(5, (int) instanceMethodRef.resolveConstantRef(LOOKUP).invokeExact(instance, 5));
+        assertEquals(5, (int) instanceMethodRef.resolveConstantRef(TestClass.LOOKUP).invokeExact(instance, 5));
+        assertEquals(5, (int) instanceIMethodRef.resolveConstantRef(LOOKUP).invokeExact(instanceI, 5));
+        assertEquals(5, (int) instanceIMethodRef.resolveConstantRef(TestClass.LOOKUP).invokeExact(instanceI, 5));
+
+        try { superMethodRef.resolveConstantRef(LOOKUP); fail(); }
+        catch (IllegalAccessException e) { /* expected */ }
+        assertEquals(-1, (int) superMethodRef.resolveConstantRef(TestClass.LOOKUP).invokeExact(instance, 5));
+
+        try { superIMethodRef.resolveConstantRef(LOOKUP); fail(); }
+        catch (IllegalAccessException e) { /* expected */ }
+        assertEquals(0, (int) superIMethodRef.resolveConstantRef(TestClass.LOOKUP).invokeExact(instance, 5));
+
+        try { privateMethodRef.resolveConstantRef(LOOKUP); fail(); }
+        catch (IllegalAccessException e) { /* expected */ }
+        assertEquals(5, (int) privateMethodRef.resolveConstantRef(TestClass.LOOKUP).invokeExact(instance, 5));
+
+        try { privateIMethodRef.resolveConstantRef(LOOKUP); fail(); }
+        catch (IllegalAccessException e) { /* expected */ }
+        try { privateIMethodRef.resolveConstantRef(TestClass.LOOKUP); fail(); }
+        catch (IllegalAccessException e) { /* expected */ }
+        assertEquals(0, (int) privateIMethodRef.resolveConstantRef(TestInterface.LOOKUP).invokeExact(instanceI, 5));
+
+        try { privateStaticMethodRef.resolveConstantRef(LOOKUP); fail(); }
+        catch (IllegalAccessException e) { /* expected */ }
+        assertEquals(5, (int) privateStaticMethodRef.resolveConstantRef(TestClass.LOOKUP).invokeExact(5));
+
+        try { privateStaticIMethodRef.resolveConstantRef(LOOKUP); fail(); }
+        catch (IllegalAccessException e) { /* expected */ }
+        try { privateStaticIMethodRef.resolveConstantRef(TestClass.LOOKUP); fail(); }
+        catch (IllegalAccessException e) { /* expected */ }
+        assertEquals(0, (int) privateStaticIMethodRef.resolveConstantRef(TestInterface.LOOKUP).invokeExact(5));
+
+        MethodHandleRef staticSetterRef = MethodHandleRef.ofField(STATIC_SETTER, testClass, "sf", CR_int);
+        MethodHandleRef staticGetterRef = MethodHandleRef.ofField(STATIC_GETTER, testClass, "sf", CR_int);
+        MethodHandleRef staticGetterIRef = MethodHandleRef.ofField(STATIC_GETTER, testInterface, "sf", CR_int);
+        MethodHandleRef setterRef = MethodHandleRef.ofField(SETTER, testClass, "f", CR_int);
+        MethodHandleRef getterRef = MethodHandleRef.ofField(GETTER, testClass, "f", CR_int);
+
+        for (MethodHandleRef r : List.of(staticSetterRef, staticGetterRef, staticGetterIRef, setterRef, getterRef))
+            testMethodHandleRef(r);
+
+        staticSetterRef.resolveConstantRef(LOOKUP).invokeExact(6); assertEquals(TestClass.sf, 6);
+        assertEquals(6, (int) staticGetterRef.resolveConstantRef(LOOKUP).invokeExact());
+        assertEquals(6, (int) staticGetterRef.resolveConstantRef(TestClass.LOOKUP).invokeExact());
+        staticSetterRef.resolveConstantRef(TestClass.LOOKUP).invokeExact(7); assertEquals(TestClass.sf, 7);
+        assertEquals(7, (int) staticGetterRef.resolveConstantRef(LOOKUP).invokeExact());
+        assertEquals(7, (int) staticGetterRef.resolveConstantRef(TestClass.LOOKUP).invokeExact());
+
+        assertEquals(3, (int) staticGetterIRef.resolveConstantRef(LOOKUP).invokeExact());
+        assertEquals(3, (int) staticGetterIRef.resolveConstantRef(TestClass.LOOKUP).invokeExact());
+
+        setterRef.resolveConstantRef(LOOKUP).invokeExact(instance, 6); assertEquals(instance.f, 6);
+        assertEquals(6, (int) getterRef.resolveConstantRef(LOOKUP).invokeExact(instance));
+        assertEquals(6, (int) getterRef.resolveConstantRef(TestClass.LOOKUP).invokeExact(instance));
+        setterRef.resolveConstantRef(TestClass.LOOKUP).invokeExact(instance, 7); assertEquals(instance.f, 7);
+        assertEquals(7, (int) getterRef.resolveConstantRef(LOOKUP).invokeExact(instance));
+        assertEquals(7, (int) getterRef.resolveConstantRef(TestClass.LOOKUP).invokeExact(instance));
+    }
+
+    private void assertBadArgs(Supplier<MethodHandleRef> supplier, String s) {
+        try {
+            MethodHandleRef r = supplier.get();
+            fail("Expected failure for " + s);
+        }
+        catch (IllegalArgumentException e) {
+            // succeed
+        }
+    }
+
+    public void testBadFieldMHs() {
+        List<String> badGetterDescs = List.of("()V", "(Ljava/lang/Object;)V", "(I)I", "(Ljava/lang/Object;I)I");
+        List<String> badStaticGetterDescs = List.of("()V", "(Ljava/lang/Object;)I", "(I)I", "(Ljava/lang/Object;I)I");
+        List<String> badSetterDescs = List.of("()V", "(I)V", "(Ljava/lang/Object;)V", "(Ljava/lang/Object;I)I", "(Ljava/lang/Object;II)V");
+        List<String> badStaticSetterDescs = List.of("()V", "(II)V", "()I");
+
+        badGetterDescs.forEach(s -> assertBadArgs(() -> MethodHandleRef.of(GETTER, thisClass, "x", s), s));
+        badSetterDescs.forEach(s -> assertBadArgs(() -> MethodHandleRef.of(SETTER, thisClass, "x", s), s));
+        badStaticGetterDescs.forEach(s -> assertBadArgs(() -> MethodHandleRef.of(STATIC_GETTER, thisClass, "x", s), s));
+        badStaticSetterDescs.forEach(s -> assertBadArgs(() -> MethodHandleRef.of(STATIC_SETTER, thisClass, "x", s), s));
+    }
+
+    public void testSymbolicRefsConstants() throws ReflectiveOperationException {
+        int tested = 0;
+        Field[] fields = ConstantRefs.class.getDeclaredFields();
+        for (Field f : fields) {
+            try {
+                if (f.getType().equals(MethodHandleRef.class)
+                    && ((f.getModifiers() & Modifier.STATIC) != 0)
+                    && ((f.getModifiers() & Modifier.PUBLIC) != 0)) {
+                    MethodHandleRef r = (MethodHandleRef) f.get(null);
+                    MethodHandle m = r.resolveConstantRef(MethodHandles.lookup());
+                    testMethodHandleRef(r, m);
+                    ++tested;
+                }
+            }
+            catch (Throwable e) {
+                fail("Error testing field " + f.getName(), e);
+            }
+        }
+
+        assertTrue(tested > 0);
+    }
+
+    private interface TestInterface {
+        public static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
+
+        public static final int sf = 3;
+
+        static int sm(int  x) { return 0; }
+        default int m(int x) { return 0; }
+        private int pm(int x) { return 0; }
+        private static int psm(int x) { return 0; }
+    }
+
+    private static class TestSuperclass {
+        public int m(int x) { return -1; }
+    }
+
+    private static class TestClass extends TestSuperclass implements TestInterface {
+        public static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
+
+        static int sf;
+        int f;
+
+        public TestClass()  {}
+
+        public static int sm(int x) { return x; }
+        public int m(int x) { return x; }
+        private static int psm(int x) { return x; }
+        private int pm(int x) { return x; }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/invoke/constant/MethodTypeRefTest.java	Wed Mar 07 16:34:02 2018 -0500
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2012, 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.
+ */
+
+import java.lang.invoke.MethodType;
+import java.lang.invoke.constant.ClassRef;
+import java.lang.invoke.constant.MethodTypeRef;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+import org.testng.annotations.Test;
+
+import static java.util.stream.Collectors.joining;
+import static java.util.stream.Collectors.toList;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+
+/**
+ * @test
+ * @run testng MethodTypeRefTest
+ * @summary unit tests for java.lang.invoke.constant.MethodTypeRef
+ */
+@Test
+public class MethodTypeRefTest extends SymbolicRefTest {
+
+    private void testMethodTypeRef(MethodTypeRef r) throws ReflectiveOperationException {
+        testSymbolicRef(r);
+
+        // Tests accessors (rType, pType, pCount, pList, pArray, descriptorString),
+        // factories (ofDescriptor, of), equals
+        assertEquals(r, MethodTypeRef.ofDescriptor(r.descriptorString()));
+        assertEquals(r, MethodTypeRef.of(r.returnType(), r.parameterArray()));
+        assertEquals(r, MethodTypeRef.of(r.returnType(), r.parameterList().toArray(new ClassRef[0])));
+        assertEquals(r, MethodTypeRef.of(r.returnType(), r.parameterList().stream().toArray(ClassRef[]::new)));
+        assertEquals(r, MethodTypeRef.of(r.returnType(), IntStream.range(0, r.parameterCount())
+                                                                  .mapToObj(r::parameterType)
+                                                                  .toArray(ClassRef[]::new)));
+    }
+
+    private void testMethodTypeRef(MethodTypeRef r, MethodType mt) throws ReflectiveOperationException {
+        testMethodTypeRef(r);
+
+        assertEquals(r.resolveConstantRef(LOOKUP), mt);
+        assertEquals(mt.toConstantRef(LOOKUP).get(), r);
+
+        assertEquals(r.descriptorString(), mt.toMethodDescriptorString());
+        assertEquals(r.parameterCount(), mt.parameterCount());
+        assertEquals(r.parameterList(), mt.parameterList().stream().map(SymbolicRefTest::classToRef).collect(toList()));
+        assertEquals(r.parameterArray(), Stream.of(mt.parameterArray()).map(SymbolicRefTest::classToRef).toArray(ClassRef[]::new));
+        for (int i=0; i<r.parameterCount(); i++)
+            assertEquals(r.parameterType(i), classToRef(mt.parameterType(i)));
+        assertEquals(r.returnType(), classToRef(mt.returnType()));
+    }
+
+    private void assertMethodType(ClassRef returnType,
+                                  ClassRef... paramTypes) throws ReflectiveOperationException {
+        String descriptor = Stream.of(paramTypes).map(ClassRef::descriptorString).collect(joining("", "(", ")"))
+                            + returnType.descriptorString();
+        MethodTypeRef mtRef = MethodTypeRef.of(returnType, paramTypes);
+
+        // MTRef accessors
+        assertEquals(descriptor, mtRef.descriptorString());
+        assertEquals(returnType, mtRef.returnType());
+        assertEquals(paramTypes, mtRef.parameterArray());
+        assertEquals(Arrays.asList(paramTypes), mtRef.parameterList());
+        assertEquals(paramTypes.length, mtRef.parameterCount());
+        for (int i=0; i<paramTypes.length; i++)
+            assertEquals(paramTypes[i], mtRef.parameterType(i));
+
+        // Consistency between MT and MTRef
+        MethodType mt = MethodType.fromMethodDescriptorString(descriptor, null);
+        testMethodTypeRef(mtRef, mt);
+
+        // changeReturnType
+        for (String r : returnDescs) {
+            ClassRef rc = ClassRef.ofDescriptor(r);
+            MethodTypeRef newRef = mtRef.changeReturnType(rc);
+            assertEquals(newRef, MethodTypeRef.of(rc, paramTypes));
+            testMethodTypeRef(newRef, mt.changeReturnType(rc.resolveConstantRef(LOOKUP)));
+        }
+
+        // changeParamType
+        for (int i=0; i<paramTypes.length; i++) {
+            for (String p : paramDescs) {
+                ClassRef pc = ClassRef.ofDescriptor(p);
+                ClassRef[] ps = paramTypes.clone();
+                ps[i] = pc;
+                MethodTypeRef newRef = mtRef.changeParameterType(i, pc);
+                assertEquals(newRef, MethodTypeRef.of(returnType, ps));
+                testMethodTypeRef(newRef, mt.changeParameterType(i, pc.resolveConstantRef(LOOKUP)));
+            }
+        }
+
+        // dropParamType
+        for (int i=0; i<paramTypes.length; i++) {
+            int k = i;
+            ClassRef[] ps = IntStream.range(0, paramTypes.length)
+                                     .filter(j -> j != k)
+                                     .mapToObj(j -> paramTypes[j])
+                                     .toArray(ClassRef[]::new);
+            MethodTypeRef newRef = mtRef.dropParameterTypes(i, i + 1);
+            assertEquals(newRef, MethodTypeRef.of(returnType, ps));
+            testMethodTypeRef(newRef, mt.dropParameterTypes(i, i+1));
+        }
+
+        // addParam
+        for (int i=0; i <= paramTypes.length; i++) {
+            for (ClassRef p : paramTypes) {
+                int k = i;
+                ClassRef[] ps = IntStream.range(0, paramTypes.length + 1)
+                                         .mapToObj(j -> (j < k) ? paramTypes[j] : (j == k) ? p : paramTypes[j-1])
+                                         .toArray(ClassRef[]::new);
+                MethodTypeRef newRef = mtRef.insertParameterTypes(i, p);
+                assertEquals(newRef, MethodTypeRef.of(returnType, ps));
+                testMethodTypeRef(newRef, mt.insertParameterTypes(i, p.resolveConstantRef(LOOKUP)));
+            }
+        }
+    }
+
+    public void testMethodTypeRef() throws ReflectiveOperationException {
+        for (String r : returnDescs) {
+            assertMethodType(ClassRef.ofDescriptor(r));
+            for (String p1 : paramDescs) {
+                assertMethodType(ClassRef.ofDescriptor(r), ClassRef.ofDescriptor(p1));
+                for (String p2 : paramDescs) {
+                    assertMethodType(ClassRef.ofDescriptor(r), ClassRef.ofDescriptor(p1), ClassRef.ofDescriptor(p2));
+                }
+            }
+        }
+    }
+
+    public void testBadMethodTypeRefs() {
+        List<String> badDescriptors = List.of("()II", "()I;", "(I;)", "(I)", "()L", "(V)V",
+                                              "(java.lang.String)V", "()[]", "(Ljava/lang/String)V",
+                                              "(Ljava.lang.String;)V", "(java/lang/String)V");
+
+        for (String d : badDescriptors) {
+            try {
+                MethodTypeRef r = MethodTypeRef.ofDescriptor(d);
+                fail(d);
+            }
+            catch (IllegalArgumentException e) {
+                // good
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/invoke/constant/SymbolicRefTest.java	Wed Mar 07 16:34:02 2018 -0500
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2012, 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.
+ */
+
+import java.lang.Class;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.constant.ClassRef;
+import java.lang.invoke.constant.Constable;
+import java.lang.invoke.constant.ConstantRef;
+import java.lang.invoke.constant.ConstantRefs;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import static org.testng.Assert.assertEquals;
+
+/**
+ * Base class for XxxRef tests
+ */
+public abstract class SymbolicRefTest {
+
+    public static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
+
+    static List<String> someRefs = List.of("Ljava/lang/String;", "Ljava/util/List;");
+    static String[] basicDescs = Stream.concat(Stream.of(Primitives.values())
+                                                     .filter(p -> p != Primitives.VOID)
+                                                     .map(p -> p.descriptor),
+                                               someRefs.stream())
+                                       .toArray(String[]::new);
+    static String[] paramDescs = Stream.of(basicDescs)
+                                       .flatMap(d -> Stream.of(d, "[" + d))
+                                       .toArray(String[]::new);
+    static String[] returnDescs = Stream.concat(Stream.of(paramDescs), Stream.of("V")).toArray(String[]::new);
+
+    enum Primitives {
+        INT("I", "int", int.class, int[].class, ConstantRefs.CR_int),
+        LONG("J", "long", long.class, long[].class, ConstantRefs.CR_long),
+        SHORT("S", "short", short.class, short[].class, ConstantRefs.CR_short),
+        BYTE("B", "byte", byte.class, byte[].class, ConstantRefs.CR_byte),
+        CHAR("C", "char", char.class, char[].class, ConstantRefs.CR_char),
+        FLOAT("F", "float", float.class, float[].class, ConstantRefs.CR_float),
+        DOUBLE("D", "double", double.class, double[].class, ConstantRefs.CR_double),
+        BOOLEAN("Z", "boolean", boolean.class, boolean[].class, ConstantRefs.CR_boolean),
+        VOID("V", "void", void.class, null, ConstantRefs.CR_void);
+
+        public final String descriptor;
+        public final String name;
+        public final Class<?> clazz;
+        public final Class<?> arrayClass;
+        public final ClassRef classRef;
+
+        Primitives(String descriptor, String name, Class<?> clazz, Class<?> arrayClass, ClassRef ref) {
+            this.descriptor = descriptor;
+            this.name = name;
+            this.clazz = clazz;
+            this.arrayClass = arrayClass;
+            classRef = ref;
+        }
+    }
+
+    static String classToDescriptor(Class<?> clazz) {
+        return MethodType.methodType(clazz).toMethodDescriptorString().substring(2);
+    }
+
+    static ClassRef classToRef(Class<?> c) {
+        return ClassRef.ofDescriptor(c.toDescriptorString());
+    }
+
+    static<T> void testSymbolicRef(ConstantRef<T> ref) throws ReflectiveOperationException {
+        testSymbolicRef(ref, false);
+    }
+
+    static<T> void testSymbolicRefForwardOnly(ConstantRef<T> ref) throws ReflectiveOperationException {
+        testSymbolicRef(ref, true);
+    }
+
+    private static<T> void testSymbolicRef(ConstantRef<T> ref, boolean forwardOnly) throws ReflectiveOperationException {
+        if (!forwardOnly) {
+            // Round trip sym -> resolve -> toSymbolicRef
+            ConstantRef<? super ConstantRef<T>> s = ((Constable<ConstantRef<T>>) ref.resolveConstantRef(LOOKUP)).toConstantRef(LOOKUP).orElseThrow();
+            assertEquals(ref, s);
+        }
+
+        // Round trip sym -> quoted sym -> resolve
+        Optional<ConstantRef<ConstantRef<T>>> opt = (Optional<ConstantRef<ConstantRef<T>>>) ((Constable) ref).toConstantRef(LOOKUP);
+        ConstantRef<T> sr = opt.orElseThrow().resolveConstantRef(LOOKUP);
+        assertEquals(sr, ref);
+    }
+}
--- a/test/jdk/java/lang/sym/ClassRefTest.java	Wed Mar 07 14:59:03 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,211 +0,0 @@
-/*
- * Copyright (c) 2012, 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.
- */
-
-import java.lang.invoke.MethodHandles;
-import java.lang.reflect.Array;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.lang.sym.ClassRef;
-import java.lang.sym.ConstantRefs;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-
-import org.testng.annotations.Test;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertNotEquals;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
-
-/**
- * @test
- * @run testng ClassRefTest
- * @summary unit tests for java.lang.sym.ClassRef
- */
-@Test
-public class ClassRefTest extends SymbolicRefTest {
-
-    private void testClassRef(ClassRef r) throws ReflectiveOperationException {
-        testSymbolicRef(r);
-
-        // Test descriptor accessor, factory, equals
-        assertEquals(r, ClassRef.ofDescriptor(r.descriptorString()));
-
-        if (!r.descriptorString().equals("V")) {
-            assertEquals(r, r.array().componentType());
-            // Commutativity: array -> resolve -> componentType -> toSymbolic
-            assertEquals(r, r.array().resolveConstantRef(LOOKUP).getComponentType().toConstantRef(LOOKUP).orElseThrow());
-            // Commutativity: resolve -> array -> toSymbolic -> component type
-            assertEquals(r, Array.newInstance(r.resolveConstantRef(LOOKUP), 0).getClass().toConstantRef(LOOKUP).orElseThrow().componentType());
-        }
-
-        if (r.isArray()) {
-            assertEquals(r, r.componentType().array());
-            assertEquals(r, r.resolveConstantRef(LOOKUP).getComponentType().toConstantRef(LOOKUP).orElseThrow().array());
-            assertEquals(r, Array.newInstance(r.componentType().resolveConstantRef(LOOKUP), 0).getClass().toConstantRef(LOOKUP).orElseThrow());
-        }
-    }
-
-    private void testClassRef(ClassRef r, Class<?> c) throws ReflectiveOperationException {
-        testClassRef(r);
-
-        assertEquals(r.resolveConstantRef(LOOKUP), c);
-        assertEquals(c.toConstantRef(LOOKUP).orElseThrow(), r);
-        assertEquals(ClassRef.ofDescriptor(c.toDescriptorString()), r);
-    }
-
-    public void testSymbolicRefsConstants() throws ReflectiveOperationException {
-        int tested = 0;
-        Field[] fields = ConstantRefs.class.getDeclaredFields();
-        for (Field f : fields) {
-            try {
-                if (f.getType().equals(ClassRef.class)
-                    && ((f.getModifiers() & Modifier.STATIC) != 0)
-                    && ((f.getModifiers() & Modifier.PUBLIC) != 0)) {
-                    ClassRef cr = (ClassRef) f.get(null);
-                    Class c = cr.resolveConstantRef(MethodHandles.lookup());
-                    testClassRef(cr, c);
-                    ++tested;
-                }
-            }
-            catch (Throwable e) {
-                fail("Error testing field " + f.getName(), e);
-            }
-        }
-
-        assertTrue(tested > 0);
-    }
-
-    public void testPrimitiveClassRef() throws ReflectiveOperationException {
-        for (Primitives p : Primitives.values()) {
-            List<ClassRef> refs = List.of(ClassRef.ofDescriptor(p.descriptor),
-                                          p.classRef,
-                                          (ClassRef) p.clazz.toConstantRef().orElseThrow());
-            for (ClassRef c : refs) {
-                testClassRef(c, p.clazz);
-                assertTrue(c.isPrimitive());
-                assertEquals(p.descriptor, c.descriptorString());
-                assertEquals(p.name, c.simpleName());
-                refs.forEach(cc -> assertEquals(c, cc));
-                if (p != Primitives.VOID) {
-                    testClassRef(c.array(), p.arrayClass);
-                    assertEquals(c, ((ClassRef) p.arrayClass.toConstantRef().orElseThrow()).componentType());
-                    assertEquals(c, p.classRef.array().componentType());
-                }
-            }
-
-            for (Primitives other : Primitives.values()) {
-                ClassRef otherDescr = ClassRef.ofDescriptor(other.descriptor);
-                if (p != other)
-                    refs.forEach(c -> assertNotEquals(c, otherDescr));
-                else
-                    refs.forEach(c -> assertEquals(c, otherDescr));
-            }
-        }
-    }
-
-    public void testSimpleClassRef() throws ReflectiveOperationException {
-
-        List<ClassRef> stringClassRefs = Arrays.asList(ClassRef.ofDescriptor("Ljava/lang/String;"),
-                                                       ClassRef.of("java.lang", "String"),
-                                                       ClassRef.of("java.lang.String"),
-                                                       ClassRef.of("java.lang.String").array().componentType(),
-                                                       String.class.toConstantRef(LOOKUP).orElseThrow());
-        for (ClassRef r : stringClassRefs) {
-            testClassRef(r, String.class);
-            assertFalse(r.isPrimitive());
-            assertEquals("Ljava/lang/String;", r.descriptorString());
-            assertEquals("String", r.simpleName());
-            assertEquals(r.array().resolveConstantRef(LOOKUP), String[].class);
-            stringClassRefs.forEach(rr -> assertEquals(r, rr));
-        }
-
-        testClassRef(ClassRef.of("java.lang.String").array(), String[].class);
-        testClassRef(ClassRef.of("java.util.Map").inner("Entry"), Map.Entry.class);
-
-        ClassRef thisClassRef = ClassRef.ofDescriptor("LClassRefTest;");
-        assertEquals(thisClassRef, ClassRef.of("", "ClassRefTest"));
-        assertEquals(thisClassRef, ClassRef.of("ClassRefTest"));
-        assertEquals(thisClassRef.simpleName(), "ClassRefTest");
-        testClassRef(thisClassRef, ClassRefTest.class);
-    }
-
-    public void testArrayClassRef() throws ReflectiveOperationException {
-        for (String d : basicDescs) {
-            ClassRef a0 = ClassRef.ofDescriptor(d);
-            ClassRef a1 = a0.array();
-            ClassRef a2 = a1.array();
-
-            testClassRef(a0);
-            testClassRef(a1);
-            testClassRef(a2);
-            assertFalse(a0.isArray());
-            assertTrue(a1.isArray());
-            assertTrue(a2.isArray());
-            assertFalse(a1.isPrimitive());
-            assertFalse(a2.isPrimitive());
-            assertEquals(a0.descriptorString(), d);
-            assertEquals(a1.descriptorString(), "[" + a0.descriptorString());
-            assertEquals(a2.descriptorString(), "[[" + a0.descriptorString());
-
-            try {
-                assertEquals(a0, a0.componentType());
-                fail("Didn't throw ISE");
-            }
-            catch (IllegalStateException expected) {
-                // succeed
-            }
-            assertEquals(a0, a1.componentType());
-            assertEquals(a1, a2.componentType());
-
-            assertNotEquals(a0, a1);
-            assertNotEquals(a1, a2);
-
-            assertEquals(a1, ClassRef.ofDescriptor("[" + d));
-            assertEquals(a2, ClassRef.ofDescriptor("[[" + d));
-            assertEquals(classToDescriptor(a0.resolveConstantRef(LOOKUP)), a0.descriptorString());
-            assertEquals(classToDescriptor(a1.resolveConstantRef(LOOKUP)), a1.descriptorString());
-            assertEquals(classToDescriptor(a2.resolveConstantRef(LOOKUP)), a2.descriptorString());
-        }
-    }
-
-    public void testBadClassRefs() {
-        List<String> badDescriptors = List.of("II", "I;", "Q", "L",
-                                              "java.lang.String", "[]", "Ljava/lang/String",
-                                              "Ljava.lang.String;", "java/lang/String");
-
-        for (String d : badDescriptors) {
-            try {
-                ClassRef constant = ClassRef.ofDescriptor(d);
-                fail(d);
-            }
-            catch (IllegalArgumentException e) {
-                // good
-            }
-        }
-    }
-}
--- a/test/jdk/java/lang/sym/CondyRefTest.java	Wed Mar 07 14:59:03 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,213 +0,0 @@
-/*
- * Copyright (c) 2012, 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.
- */
-
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.VarHandle;
-import java.lang.sym.ClassRef;
-import java.lang.sym.ConstantRef;
-import java.lang.sym.DynamicConstantRef;
-import java.lang.sym.EnumRef;
-import java.lang.sym.MethodHandleRef;
-import java.lang.sym.ConstantRefs;
-import java.lang.sym.VarHandleRef;
-
-import org.testng.annotations.Test;
-
-import static java.lang.sym.ConstantRefs.CR_MethodHandle;
-import static java.lang.sym.ConstantRefs.CR_Object;
-import static java.lang.sym.ConstantRefs.CR_String;
-import static java.lang.sym.ConstantRefs.CR_VarHandle;
-import static java.lang.sym.ConstantRefs.CR_int;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertNotEquals;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.assertTrue;
-
-/**
- * @test
- * @run testng CondyRefTest
- * @summary unit tests for java.lang.sym.CondyRefTest
- */
-@Test
-public class CondyRefTest extends SymbolicRefTest {
-    private final static ConstantRef<?>[] EMPTY_ARGS = new ConstantRef<?>[0];
-    private final static ClassRef CR_ConstantBootstraps = ClassRef.of("java.lang.invoke.ConstantBootstraps");
-
-    private static<T> void testDCR(DynamicConstantRef<T> r, T c) throws ReflectiveOperationException {
-        assertEquals(r, DynamicConstantRef.of(r.bootstrapMethod(), r.constantName(), r.constantType(), r.bootstrapArgs()));
-        assertEquals(r.resolveConstantRef(LOOKUP), c);
-    }
-
-    private void testVarHandleRef(DynamicConstantRef<VarHandle> r, VarHandle vh) throws ReflectiveOperationException  {
-        testSymbolicRef(r);
-        assertEquals(r.resolveConstantRef(LOOKUP), vh);
-        assertEquals(vh.toConstantRef(LOOKUP).orElseThrow(), r);
-    }
-
-    private static<E extends Enum<E>> void testEnumRef(EnumRef<E> r, E e) throws ReflectiveOperationException {
-        testSymbolicRef(r);
-
-        assertEquals(r, EnumRef.of(r.constantType(), r.constantName()));
-        assertEquals(r.resolveConstantRef(LOOKUP), e);
-    }
-
-    public void testNullConstant() throws ReflectiveOperationException {
-        DynamicConstantRef<?> r = (DynamicConstantRef<?>) ConstantRefs.NULL;
-        assertEquals(r, DynamicConstantRef.of(r.bootstrapMethod(), r.constantName(), r.constantType(), r.bootstrapArgs()));
-        assertNull(r.resolveConstantRef(LOOKUP));
-    }
-
-    static String concatBSM(MethodHandles.Lookup lookup, String name, Class<?> type, String a, String b) {
-        return a + b;
-    }
-
-    public void testDynamicConstant() throws ReflectiveOperationException {
-        MethodHandleRef bsmRef = MethodHandleRef.ofDynamicConstant(ClassRef.of("CondyRefTest"), "concatBSM",
-                                                                   CR_String, CR_String, CR_String);
-        DynamicConstantRef<String> r = DynamicConstantRef.<String>of(bsmRef).withArgs("foo", "bar");
-        testDCR(r, "foobar");
-    }
-
-    public void testNested() throws Throwable {
-        MethodHandleRef invoker = MethodHandleRef.ofDynamicConstant(CR_ConstantBootstraps, "invoke", CR_Object, CR_MethodHandle, CR_Object.array());
-        MethodHandleRef format = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_String, "format", CR_String, CR_String, CR_Object.array());
-
-        String s = (String) invoker.resolveConstantRef(LOOKUP)
-                                   .invoke(LOOKUP, "", String.class,
-                                           format.resolveConstantRef(LOOKUP), "%s%s", "moo", "cow");
-        assertEquals(s, "moocow");
-
-        DynamicConstantRef<String> ref = DynamicConstantRef.<String>of(invoker).withArgs(format, "%s%s", "moo", "cow");
-        testDCR(ref, "moocow");
-
-        DynamicConstantRef<String> ref2 = DynamicConstantRef.<String>of(invoker).withArgs(format, "%s%s", ref, "cow");
-        testDCR(ref2, "moocowcow");
-    }
-
-    enum MyEnum { A, B, C }
-
-    public void testEnumRef() throws ReflectiveOperationException {
-        ClassRef enumClass = ClassRef.of("CondyRefTest").inner("MyEnum");
-
-        testEnumRef(EnumRef.of(enumClass, "A"), MyEnum.A);
-        testEnumRef(EnumRef.of(enumClass, "B"), MyEnum.B);
-        testEnumRef(EnumRef.of(enumClass, "C"), MyEnum.C);
-    }
-
-    static class MyClass {
-        static int sf;
-        int f;
-    }
-
-    public void testVarHandles() throws ReflectiveOperationException {
-        ClassRef testClass = ClassRef.of("CondyRefTest").inner("MyClass");
-        MyClass instance = new MyClass();
-
-        // static varHandle
-        VarHandleRef vhc = VarHandleRef.ofStaticField(testClass, "sf", CR_int);
-        VarHandle varHandle = LOOKUP.findStaticVarHandle(MyClass.class, "sf", int.class);
-        testVarHandleRef(vhc, varHandle);
-
-        assertEquals(varHandle.varType(), int.class);
-        varHandle.set(8);
-        assertEquals(8, (int) varHandle.get());
-        assertEquals(MyClass.sf, 8);
-
-        // static varHandle
-        vhc = VarHandleRef.ofField(testClass, "f", CR_int);
-        varHandle = LOOKUP.findVarHandle(MyClass.class, "f", int.class);
-        testVarHandleRef(vhc, varHandle);
-
-        assertEquals(varHandle.varType(), int.class);
-        varHandle.set(instance, 9);
-        assertEquals(9, (int) varHandle.get(instance));
-        assertEquals(instance.f, 9);
-
-        vhc = VarHandleRef.ofArray(CR_int.array());
-        varHandle = MethodHandles.arrayElementVarHandle(int[].class);
-        testVarHandleRef(vhc, varHandle);
-
-        int[] ints = new int[3];
-        varHandle.set(ints, 0, 1);
-        varHandle.set(ints, 1, 2);
-        varHandle.set(ints, 2, 3);
-
-        assertEquals(1, varHandle.get(ints, 0));
-        assertEquals(2, varHandle.get(ints, 1));
-        assertEquals(3, varHandle.get(ints, 2));
-        assertEquals(1, ints[0]);
-        assertEquals(2, ints[1]);
-        assertEquals(3, ints[2]);
-    }
-
-    private<T> void assertLifted(ConstantRef<T> prototype,
-                                 DynamicConstantRef<T> nonCanonical,
-                                 ConstantRef<T> canonical) {
-        Class<?> clazz = prototype.getClass();
-
-        assertTrue(canonical != nonCanonical);
-        assertTrue(clazz.isAssignableFrom(canonical.getClass()));
-        assertFalse(clazz.isAssignableFrom(nonCanonical.getClass()));
-        assertTrue(prototype.equals(canonical));
-        assertTrue(canonical.equals(prototype));
-        if (prototype instanceof DynamicConstantRef) {
-            assertTrue(canonical.equals(nonCanonical));
-            assertTrue(nonCanonical.equals(canonical));
-            assertTrue(prototype.equals(nonCanonical));
-            assertTrue(nonCanonical.equals(prototype));
-        }
-    }
-
-    public void testLifting() {
-        DynamicConstantRef<Object> unliftedNull = DynamicConstantRef.of(ConstantRefs.BSM_NULL_CONSTANT, "_", CR_Object, EMPTY_ARGS);
-        assertEquals(ConstantRefs.NULL, unliftedNull);
-        assertTrue(ConstantRefs.NULL != unliftedNull);
-        assertTrue(ConstantRefs.NULL == DynamicConstantRef.ofCanonical(ConstantRefs.BSM_NULL_CONSTANT, "_", CR_Object, EMPTY_ARGS));
-        assertTrue(ConstantRefs.NULL == DynamicConstantRef.ofCanonical(ConstantRefs.BSM_NULL_CONSTANT, "_", CR_String, EMPTY_ARGS));
-        assertTrue(ConstantRefs.NULL == DynamicConstantRef.ofCanonical(ConstantRefs.BSM_NULL_CONSTANT, "wahoo", CR_Object, EMPTY_ARGS));
-
-        assertLifted(CR_int,
-                     DynamicConstantRef.of(ConstantRefs.BSM_PRIMITIVE_CLASS, "I", ConstantRefs.CR_Class, EMPTY_ARGS),
-                     DynamicConstantRef.ofCanonical(ConstantRefs.BSM_PRIMITIVE_CLASS, "I", ConstantRefs.CR_Class, EMPTY_ARGS));
-
-        ClassRef enumClass = ClassRef.of("CondyRefTest").inner("MyEnum");
-        assertLifted(EnumRef.of(enumClass, "A"),
-                     DynamicConstantRef.of(ConstantRefs.BSM_ENUM_CONSTANT, "A", enumClass, EMPTY_ARGS),
-                     DynamicConstantRef.<MyEnum>ofCanonical(ConstantRefs.BSM_ENUM_CONSTANT, "A", enumClass, EMPTY_ARGS));
-
-        ClassRef testClass = ClassRef.of("CondyRefTest").inner("MyClass");
-        assertLifted(VarHandleRef.ofStaticField(testClass, "sf", CR_int),
-                     DynamicConstantRef.of(ConstantRefs.BSM_VARHANDLE_STATIC_FIELD, "sf", CR_VarHandle, new ConstantRef<?>[] {testClass, "sf", CR_int }),
-                     DynamicConstantRef.ofCanonical(ConstantRefs.BSM_VARHANDLE_STATIC_FIELD, "sf", CR_VarHandle, new ConstantRef<?>[] {testClass, "sf", CR_int }));
-        assertLifted(VarHandleRef.ofField(testClass, "f", CR_int),
-                     DynamicConstantRef.of(ConstantRefs.BSM_VARHANDLE_FIELD, "f", CR_VarHandle, new ConstantRef<?>[] {testClass, "f", CR_int }),
-                     DynamicConstantRef.ofCanonical(ConstantRefs.BSM_VARHANDLE_FIELD, "f", CR_VarHandle, new ConstantRef<?>[] {testClass, "f", CR_int }));
-        assertLifted(VarHandleRef.ofArray(CR_int.array()),
-                     DynamicConstantRef.of(ConstantRefs.BSM_VARHANDLE_ARRAY, "_", CR_VarHandle, new ConstantRef<?>[] {CR_int.array() }),
-                     DynamicConstantRef.ofCanonical(ConstantRefs.BSM_VARHANDLE_ARRAY, "_", CR_VarHandle, new ConstantRef<?>[] {CR_int.array() }));
-    }
-
-}
--- a/test/jdk/java/lang/sym/IndyRefTest.java	Wed Mar 07 14:59:03 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2012, 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.
- */
-
-import org.testng.annotations.Test;
-
-/**
- * IndyRefTest
- *
- * @author Brian Goetz
- */
-@Test
-public class IndyRefTest {
-    // @@@ non-intrinsified: get dynamic invoker, and invoke
-    // test toSymRef and back
-    // test canonicalization; StringConcat?
-    // @@@ intrinsified tests too
-}
--- a/test/jdk/java/lang/sym/IntrinsifiedRefTest.java	Wed Mar 07 14:59:03 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,364 +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.
- */
-
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-import java.lang.sym.ClassRef;
-import java.lang.sym.Constable;
-import java.lang.sym.ConstantRef;
-import java.lang.sym.EnumRef;
-import java.lang.sym.MethodHandleRef;
-import java.lang.sym.MethodTypeRef;
-import java.lang.sym.ConstantRefs;
-import java.util.function.Supplier;
-
-import org.testng.annotations.Test;
-
-import static java.lang.invoke.Intrinsics.ldc;
-import static java.lang.sym.MethodHandleRef.Kind.GETTER;
-import static java.lang.sym.MethodHandleRef.Kind.SETTER;
-import static java.lang.sym.MethodHandleRef.Kind.STATIC_GETTER;
-import static java.lang.sym.MethodHandleRef.Kind.STATIC_SETTER;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.fail;
-
-/**
- * @test
- * @compile -XDdoConstantFold IntrinsifiedRefTest.java
- * @run testng IntrinsifiedRefTest
- * @summary Integration test for intrinsification of XxxRef
- */
-@Test
-public class IntrinsifiedRefTest {
-    public static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
-
-    private static final ClassRef CR_THIS = ClassRef.of("IntrinsifiedRefTest");
-    private static final ClassRef CR_TESTCLASS = CR_THIS.inner("TestClass");
-    private static final ClassRef CR_TESTINTF = CR_THIS.inner("TestInterface");
-    private static final ClassRef CR_TESTSUPERCLASS = CR_THIS.inner("TestSuperclass");
-    private static final ClassRef CR_TESTENUM = CR_THIS.inner("TestEnum");
-    private static final String NONEXISTENT_CLASS = "foo.Bar";
-    private static final String INACCESSIBLE_CLASS = "java.lang.invoke.DirectMethodHandle";
-
-    private static final MethodHandleRef MHR_TESTCLASS_CTOR = MethodHandleRef.of(MethodHandleRef.Kind.CONSTRUCTOR, CR_TESTCLASS, "<ignored!>", MethodTypeRef.ofDescriptor("()V"));
-    private static final MethodHandleRef MHR_TESTCLASS_SM = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_TESTCLASS, "sm", "(I)I");
-    private static final MethodHandleRef MHR_TESTINTF_SM = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_TESTINTF, "sm", "(I)I");
-    private static final MethodHandleRef MHR_TESTCLASS_M = MethodHandleRef.of(MethodHandleRef.Kind.VIRTUAL, CR_TESTCLASS, "m", MethodTypeRef.ofDescriptor("(I)I"));
-    private static final MethodHandleRef MHR_TESTINTF_M = MethodHandleRef.of(MethodHandleRef.Kind.INTERFACE_VIRTUAL, CR_TESTINTF, "m", MethodTypeRef.ofDescriptor("(I)I"));
-    private static final MethodHandleRef MHR_TESTCLASS_PM_SPECIAL = MethodHandleRef.of(MethodHandleRef.Kind.SPECIAL, CR_TESTCLASS, "pm", MethodTypeRef.ofDescriptor("(I)I"));
-    private static final MethodHandleRef MHR_TESTINTF_PM_SPECIAL = MethodHandleRef.of(MethodHandleRef.Kind.SPECIAL, CR_TESTINTF, "pm", MethodTypeRef.ofDescriptor("(I)I"));
-    private static final MethodHandleRef MHR_TESTCLASS_PSM = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_TESTCLASS, "psm", MethodTypeRef.ofDescriptor("(I)I"));
-    private static final MethodHandleRef MHR_TESTINTF_PSM = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_TESTINTF, "psm", MethodTypeRef.ofDescriptor("(I)I"));
-    private static final MethodHandleRef MHR_TESTSUPER_M_SPECIAL = MethodHandleRef.of(MethodHandleRef.Kind.SPECIAL, CR_TESTSUPERCLASS, "m", "(I)I");
-    private static final MethodHandleRef MHR_TESTINTF_M_SPECIAL = MethodHandleRef.of(MethodHandleRef.Kind.SPECIAL, CR_TESTINTF, "m", "(I)I");
-    private static final MethodHandleRef MHR_TESTCLASS_SF_SETTER = MethodHandleRef.ofField(STATIC_SETTER, CR_TESTCLASS, "sf", ConstantRefs.CR_int);
-    private static final MethodHandleRef MHR_TESTCLASS_SF_GETTER = MethodHandleRef.ofField(STATIC_GETTER, CR_TESTCLASS, "sf", ConstantRefs.CR_int);
-    private static final MethodHandleRef MHR_TESTINTF_SF_GETTER = MethodHandleRef.ofField(STATIC_GETTER, CR_TESTINTF, "sf", ConstantRefs.CR_int);
-    private static final MethodHandleRef MHR_TESTCLASS_F_SETTER = MethodHandleRef.ofField(SETTER, CR_TESTCLASS, "f", ConstantRefs.CR_int);
-    private static final MethodHandleRef MHR_TESTCLASS_F_GETTER = MethodHandleRef.ofField(GETTER, CR_TESTCLASS, "f", ConstantRefs.CR_int);
-
-
-
-    private static <T extends Constable> void assertIntrinsic(ConstantRef<T> ref, T intrinsified, T target) throws ReflectiveOperationException {
-        assertEquals(target, intrinsified);
-        assertEquals(ref.resolveConstantRef(LOOKUP), intrinsified);
-        assertEquals(intrinsified.toConstantRef(LOOKUP).orElseThrow(), ref);
-    }
-
-    private static<T extends Constable> void assertIntrinsicFail(ConstantRef<T> ref, Supplier<T> supplier, Class<? extends Throwable> exception) {
-        try {
-            T t = supplier.get();
-            fail("Expected failure resolving " + ref);
-        } catch (Throwable e) {
-            if (exception.isAssignableFrom(e.getClass()))
-                return;
-            else if (e instanceof BootstrapMethodError) {
-                Throwable cause = e.getCause();
-                if (cause != null && exception.isAssignableFrom(cause.getClass()))
-                    return;
-            }
-            fail(String.format("Expected %s, found %s for %s", exception, e.getClass(), ref));
-        }
-    }
-
-    public void testLdcClass() throws ReflectiveOperationException {
-        ClassRef cr1 = ClassRef.ofDescriptor("Ljava/lang/String;");
-        ClassRef cr2 = ClassRef.of("java.lang.String");
-        ClassRef cr3 = ClassRef.of("java.lang", "String");
-
-        assertIntrinsic(cr1, ldc(cr1), String.class);
-        assertIntrinsic(cr2, ldc(cr2), String.class);
-        assertIntrinsic(cr3, ldc(cr3), String.class);
-
-        ClassRef cr4 = ClassRef.ofDescriptor("[Ljava/lang/String;");
-        ClassRef cr5 = cr2.array();
-        assertIntrinsic(cr4, ldc(cr4), String[].class);
-        assertIntrinsic(cr5, ldc(cr5), String[].class);
-
-        ClassRef cr6 = ClassRef.ofDescriptor("I");
-        assertIntrinsic(cr6, ldc(cr6), int.class);
-        assertIntrinsic(ConstantRefs.CR_int, ldc(ConstantRefs.CR_int), int.class);
-
-        ClassRef cr7 = ClassRef.ofDescriptor("[I");
-        ClassRef cr8 = ConstantRefs.CR_int.array();
-        assertIntrinsic(cr7, ldc(cr7), int[].class);
-        assertIntrinsic(cr8, ldc(cr8), int[].class);
-    }
-
-    public void negLdcClass() {
-        ClassRef cr = ClassRef.of(NONEXISTENT_CLASS);
-        assertIntrinsicFail(cr, () -> ldc(cr), NoClassDefFoundError.class);
-
-        ClassRef cr2 = ClassRef.of(INACCESSIBLE_CLASS);
-        assertIntrinsicFail(cr2, () -> ldc(cr2), IllegalAccessError.class);
-    }
-
-    public void testLdcMethodType() throws ReflectiveOperationException {
-        MethodTypeRef mtr1 = MethodTypeRef.ofDescriptor("()V");
-        MethodTypeRef mtr2 = MethodTypeRef.of(ConstantRefs.CR_void);
-        assertIntrinsic(mtr1, ldc(mtr1), MethodType.methodType(void.class));
-        assertIntrinsic(mtr2, ldc(mtr2), MethodType.methodType(void.class));
-
-        MethodTypeRef mtr3 = MethodTypeRef.ofDescriptor("(I)I");
-        MethodTypeRef mtr4 = MethodTypeRef.of(ConstantRefs.CR_int, ConstantRefs.CR_int);
-        assertIntrinsic(mtr3, ldc(mtr3), MethodType.methodType(int.class, int.class));
-        assertIntrinsic(mtr4, ldc(mtr4), MethodType.methodType(int.class, int.class));
-
-        MethodTypeRef mtr5 = MethodTypeRef.ofDescriptor("(Ljava/lang/String;)Ljava/lang/String;");
-        MethodTypeRef mtr6 = MethodTypeRef.of(ConstantRefs.CR_String, ConstantRefs.CR_String);
-        assertIntrinsic(mtr5, ldc(mtr5), MethodType.methodType(String.class, String.class));
-        assertIntrinsic(mtr6, ldc(mtr6), MethodType.methodType(String.class, String.class));
-
-        MethodTypeRef mtr7 = MethodTypeRef.ofDescriptor("([I)[Ljava/lang/String;");
-        assertIntrinsic(mtr7, ldc(mtr7), MethodType.methodType(String[].class, int[].class));
-    }
-
-    public void negLdcMethodType() {
-        MethodTypeRef mtr1 = MethodTypeRef.of(ClassRef.of(NONEXISTENT_CLASS));
-        assertIntrinsicFail(mtr1, () -> ldc(mtr1), NoClassDefFoundError.class);
-
-        MethodTypeRef mtr2 = MethodTypeRef.of(ClassRef.of(INACCESSIBLE_CLASS));
-        assertIntrinsicFail(mtr2, () -> ldc(mtr2), IllegalAccessError.class);
-    }
-
-    public void testLdcEnum() throws ReflectiveOperationException {
-        EnumRef<TestEnum> enr1 = EnumRef.of(CR_TESTENUM, "A");
-        assertIntrinsic(enr1, ldc(enr1), TestEnum.A);
-
-        EnumRef<TestEnum> enr2 = EnumRef.of(CR_TESTENUM, "B");
-        assertIntrinsic(enr2, ldc(enr2), TestEnum.B);
-    }
-
-    public void negLdcEnum() {
-        EnumRef<TestEnum> enr1 = EnumRef.of(CR_TESTENUM, "C");
-        assertIntrinsicFail(enr1, () -> ldc(enr1), IllegalArgumentException.class);
-
-        EnumRef<TestEnum> enr2 = EnumRef.of(ClassRef.of(NONEXISTENT_CLASS), "A");
-        assertIntrinsicFail(enr2, () -> ldc(enr2), NoClassDefFoundError.class);
-
-        EnumRef<TestEnum> enr3 = EnumRef.of(CR_THIS, "A");
-        assertIntrinsicFail(enr3, () -> ldc(enr3), IllegalArgumentException.class);
-
-        EnumRef<TestEnum> enr4 = EnumRef.of(ClassRef.of(INACCESSIBLE_CLASS), "A");
-        assertIntrinsicFail(enr4, () -> ldc(enr4), IllegalAccessError.class);
-    }
-
-    public void testLdcSelfConstants() throws ReflectiveOperationException {
-        assertIntrinsic("Foo", ldc("Foo"), "Foo");
-        assertIntrinsic(1, ldc(1), 1);
-        assertIntrinsic(1L, ldc(1L), 1L);
-        assertIntrinsic(2.0f, ldc(2.0f), 2.0f);
-        assertIntrinsic(3.0d, ldc(3.0d), 3.0d);
-    }
-
-    public void testLdcMethodHandleFromInner() throws Throwable {
-        TestClass.ldcMethodHandleFromInner();
-        TestClass.negLdcMethodHandleFromInner();
-        TestInterface.testLdcMethodHandleFromIntf(new TestInterface(){});
-    }
-
-    public void testLdcMethodHandle() throws Throwable {
-        TestClass instance = (TestClass) ldc(MHR_TESTCLASS_CTOR).invokeExact();
-
-        assertEquals(5, (int) ldc(MHR_TESTCLASS_SM).invokeExact(5));
-        assertEquals(0, (int) ldc(MHR_TESTINTF_SM).invokeExact(5));
-
-        assertEquals(5, (int) ldc(MHR_TESTCLASS_M).invokeExact(instance, 5));
-        assertEquals(5, (int) ldc(MHR_TESTINTF_M).invoke(instance, 5));
-
-        ldc(MHR_TESTCLASS_SF_SETTER).invokeExact(8);
-        assertEquals(TestClass.sf, 8);
-        assertEquals(8, (int) ldc(MHR_TESTCLASS_SF_GETTER).invokeExact());
-
-        assertEquals(3, (int) ldc(MHR_TESTINTF_SF_GETTER).invokeExact());
-
-        ldc(MHR_TESTCLASS_F_SETTER).invokeExact(instance, 9); assertEquals(instance.f, 9);
-        assertEquals(9, (int) ldc(MHR_TESTCLASS_F_GETTER).invokeExact(instance));
-    }
-
-    public void negLdcMethodHandle() {
-        // Accessible classes, inaccessible methods
-        assertIntrinsicFail(MHR_TESTCLASS_PM_SPECIAL, () -> ldc(MHR_TESTCLASS_PM_SPECIAL), IllegalAccessError.class);
-        assertIntrinsicFail(MHR_TESTINTF_PM_SPECIAL, () -> ldc(MHR_TESTINTF_PM_SPECIAL), IllegalAccessError.class);
-        assertIntrinsicFail(MHR_TESTCLASS_PSM, () -> ldc(MHR_TESTCLASS_PSM), IllegalAccessError.class);
-        assertIntrinsicFail(MHR_TESTINTF_PSM, () -> ldc(MHR_TESTINTF_PSM), IllegalAccessError.class);
-
-        // Accessible class and method, but illegal super access
-        assertIntrinsicFail(MHR_TESTSUPER_M_SPECIAL, () -> ldc(MHR_TESTSUPER_M_SPECIAL), IllegalAccessError.class);
-        assertIntrinsicFail(MHR_TESTINTF_M_SPECIAL, () -> ldc(MHR_TESTINTF_M_SPECIAL), IncompatibleClassChangeError.class);
-
-        // Method kind mismatches -- intf, virtual, static
-        MethodHandleRef intfMethodAsVirtual = MethodHandleRef.of(MethodHandleRef.Kind.VIRTUAL, CR_TESTINTF, "m", MethodTypeRef.ofDescriptor("(I)I"));
-        MethodHandleRef intfMethodAsStatic = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_TESTINTF, "m", MethodTypeRef.ofDescriptor("(I)I"));
-        MethodHandleRef virtualMethodAsIntf = MethodHandleRef.of(MethodHandleRef.Kind.INTERFACE_VIRTUAL, CR_TESTCLASS, "m", MethodTypeRef.ofDescriptor("(I)I"));
-        MethodHandleRef virtualMethodAsStatic = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_TESTCLASS, "m", MethodTypeRef.ofDescriptor("(I)I"));
-        MethodHandleRef staticMethodAsVirtual = MethodHandleRef.of(MethodHandleRef.Kind.VIRTUAL, CR_TESTCLASS, "sm", MethodTypeRef.ofDescriptor("(I)I"));
-        MethodHandleRef staticMethodAsIntf = MethodHandleRef.of(MethodHandleRef.Kind.INTERFACE_VIRTUAL, CR_TESTINTF, "sm", MethodTypeRef.ofDescriptor("(I)I"));
-
-        assertIntrinsicFail(intfMethodAsVirtual, () -> ldc(intfMethodAsVirtual), IncompatibleClassChangeError.class);
-        assertIntrinsicFail(intfMethodAsStatic, () -> ldc(intfMethodAsStatic), IncompatibleClassChangeError.class);
-        assertIntrinsicFail(virtualMethodAsIntf, () -> ldc(virtualMethodAsIntf), IncompatibleClassChangeError.class);
-        assertIntrinsicFail(virtualMethodAsStatic, () -> ldc(virtualMethodAsStatic), IncompatibleClassChangeError.class);
-        assertIntrinsicFail(staticMethodAsVirtual, () -> ldc(staticMethodAsVirtual), IncompatibleClassChangeError.class);
-        assertIntrinsicFail(staticMethodAsIntf, () -> ldc(staticMethodAsIntf), IncompatibleClassChangeError.class);
-
-        // Field kind mismatch -- instance/static
-        MethodHandleRef staticFieldAsInstance = MethodHandleRef.ofField(MethodHandleRef.Kind.GETTER, CR_TESTCLASS, "sf", ConstantRefs.CR_int);
-        MethodHandleRef instanceFieldAsStatic = MethodHandleRef.of(MethodHandleRef.Kind.STATIC_GETTER, CR_TESTCLASS, "f", ConstantRefs.CR_int);
-
-        assertIntrinsicFail(staticFieldAsInstance, () -> ldc(staticFieldAsInstance), IncompatibleClassChangeError.class);
-        assertIntrinsicFail(instanceFieldAsStatic, () -> ldc(instanceFieldAsStatic), IncompatibleClassChangeError.class);
-
-        // Setter for final field
-        MethodHandleRef finalStaticSetter = MethodHandleRef.ofField(MethodHandleRef.Kind.STATIC_SETTER, CR_TESTCLASS, "sff", ConstantRefs.CR_int);
-        MethodHandleRef finalSetter = MethodHandleRef.ofField(MethodHandleRef.Kind.SETTER, CR_TESTCLASS, "ff", ConstantRefs.CR_int);
-
-        assertIntrinsicFail(finalStaticSetter, () -> ldc(finalStaticSetter), IllegalAccessError.class);
-        assertIntrinsicFail(finalSetter, () -> ldc(finalSetter), IllegalAccessError.class);
-
-        // Nonexistent owner
-        MethodHandleRef r1 = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, ClassRef.of(NONEXISTENT_CLASS), "m", "()V");
-        assertIntrinsicFail(r1, () -> ldc(r1), NoClassDefFoundError.class);
-
-        // Inaccessible owner
-        MethodHandleRef r2 = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, ClassRef.of(INACCESSIBLE_CLASS), "m", "()V");
-        assertIntrinsicFail(r2, () -> ldc(r2), IllegalAccessError.class);
-
-        // Nonexistent method, ctor, field
-        MethodHandleRef r3 = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_TESTCLASS, "nonexistent", "()V");
-        MethodHandleRef r4 = MethodHandleRef.of(MethodHandleRef.Kind.VIRTUAL, CR_TESTCLASS, "nonexistent", "()V");
-        MethodHandleRef r5 = MethodHandleRef.of(MethodHandleRef.Kind.CONSTRUCTOR, CR_TESTCLASS, "<ignored>", "(I)V");
-        MethodHandleRef r6 = MethodHandleRef.ofField(MethodHandleRef.Kind.GETTER, CR_TESTCLASS, "nonexistent", ConstantRefs.CR_int);
-        MethodHandleRef r7 = MethodHandleRef.ofField(MethodHandleRef.Kind.SETTER, CR_TESTCLASS, "nonexistent", ConstantRefs.CR_int);
-        MethodHandleRef r8 = MethodHandleRef.ofField(MethodHandleRef.Kind.STATIC_GETTER, CR_TESTCLASS, "nonexistent", ConstantRefs.CR_int);
-        MethodHandleRef r9 = MethodHandleRef.ofField(MethodHandleRef.Kind.STATIC_SETTER, CR_TESTCLASS, "nonexistent", ConstantRefs.CR_int);
-
-        assertIntrinsicFail(r3, () -> ldc(r3), NoSuchMethodError.class);
-        assertIntrinsicFail(r4, () -> ldc(r4), NoSuchMethodError.class);
-        assertIntrinsicFail(r5, () -> ldc(r5), NoSuchMethodError.class);
-        assertIntrinsicFail(r6, () -> ldc(r6), NoSuchFieldError.class);
-        assertIntrinsicFail(r7, () -> ldc(r7), NoSuchFieldError.class);
-        assertIntrinsicFail(r8, () -> ldc(r8), NoSuchFieldError.class);
-        assertIntrinsicFail(r9, () -> ldc(r9), NoSuchFieldError.class);
-    }
-
-    public void testLdcDynamicConstants() throws ReflectiveOperationException {
-        assertNull(ldc(ConstantRefs.NULL));
-        assertIntrinsic(ConstantRefs.CR_int, ldc(ConstantRefs.CR_int), int.class);
-        // @@@ VarHandle
-        // @@@ invoke (including multiple deep)
-    }
-
-    public void negLdcDynamicConstants() {
-        // @@@ negative tests for nonexistent/inaccessible bootstrap
-        // @@@ negative tests for bootstrap parameter mismatch
-    }
-
-    private enum TestEnum {
-        A, B;
-    }
-
-    private interface TestInterface {
-        public static final int sf = 3;
-
-        static int sm(int x) { return 0; }
-        default int m(int x) { return 0; }
-        private int pm(int x) { return 1; }
-        private static int psm(int x) { return 2; }
-
-        static void testLdcMethodHandleFromIntf(TestInterface testInterface) throws Throwable {
-            assertEquals(1, ldc(MHR_TESTINTF_PM_SPECIAL).invoke(testInterface, 1));
-            assertEquals(2, ldc(MHR_TESTINTF_PSM).invoke(1));
-        }
-    }
-
-    private static class TestSuperclass {
-        public int m(int x) { return -1; }
-    }
-
-    private static class TestClass extends TestSuperclass implements TestInterface {
-
-        static final int sff = 7;
-        static final int ff = 8;
-
-        static int sf;
-        int f;
-
-        public TestClass()  {}
-
-        public static int sm(int x) { return x; }
-        public int m(int x) { return x; }
-        private static int psm(int x) { return x; }
-        private int pm(int x) { return x; }
-
-        private static void negLdcMethodHandleFromInner() {
-            // When we have nestmates, these will probably start succeeding,
-            // at which point we will need to find new negative tests for super-access.
-            assertIntrinsicFail(MHR_TESTINTF_PM_SPECIAL, () -> ldc(MHR_TESTINTF_PM_SPECIAL), IllegalAccessError.class);
-            assertIntrinsicFail(MHR_TESTINTF_PSM, () -> ldc(MHR_TESTINTF_PSM), IllegalAccessError.class);
-        }
-
-        private static void ldcMethodHandleFromInner() throws Throwable {
-            TestClass instance = (TestClass) ldc(MHR_TESTCLASS_CTOR).invokeExact();
-
-            assertEquals(-1, (int) ldc(MHR_TESTSUPER_M_SPECIAL).invokeExact(instance, 5));
-            assertEquals(0, (int) ldc(MHR_TESTINTF_M_SPECIAL).invokeExact(instance, 5));
-
-            assertEquals(5, (int) ldc(MHR_TESTCLASS_PM_SPECIAL).invokeExact(instance, 5));
-
-            assertEquals(5, (int) ldc(MHR_TESTCLASS_PSM).invokeExact(5));
-        }
-
-    }
-
-    private static int privateStaticMethod(int i) {
-        return i;
-    }
-
-    private int privateMethod(int i) {
-        return i;
-    }
-}
--- a/test/jdk/java/lang/sym/MethodHandleRefTest.java	Wed Mar 07 14:59:03 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,308 +0,0 @@
-/*
- * Copyright (c) 2012, 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.
- */
-
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandleInfo;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-import java.lang.invoke.WrongMethodTypeException;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.lang.sym.ClassRef;
-import java.lang.sym.ConstantMethodHandleRef;
-import java.lang.sym.MethodHandleRef;
-import java.lang.sym.MethodTypeRef;
-import java.lang.sym.ConstantRefs;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.function.Supplier;
-
-import org.testng.annotations.Test;
-
-import static java.lang.sym.MethodHandleRef.Kind.GETTER;
-import static java.lang.sym.MethodHandleRef.Kind.SETTER;
-import static java.lang.sym.MethodHandleRef.Kind.STATIC_GETTER;
-import static java.lang.sym.MethodHandleRef.Kind.STATIC_SETTER;
-import static java.lang.sym.ConstantRefs.CR_Integer;
-import static java.lang.sym.ConstantRefs.CR_List;
-import static java.lang.sym.ConstantRefs.CR_Object;
-import static java.lang.sym.ConstantRefs.CR_String;
-import static java.lang.sym.ConstantRefs.CR_int;
-import static java.lang.sym.ConstantRefs.CR_void;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
-
-/**
- * @test
- * @run testng MethodHandleRefTest
- * @summary unit tests for java.lang.sym.MethodHandleRefTest
- */
-@Test
-public class MethodHandleRefTest extends SymbolicRefTest {
-    private static ClassRef thisClass = ClassRef.of("MethodHandleRefTest");
-    private static ClassRef testClass = thisClass.inner("TestClass");
-    private static ClassRef testInterface = thisClass.inner("TestInterface");
-    private static ClassRef testSuperclass = thisClass.inner("TestSuperclass");
-
-
-    private static void assertMHEquals(MethodHandle a, MethodHandle b) {
-        MethodHandleInfo ia = LOOKUP.revealDirect(a);
-        MethodHandleInfo ib = LOOKUP.revealDirect(b);
-        assertEquals(ia.getDeclaringClass(), ib.getDeclaringClass());
-        assertEquals(ia.getName(), ib.getName());
-        assertEquals(ia.getMethodType(), ib.getMethodType());
-        assertEquals(ia.getReferenceKind(), ib.getReferenceKind());
-    }
-
-    private void testMethodHandleRef(MethodHandleRef r) throws ReflectiveOperationException {
-        if (r instanceof ConstantMethodHandleRef) {
-            testSymbolicRef(r);
-
-            ConstantMethodHandleRef rr = (ConstantMethodHandleRef) r;
-            assertEquals(r, MethodHandleRef.of(rr.kind(), rr.owner(), rr.methodName(), r.methodType()));
-        }
-        else {
-            testSymbolicRefForwardOnly(r);
-        }
-    }
-
-    private void testMethodHandleRef(MethodHandleRef r, MethodHandle mh) throws ReflectiveOperationException {
-        testMethodHandleRef(r);
-
-        assertMHEquals(r.resolveConstantRef(LOOKUP), mh);
-        assertEquals(mh.toConstantRef(LOOKUP).orElseThrow(), r);
-
-        // compare extractable properties: refKind, owner, name, type
-        MethodHandleInfo mhi = LOOKUP.revealDirect(mh);
-        ConstantMethodHandleRef rr = (ConstantMethodHandleRef) r;
-        assertEquals(mhi.getDeclaringClass().toDescriptorString(), rr.owner().descriptorString());
-        assertEquals(mhi.getName(), rr.methodName());
-        assertEquals(mhi.getReferenceKind(), rr.kind().refKind);
-        assertEquals(mhi.getMethodType().toMethodDescriptorString(), r.methodType().descriptorString());
-    }
-
-    public void testSimpleMHs() throws ReflectiveOperationException {
-        testMethodHandleRef(MethodHandleRef.of(MethodHandleRef.Kind.VIRTUAL, CR_String, "isEmpty", "()Z"),
-                            LOOKUP.findVirtual(String.class, "isEmpty", MethodType.fromMethodDescriptorString("()Z", null)));
-        testMethodHandleRef(MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_String, "format", CR_String, CR_String, CR_Object.array()),
-                            LOOKUP.findStatic(String.class, "format", MethodType.methodType(String.class, String.class, Object[].class)));
-        testMethodHandleRef(MethodHandleRef.of(MethodHandleRef.Kind.INTERFACE_VIRTUAL, CR_List, "isEmpty", "()Z"),
-                            LOOKUP.findVirtual(List.class, "isEmpty", MethodType.fromMethodDescriptorString("()Z", null)));
-        testMethodHandleRef(MethodHandleRef.of(MethodHandleRef.Kind.CONSTRUCTOR, ClassRef.of("java.util.ArrayList"), "<init>", CR_void),
-                            LOOKUP.findConstructor(ArrayList.class, MethodType.methodType(void.class)));
-    }
-
-    public void testAsType() throws Throwable {
-        MethodHandleRef mhr = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, ClassRef.of("java.lang.Integer"), "valueOf",
-                                                 MethodTypeRef.of(CR_Integer, CR_int));
-            MethodHandleRef takesInteger = mhr.asType(MethodTypeRef.of(CR_Integer, CR_Integer));
-        testMethodHandleRef(takesInteger);
-        MethodHandle mh1 = takesInteger.resolveConstantRef(LOOKUP);