changeset 47368:d7540a5a5ea6 condy-folding

small scale refactoring to condy folding, improving the original patch
author vromero
date Mon, 02 Oct 2017 18:45:11 -0700
parents eea57999102e
children 0b0d8e79beb7
files src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ConstFold.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ConstablesVisitor.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Pool.java src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java src/jdk.compiler/share/classes/com/sun/tools/javac/util/Constables.java src/jdk.compiler/share/classes/com/sun/tools/javac/util/SpecialConstantUtils.java
diffstat 13 files changed, 750 insertions(+), 804 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java	Mon Oct 02 18:27:12 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java	Mon Oct 02 18:45:11 2017 -0700
@@ -101,7 +101,7 @@
 
     public final Warner noWarnings;
     private final boolean doConstantFold;
-    private final SpecialConstantUtils specialConstUtils;
+    private final Constables constables;
 
     // <editor-fold defaultstate="collapsed" desc="Instantiating">
     public static Types instance(Context context) {
@@ -128,7 +128,7 @@
         noWarnings = new Warner(null);
         Options options = Options.instance(context);
         doConstantFold = options.isSet("doConstantFold");
-        specialConstUtils = new SpecialConstantUtils(context);
+        constables = new Constables(context);
     }
     // </editor-fold>
 
@@ -1261,7 +1261,7 @@
      *   (v) is native.
     */
    public boolean isSignaturePolymorphic(MethodSymbol msym) {
-       if (doConstantFold && specialConstUtils.isIntrinsicsIndy(msym)) {
+       if (doConstantFold && constables.isIntrinsicsIndy(msym)) {
            return true;
        }
        List<Type> argtypes = msym.type.getParameterTypes();
@@ -4282,22 +4282,6 @@
         return syms.enterClass(syms.java_base, syms.boxedName[t.getTag().ordinal()]);
     }
 
-    public ClassSymbol boxedClass(String descriptor) {
-        switch (descriptor) {
-            case "I": return syms.enterClass(syms.java_base, syms.boxedName[TypeTag.INT.ordinal()]);
-            case "J": return syms.enterClass(syms.java_base, syms.boxedName[TypeTag.LONG.ordinal()]);
-            case "S": return syms.enterClass(syms.java_base, syms.boxedName[TypeTag.SHORT.ordinal()]);
-            case "B": return syms.enterClass(syms.java_base, syms.boxedName[TypeTag.BYTE.ordinal()]);
-            case "C": return syms.enterClass(syms.java_base, syms.boxedName[TypeTag.CHAR.ordinal()]);
-            case "F": return syms.enterClass(syms.java_base, syms.boxedName[TypeTag.FLOAT.ordinal()]);
-            case "D": return syms.enterClass(syms.java_base, syms.boxedName[TypeTag.DOUBLE.ordinal()]);
-            case "Z": return syms.enterClass(syms.java_base, syms.boxedName[TypeTag.BOOLEAN.ordinal()]);
-            case "V": return syms.enterClass(syms.java_base, syms.boxedName[TypeTag.VOID.ordinal()]);
-            default:
-                throw new AssertionError("invalid primitive descriptor " + descriptor);
-        }
-    }
-
     /**
      * Return the boxed type if 't' is primitive, otherwise return 't' itself.
      */
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Mon Oct 02 18:27:12 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Mon Oct 02 18:45:11 2017 -0700
@@ -2023,7 +2023,6 @@
             Type capturedRes = resultInfo.checkContext.inferenceContext().cachedCapture(tree, restype, true);
             result = check(tree, capturedRes, KindSelector.VAL, resultInfo);
         }
-        tree.resolutionPhase = localEnv.info.pendingResolutionPhase;
         chk.validate(tree.typeargs, localEnv);
     }
     //where
@@ -3375,7 +3374,7 @@
 
             // If the argument is constant, fold it.
             if (argtype.constValue() != null) {
-                Type ctype = cfolder.fold1(opc, argtype, argtype.constValue());
+                Type ctype = cfolder.fold1(opc, argtype);
                 if (ctype != null) {
                     owntype = cfolder.coerce(ctype, owntype);
                 }
@@ -3398,7 +3397,7 @@
             int opc = ((OperatorSymbol)operator).opcode;
             // If both arguments are constants, fold them.
             if (left.constValue() != null && right.constValue() != null) {
-                Type ctype = cfolder.fold2(opc, left, right, left.constValue(), right.constValue());
+                Type ctype = cfolder.fold2(opc, left, right);
                 if (ctype != null) {
                     owntype = cfolder.coerce(ctype, owntype);
                 }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ConstFold.java	Mon Oct 02 18:27:12 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ConstFold.java	Mon Oct 02 18:45:11 2017 -0700
@@ -81,6 +81,18 @@
      *  @param operand   The operation's operand type.
      *                   Argument types are assumed to have non-null constValue's.
      */
+    Type fold1(int opcode, Type operand) {
+        return fold1(opcode, operand, operand.constValue());
+    }
+
+    /** Fold unary operation.
+     *  @param opcode    The operation's opcode instruction (usually a byte code),
+     *                   as entered by class Symtab.
+     *                   opcode's ifeq to ifge are for postprocessing
+     *                   xcmp; ifxx pairs of instructions.
+     *  @param operand   The operation's operand type.
+     *                   Argument types are assumed to have non-null constValue's.
+     */
     Type fold1(int opcode, Type operand, Object od) {
         try {
             switch (opcode) {
@@ -132,6 +144,18 @@
      *  @param left      The type of the operation's left operand.
      *  @param right     The type of the operation's right operand.
      */
+    Type fold2(int opcode, Type left, Type right) {
+        return fold2(opcode, left, right, left.constValue(), right.constValue());
+    }
+
+    /** Fold binary operation.
+     *  @param opcode    The operation's opcode instruction (usually a byte code),
+     *                   as entered by class Symtab.
+     *                   opcode's ifeq to ifge are for postprocessing
+     *                   xcmp; ifxx pairs of instructions.
+     *  @param left      The type of the operation's left operand.
+     *  @param right     The type of the operation's right operand.
+     */
     Type fold2(int opcode, Type left, Type right, Object l, Object r) {
         try {
             Assert.check(l != null);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ConstablesVisitor.java	Mon Oct 02 18:27:12 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ConstablesVisitor.java	Mon Oct 02 18:45:11 2017 -0700
@@ -25,11 +25,6 @@
 
 package com.sun.tools.javac.comp;
 
-import java.lang.reflect.Array;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -40,16 +35,13 @@
 import com.sun.tools.javac.code.Symbol.VarSymbol;
 import com.sun.tools.javac.code.Symtab;
 import com.sun.tools.javac.code.Type;
-import com.sun.tools.javac.code.Type.ArrayType;
 import com.sun.tools.javac.code.Type.MethodType;
 import com.sun.tools.javac.code.Types;
-import com.sun.tools.javac.comp.Resolve.MethodResolutionPhase;
 import com.sun.tools.javac.jvm.Pool;
 import com.sun.tools.javac.resources.CompilerProperties.Errors;
 import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.tree.JCTree.JCBinary;
 import com.sun.tools.javac.tree.JCTree.JCConditional;
-import com.sun.tools.javac.tree.JCTree.JCExpression;
 import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
 import com.sun.tools.javac.tree.JCTree.JCIdent;
 import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
@@ -58,6 +50,7 @@
 import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
 import com.sun.tools.javac.tree.TreeInfo;
 import com.sun.tools.javac.tree.TreeScanner;
+import com.sun.tools.javac.util.Constables;
 import com.sun.tools.javac.util.Context;
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.util.ListBuffer;
@@ -65,14 +58,11 @@
 import com.sun.tools.javac.util.Name;
 import com.sun.tools.javac.util.Names;
 import com.sun.tools.javac.util.Options;
-import com.sun.tools.javac.util.SpecialConstantUtils;
 
 import static com.sun.tools.javac.code.Flags.EFFECTIVELY_FINAL;
 import static com.sun.tools.javac.code.Flags.FINAL;
 import static com.sun.tools.javac.code.Kinds.Kind.VAR;
-import static com.sun.tools.javac.code.TypeTag.ARRAY;
 import static com.sun.tools.javac.code.TypeTag.NONE;
-import static com.sun.tools.javac.tree.JCTree.Tag.SELECT;
 
 /**
  *  <p><b>This is NOT part of any supported API.
@@ -96,7 +86,7 @@
     private final Resolve rs;
     private final Log log;
     private final ConstFold cfolder;
-    private final SpecialConstantUtils specialConstantUtils;
+    private final Constables constables;
 
     protected ConstablesVisitor(Context context) {
         context.put(constablesVisitorKey, this);
@@ -108,9 +98,8 @@
         rs = Resolve.instance(context);
         log = Log.instance(context);
         cfolder = ConstFold.instance(context);
-        specialConstantUtils = new SpecialConstantUtils(context);
+        constables = new Constables(context);
         elementToConstantMap = new HashMap<>();
-        specialConstantsHelper = new SpecialConstantsHelper(types, names, syms, rs, log, specialConstantUtils, elementToConstantMap);
     }
 
     /**
@@ -129,7 +118,7 @@
         elementToConstantMap.clear();
     }
 
-    Map<Object, Object> elementToConstantMap;
+    public Map<Object, Object> elementToConstantMap;
 
     @Override
     public void visitVarDef(JCVariableDecl tree) {
@@ -241,7 +230,7 @@
                 constant = elementToConstantMap.get(v);
                 constant = constant != null ?
                         constant :
-                        specialConstantsHelper.foldTrackableField(tree, attrEnv);
+                        constables.foldTrackableField(tree, attrEnv);
                 if (constant != null) {
                     elementToConstantMap.put(tree, constant);
                 }
@@ -252,7 +241,7 @@
     @Override
     public void visitSelect(JCFieldAccess tree) {
         super.visitSelect(tree);
-        Object constantType = specialConstantsHelper.foldTrackableField(tree, attrEnv);
+        Object constantType = constables.foldTrackableField(tree, attrEnv);
         if (constantType != null) {
             elementToConstantMap.put(tree, constantType);
         }
@@ -264,9 +253,9 @@
         Name methName = TreeInfo.name(tree.meth);
         boolean isConstructorCall = methName == names._this || methName == names._super;
         if (!isConstructorCall) {
-            Object constant = specialConstantsHelper.foldMethodInvocation(tree, attrEnv);
+            Object constant = constables.foldMethodInvocation(tree, attrEnv);
             Symbol msym = TreeInfo.symbol(tree.meth);
-            boolean isLDC = specialConstantUtils.isIntrinsicsLDCInvocation(msym);
+            boolean isLDC = constables.isIntrinsicsLDCInvocation(msym);
             if (constant == null && isLDC) {
                 log.error(tree.pos(), Errors.IntrinsicsLdcMustHaveConstantArg);
             }
@@ -275,31 +264,27 @@
                 if (isLDC) {
                     // if condy
                     if (tree.args.head.type.tsym == syms.dynamicConstantRefType.tsym) {
-                        Object classRef =
-                                specialConstantUtils.invokeReflectiveMethod(specialConstantUtils.dynamicConstantClass, constant, "type");
-                        String descriptor = (String)specialConstantUtils.invokeReflectiveMethod(specialConstantUtils.classRefClass, classRef, "descriptorString");
-                        Type newType = specialConstantUtils.descriptorToType(descriptor, attrEnv.enclClass.sym.packge().modle, false);
-                        constant = specialConstantUtils.convertConstant(tree, attrEnv,
+                        constant = constables.convertConstant(tree, attrEnv,
                                 constant, attrEnv.enclClass.sym.packge().modle);
-                        ((Pool.ConstantDynamic)constant).updateType(newType);
                         MethodType oldMT = tree.meth.type.asMethodType();
-                        MethodType newMT = new MethodType(oldMT.argtypes, newType, oldMT.thrown, syms.methodClass);
+                        MethodType newMT = new MethodType(oldMT.argtypes,
+                                ((Pool.ConstantDynamic)constant).type, oldMT.thrown, syms.methodClass);
                         MethodSymbol newMS = new MethodSymbol(msym.flags_field, msym.name, newMT, msym.owner);
-                        TreeInfo.updateSymbol(tree.meth, msym, newMS);
+                        TreeInfo.setSymbol(tree.meth, newMS);
                         tree.meth.type = newMT;
-                        tree.type = newType;
+                        tree.type = newMT.restype;
                     } else {
-                        constant = specialConstantUtils.convertConstant(tree, attrEnv,
+                        constant = constables.convertConstant(tree, attrEnv,
                                 constant, attrEnv.enclClass.sym.packge().modle);
                     }
                     // lets update the field as condy could have changed it
                     msym = TreeInfo.symbol(tree.meth);
                     IntrinsicsLDCMethodSymbol ldcSymbol = new IntrinsicsLDCMethodSymbol(
                             msym.flags_field, msym.name, msym.type, msym.owner, constant);
-                    TreeInfo.updateSymbol(tree, msym, ldcSymbol);
+                    TreeInfo.setSymbol(tree.meth, ldcSymbol);
                 }
-            } else if (specialConstantUtils.isIntrinsicsIndy(tree)) {
-                List<Object> constants = specialConstantsHelper.extractAllConstansOrNone(List.of(tree.args.head, tree.args.tail.head));
+            } else if (constables.isIntrinsicsIndy(tree.meth)) {
+                List<Object> constants = constables.extractAllConstansOrNone(List.of(tree.args.head, tree.args.tail.head));
                 if (constants.isEmpty()) {
                     log.error(tree.args.head.pos(), Errors.IntrinsicsIndyMustHaveConstantArg);
                 } else {
@@ -308,9 +293,9 @@
                     if (invocationName.isEmpty()) {
                         log.error(tree.args.tail.head.pos(), Errors.InvocationNameCannotBeEmpty);
                     }
-                    Object mh = specialConstantUtils.invokeReflectiveMethod(specialConstantUtils.bootstrapSpecifierClass,
+                    Object mh = constables.invokeReflectiveMethod(constables.bootstrapSpecifierClass,
                             bootstrapSpecifier, "method");
-                    Pool.MethodHandle mHandle = (Pool.MethodHandle)specialConstantUtils
+                    Pool.MethodHandle mHandle = (Pool.MethodHandle)constables
                             .convertConstant(tree, attrEnv, mh, attrEnv.enclClass.sym.packge().modle);
                     boolean correct = false;
                     if (mHandle.refKind == 6 || mHandle.refKind == 8) {
@@ -328,8 +313,8 @@
                     ListBuffer<Type> arguments = new ListBuffer<>();
                     tree.args = tree.args.tail.tail;
                     tree.args.forEach(arg -> arguments.add(arg.type));
-                    Object[] bsmArgs = (Object[])specialConstantUtils.invokeReflectiveMethod(specialConstantUtils.bootstrapSpecifierClass, bootstrapSpecifier, "arguments");
-                    Object[] convertedBsmArgs = specialConstantUtils.convertConstants(tree, attrEnv, bsmArgs, attrEnv.enclClass.sym.packge().modle, true);
+                    Object[] bsmArgs = (Object[])constables.invokeReflectiveMethod(constables.bootstrapSpecifierClass, bootstrapSpecifier, "arguments");
+                    Object[] convertedBsmArgs = constables.convertConstants(tree, attrEnv, bsmArgs, attrEnv.enclClass.sym.packge().modle, true);
                     MethodType mType = new MethodType(arguments.toList(), tree.type, List.nil(), syms.methodClass);
                     DynamicMethodSymbol dynSym = new DynamicMethodSymbol(
                             names.fromString(invocationName),
@@ -338,228 +323,10 @@
                             (MethodSymbol)mHandle.refSym,
                             mType,
                             convertedBsmArgs);
-                    TreeInfo.updateSymbol(tree, msym, dynSym);
+                    TreeInfo.setSymbol(tree.meth, dynSym);
                     tree.meth.type = mType;
                 }
             }
         }
     }
-
-    final SpecialConstantsHelper specialConstantsHelper;
-
-    public static class SpecialConstantsHelper {
-        final Types types;
-        final Names names;
-        final Symtab syms;
-        final Resolve rs;
-        final Log log;
-        final SpecialConstantUtils specialConstantUtils;
-        final Map<Object, Object> elementToConstantMap;
-
-        public SpecialConstantsHelper(
-                Types types,
-                Names names,
-                Symtab syms,
-                Resolve rs,
-                Log log,
-                SpecialConstantUtils specialConstantUtils,
-                Map<Object, Object> elementsToConstantsMap) {
-            this.syms = syms;
-            this.types = types;
-            this.names = names;
-            this.rs = rs;
-            this.log = log;
-            this.specialConstantUtils = specialConstantUtils;
-            this.elementToConstantMap = elementsToConstantsMap;
-        }
-
-        /* This method doesnt verify that the annotated field is static it is assumed that
-         * it has to be
-         */
-        Object foldTrackableField(final JCTree tree, final Env<AttrContext> env) {
-            Symbol sym = TreeInfo.symbol(tree);
-            boolean trackableConstant = sym.attribute(syms.trackableConstantType.tsym) != null &&
-                    sym.packge().modle == syms.java_base;
-            if (trackableConstant) {
-                String className = sym.owner.type.tsym.flatName().toString();
-                try {
-                    Class<?> constablesClass = Class.forName(className, false, null);
-                    MemberKind mKind = getMemberKind(constablesClass, sym.name.toString());
-                    if (mKind == MemberKind.METHOD) {
-                        // we are in the middle of a method invocation bail out
-                        return null;
-                    }
-                    Field theField = constablesClass.getField(sym.name.toString());
-                    Object value = theField.get(null);
-                    if (value != null) {
-                        return value;
-                    }
-                } catch (ClassNotFoundException |
-                        NoSuchFieldException |
-                        IllegalAccessException ex) {
-                    log.error(tree, Errors.ReflectiveError(sym.name.toString(), className));
-                }
-            }
-            return null;
-        }
-
-        enum MemberKind {
-            FIELD,
-            METHOD
-        }
-
-        MemberKind getMemberKind(Class<?> aClass, String name) {
-            try {
-                aClass.getField(name);
-                return MemberKind.FIELD;
-            } catch (NoSuchFieldException ex) {
-                return MemberKind.METHOD;
-            }
-        }
-
-        Object foldMethodInvocation(final JCMethodInvocation tree, final Env<AttrContext> env) {
-            Symbol msym = TreeInfo.symbol(tree.meth);
-            Object constant = null;
-            boolean trackableConstant = msym.attribute(syms.trackableConstantType.tsym) != null &&
-                    msym.packge().modle == syms.java_base;
-            boolean isLDC = msym.owner.type.tsym == syms.intrinsicsType.tsym && msym.name == names.ldc;
-            if (trackableConstant || isLDC) {
-                List<Object> constantArgumentValues = extractAllConstansOrNone(tree.args);
-                boolean allConstants = tree.args.isEmpty() == constantArgumentValues.isEmpty();
-                if (allConstants) {
-                    if (trackableConstant) {
-                        constant = invokeConstablesMethod(tree, env, constantArgumentValues);
-                    } else if (isLDC) {
-                        constant = constantArgumentValues.head;
-                    }
-                }
-                if (constant != null) {
-                    return constant;
-                }
-            }
-            return null;
-        }
-
-        List<Object> extractAllConstansOrNone(List<JCExpression> args) {
-            ListBuffer<Object> constantArgumentValues = new ListBuffer<>();
-            for (JCExpression arg: args) {
-                Object argConstant = arg.type.constValue();
-                if (argConstant != null) {
-                    constantArgumentValues.add(argConstant);
-                } else {
-                    argConstant = elementToConstantMap.get(arg) != null ?
-                            elementToConstantMap.get(arg) :
-                            elementToConstantMap.get(TreeInfo.symbol(arg));
-                    if (argConstant != null) {
-                        constantArgumentValues.add(argConstant);
-                    } else {
-                        return List.nil();
-                    }
-                }
-            }
-            return constantArgumentValues.toList();
-        }
-
-        // where
-            Object invokeConstablesMethod(
-                    final JCMethodInvocation tree,
-                    final Env<AttrContext> env,
-                    List<Object> constantArgumentValues) {
-                String className = "";
-                Name methodName = names.empty;
-                try {
-                    Symbol msym = TreeInfo.symbol(tree.meth);
-                    JCTree qualifierTree = (tree.meth.hasTag(SELECT))
-                        ? ((JCFieldAccess) tree.meth).selected
-                        : null;
-                    Object instance = elementToConstantMap.get(qualifierTree);
-                    className = msym.owner.type.tsym.flatName().toString();
-                    methodName = msym.name;
-                    Class<?> constablesClass = Class.forName(className, false, null);
-                    MethodType mt = msym.type.asMethodType();
-                    java.util.List<Class<?>> argumentTypes =
-                            mt.argtypes.stream().map(t -> getClassForType(t)).collect(List.collector());
-                    Method theMethod = constablesClass.getDeclaredMethod(methodName.toString(),
-                            argumentTypes.toArray(new Class<?>[argumentTypes.size()]));
-                    int modifiers = theMethod.getModifiers();
-                    Type varTypeElement = mt.getParameterTypes().last();
-                    if (varTypeElement != null) {
-                        varTypeElement = types.elemtype(varTypeElement);
-                    }
-                    Object[] args = boxArgs(
-                            mt.argtypes,
-                            constantArgumentValues,
-                            tree.resolutionPhase == MethodResolutionPhase.VARARITY ? varTypeElement : null);
-                    if ((modifiers & Modifier.STATIC) == 0) {
-                        return (instance != null) ? theMethod.invoke(instance, args) : null;
-                    }
-                    return theMethod.invoke(null, args);
-                } catch (ClassNotFoundException |
-                        SecurityException |
-                        NoSuchMethodException |
-                        IllegalAccessException |
-                        IllegalArgumentException |
-                        InvocationTargetException ex) {
-                    log.error(tree, Errors.ReflectiveError(methodName.toString(), className));
-                    return null;
-                }
-            }
-
-            Class<?> getClassForType(Type t) {
-                try {
-                    if (t.isPrimitiveOrVoid()) {
-                        return t.getTag().theClass;
-                    } else {
-                        return Class.forName(getFlatName(t), false, null);
-                    }
-                } catch (ClassNotFoundException ex) {
-                    return null;
-                }
-            }
-
-            String getFlatName(Type t) {
-                String flatName = t.tsym.flatName().toString();
-                if (t.hasTag(ARRAY)) {
-                    flatName = "";
-                    while (t.hasTag(ARRAY)) {
-                        ArrayType at = (ArrayType)t;
-                        flatName += "[";
-                        t = at.elemtype;
-                    }
-                    flatName += "L" + t.tsym.flatName().toString() + ';';
-                }
-                return flatName;
-            }
-
-            Object[] boxArgs(List<Type> parameters, List<Object> _args, Type varargsElement) {
-                java.util.List<Object> result = new java.util.ArrayList<>();
-                List<Object> args = _args;
-                if (parameters.isEmpty()) return new Object[0];
-                while (parameters.tail.nonEmpty()) {
-                    result.add(args.head);
-                    args = args.tail;
-                    parameters = parameters.tail;
-                }
-                if (varargsElement != null) {
-                    java.util.List<Object> elems = new java.util.ArrayList<>();
-                    while (args.nonEmpty()) {
-                        elems.add(args.head);
-                        args = args.tail;
-                    }
-                    Class<?> arrayClass = null;
-                    try {
-                        arrayClass = Class.forName(getFlatName(varargsElement), false, null);
-                    } catch (ClassNotFoundException ex) {}
-                    Object arr = Array.newInstance(arrayClass, elems.size());
-                    for (int i = 0; i < elems.size(); i++) {
-                        Array.set(arr, i, elems.get(i));
-                    }
-                    result.add(arr);
-                } else {
-                    if (args.length() != 1) throw new AssertionError(args);
-                    result.add(args.head);
-                }
-                return result.toArray();
-            }
-    }
 }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Mon Oct 02 18:27:12 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Mon Oct 02 18:45:11 2017 -0700
@@ -3124,7 +3124,7 @@
         tree.arg = boxIfNeeded(translate(tree.arg, tree), tree.type);
 
         if (tree.hasTag(NOT) && tree.arg.type.constValue() != null) {
-            tree.type = cfolder.fold1(bool_not, tree.arg.type, tree.arg.type.constValue());
+            tree.type = cfolder.fold1(bool_not, tree.arg.type);
         }
 
         // If translated left hand side is an Apply, we are
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java	Mon Oct 02 18:27:12 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java	Mon Oct 02 18:45:11 2017 -0700
@@ -149,7 +149,7 @@
 
         doConstantFold = options.isSet("doConstantFold");
         if (doConstantFold) {
-            specialConstUtils = new SpecialConstantUtils(context);
+            constables = new Constables(context);
         }
     }
 
@@ -2625,7 +2625,7 @@
                         } else {
                             MethodSymbol msym = (MethodSymbol)sym;
                             if (doConstantFold &&
-                                    (specialConstUtils.isIntrinsicsIndy(msym))) {
+                                    (constables.isIntrinsicsIndy(msym))) {
                                 sym.flags_field |= SIGNATURE_POLYMORPHIC;
                                 return findPolymorphicSignatureInstance(env, sym, argtypes);
                             }
@@ -2654,19 +2654,11 @@
                                   List<Type> typeargtypes) {
         return resolveQualifiedMethod(new MethodResolutionContext(), pos, env, location, site, name, argtypes, typeargtypes);
     }
-    Symbol resolveQualifiedMethod(MethodResolutionContext resolveContext,
+    private Symbol resolveQualifiedMethod(MethodResolutionContext resolveContext,
                                   DiagnosticPosition pos, Env<AttrContext> env,
                                   Symbol location, Type site, Name name, List<Type> argtypes,
                                   List<Type> typeargtypes) {
-        return resolveQualifiedMethod(resolveContext, pos, env, location, site, name,
-                argtypes, typeargtypes, MethodResolutionPhase.VARARITY);
-    }
-    Symbol resolveQualifiedMethod(MethodResolutionContext resolveContext,
-                                  DiagnosticPosition pos, Env<AttrContext> env,
-                                  Symbol location, Type site, Name name, List<Type> argtypes,
-                                  List<Type> typeargtypes,
-                                  MethodResolutionPhase maxPhase) {
-        return lookupMethod(env, pos, location, resolveContext, new BasicLookupHelper(name, site, argtypes, typeargtypes, maxPhase) {
+        return lookupMethod(env, pos, location, resolveContext, new BasicLookupHelper(name, site, argtypes, typeargtypes) {
             @Override
             Symbol doLookup(Env<AttrContext> env, MethodResolutionPhase phase) {
                 return findMethod(env, site, name, argtypes, typeargtypes,
@@ -2681,7 +2673,7 @@
                     MethodSymbol msym = (MethodSymbol)sym;
                     if ((msym.flags() & SIGNATURE_POLYMORPHIC) != 0 ||
                         doConstantFold &&
-                        specialConstUtils.isIntrinsicsIndy(msym)) {
+                        constables.isIntrinsicsIndy(msym)) {
                         sym.flags_field |= SIGNATURE_POLYMORPHIC;
                         return findPolymorphicSignatureInstance(env, sym, argtypes);
                     }
@@ -2692,7 +2684,7 @@
     }
 
     private boolean doConstantFold;
-    private SpecialConstantUtils specialConstUtils;
+    private Constables constables;
 
     /** Find or create an implicit method of exactly the given type (after erasure).
      *  Searches in a side table, not the main scope of the site.
@@ -4673,7 +4665,7 @@
         }
     }
 
-    public enum MethodResolutionPhase {
+    enum MethodResolutionPhase {
         BASIC(false, false),
         BOX(true, false),
         VARARITY(true, true) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java	Mon Oct 02 18:27:12 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java	Mon Oct 02 18:45:11 2017 -0700
@@ -1649,6 +1649,8 @@
             // primitives special case
             if (constant instanceof VarSymbol && ((VarSymbol)constant).name == names.TYPE) {
                 m = items.makeStaticItem((Symbol)constant);
+            } else if (constant instanceof Pool.ConstantDynamic) {
+                m = items.makeCondyItem((Pool.ConstantDynamic)constant);
             } else {
                 m = items.makeImmediateItem(pt, constant);
             }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java	Mon Oct 02 18:27:12 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java	Mon Oct 02 18:45:11 2017 -0700
@@ -30,6 +30,7 @@
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.code.Type.*;
 import com.sun.tools.javac.jvm.Code.*;
+import com.sun.tools.javac.jvm.Pool.ConstantDynamic;
 import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.util.Assert;
 
@@ -164,6 +165,13 @@
         return new ImmediateItem(type, value);
     }
 
+    /** Make an item representing a condy.
+     *  @param value    The condy value.
+     */
+    Item makeCondyItem(ConstantDynamic value) {
+        return new CondyItem(value);
+    }
+
     /** Make an item representing an assignment expression.
      *  @param lhs      The item representing the assignment's left hand side.
      */
@@ -465,6 +473,33 @@
         }
     }
 
+    /** An item representing a condy
+     */
+    class CondyItem extends Item {
+        ConstantDynamic value;
+
+        CondyItem(ConstantDynamic value) {
+            super(Code.typecode(value.type));
+            this.value = value;
+        }
+
+        @Override
+        public String toString() {
+            return "condy(" + value + ")";
+        }
+
+        @Override
+        Item load() {
+            int idx = pool.put(value);
+            if (typecode == LONGcode || typecode == DOUBLEcode) {
+                code.emitop2(ldc2w, idx);
+            } else {
+                code.emitLdc(idx);
+            }
+            return stackItem[typecode];
+        }
+    }
+
     /** An item representing a dynamic call site.
      */
     class DynamicItem extends StaticItem {
@@ -473,11 +508,7 @@
         }
 
         Item load() {
-            Assert.check(member.kind == Kind.VAR);
-            Type type = member.erasure(types);
-            int rescode = Code.typecode(type);
-            code.emitLdc(pool.put(member));
-            return stackItem[rescode];
+            throw new AssertionError();
         }
 
         void store() {
@@ -581,49 +612,45 @@
         }
 
         Item load() {
-            if (value instanceof Pool.ConstantDynamic) {
+            switch (typecode) {
+            case INTcode: case BYTEcode: case SHORTcode: case CHARcode:
+                int ival = ((Number)value).intValue();
+                if (-1 <= ival && ival <= 5)
+                    code.emitop0(iconst_0 + ival);
+                else if (Byte.MIN_VALUE <= ival && ival <= Byte.MAX_VALUE)
+                    code.emitop1(bipush, ival);
+                else if (Short.MIN_VALUE <= ival && ival <= Short.MAX_VALUE)
+                    code.emitop2(sipush, ival);
+                else
+                    ldc();
+                break;
+            case LONGcode:
+                long lval = ((Number)value).longValue();
+                if (lval == 0 || lval == 1)
+                    code.emitop0(lconst_0 + (int)lval);
+                else
+                    ldc();
+                break;
+            case FLOATcode:
+                float fval = ((Number)value).floatValue();
+                if (isPosZero(fval) || fval == 1.0 || fval == 2.0)
+                    code.emitop0(fconst_0 + (int)fval);
+                else {
+                    ldc();
+                }
+                break;
+            case DOUBLEcode:
+                double dval = ((Number)value).doubleValue();
+                if (isPosZero(dval) || dval == 1.0)
+                    code.emitop0(dconst_0 + (int)dval);
+                else
+                    ldc();
+                break;
+            case OBJECTcode:
                 ldc();
-            } else {
-                switch (typecode) {
-                case INTcode: case BYTEcode: case SHORTcode: case CHARcode:
-                    int ival = ((Number)value).intValue();
-                    if (-1 <= ival && ival <= 5)
-                        code.emitop0(iconst_0 + ival);
-                    else if (Byte.MIN_VALUE <= ival && ival <= Byte.MAX_VALUE)
-                        code.emitop1(bipush, ival);
-                    else if (Short.MIN_VALUE <= ival && ival <= Short.MAX_VALUE)
-                        code.emitop2(sipush, ival);
-                    else
-                        ldc();
-                    break;
-                case LONGcode:
-                    long lval = ((Number)value).longValue();
-                    if (lval == 0 || lval == 1)
-                        code.emitop0(lconst_0 + (int)lval);
-                    else
-                        ldc();
-                    break;
-                case FLOATcode:
-                    float fval = ((Number)value).floatValue();
-                    if (isPosZero(fval) || fval == 1.0 || fval == 2.0)
-                        code.emitop0(fconst_0 + (int)fval);
-                    else {
-                        ldc();
-                    }
-                    break;
-                case DOUBLEcode:
-                    double dval = ((Number)value).doubleValue();
-                    if (isPosZero(dval) || dval == 1.0)
-                        code.emitop0(dconst_0 + (int)dval);
-                    else
-                        ldc();
-                    break;
-                case OBJECTcode:
-                    ldc();
-                    break;
-                default:
-                    Assert.error();
-                }
+                break;
+            default:
+                Assert.error();
             }
             return stackItem[typecode];
         }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Pool.java	Mon Oct 02 18:27:12 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Pool.java	Mon Oct 02 18:45:11 2017 -0700
@@ -300,18 +300,19 @@
     public static class ConstantDynamic {
         MethodHandle bsm;
         Name name;
-        Type type;
-
+        public Type type;
         Object[] args;
         Types types;
 
         public ConstantDynamic(Name name, MethodHandle bsm, Object[] args, Types types) {
+            this(name, bsm, bsm.refSym.type.asMethodType().restype, args, types);
+        }
+
+        public ConstantDynamic(Name name, MethodHandle bsm, Type type, Object[] args, Types types) {
             Assert.checkNonNull(args);
             this.bsm = bsm;
-            MethodSymbol ms = (MethodSymbol)bsm.refSym;
-            MethodType mt = (MethodType)ms.type;
             this.name = name;
-            this.type = mt.restype;
+            this.type = type;
             this.args = args;
             this.types = types;
         }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java	Mon Oct 02 18:27:12 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java	Mon Oct 02 18:45:11 2017 -0700
@@ -1620,7 +1620,6 @@
         public JCExpression meth;
         public List<JCExpression> args;
         public Type varargsElement;
-        public Resolve.MethodResolutionPhase resolutionPhase;
         protected JCMethodInvocation(List<JCExpression> typeargs,
                         JCExpression meth,
                         List<JCExpression> args)
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Mon Oct 02 18:27:12 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Mon Oct 02 18:45:11 2017 -0700
@@ -858,66 +858,11 @@
             return symbol(((JCAnnotatedType) tree).underlyingType);
         case REFERENCE:
             return ((JCMemberReference) tree).sym;
-        case VARDEF :
-            return ((JCVariableDecl)tree).sym;
-        case TYPEIDENT:
-            return ((JCPrimitiveTypeTree)tree).type.tsym;
-        case TYPEARRAY:
-            return ((JCArrayTypeTree)tree).type.tsym;
-        case APPLY:
-            return symbol(((JCMethodInvocation)tree).meth);
         default:
             return null;
         }
     }
 
-    public static void updateSymbol(JCTree tree, Symbol oldSymbol, Symbol newSymbol) {
-        tree = skipParens(tree);
-        switch (tree.getTag()) {
-        case IDENT:
-            if (((JCIdent) tree).sym == oldSymbol) {
-                ((JCIdent) tree).sym = newSymbol;
-            }
-            return;
-        case SELECT:
-            if (((JCFieldAccess) tree).sym == oldSymbol) {
-                ((JCFieldAccess) tree).sym = newSymbol;
-            }
-            return;
-        case TYPEAPPLY:
-            updateSymbol(((JCTypeApply) tree).clazz, oldSymbol, newSymbol);
-            return;
-        case ANNOTATED_TYPE:
-            updateSymbol(((JCAnnotatedType) tree).underlyingType, oldSymbol, newSymbol);
-            return;
-        case REFERENCE:
-            if (((JCMemberReference) tree).sym == oldSymbol) {
-                ((JCMemberReference) tree).sym = newSymbol;
-            }
-            return;
-        case VARDEF :
-            if (((JCVariableDecl)tree).sym == oldSymbol) {
-                ((JCVariableDecl)tree).sym = (Symbol.VarSymbol)newSymbol;
-            }
-            return;
-        case TYPEIDENT:
-            if (((JCPrimitiveTypeTree)tree).type.tsym == oldSymbol) {
-                ((JCPrimitiveTypeTree)tree).type.tsym = (Symbol.TypeSymbol)newSymbol;
-            }
-            return;
-        case TYPEARRAY:
-            if (((JCArrayTypeTree)tree).type.tsym == oldSymbol) {
-                ((JCArrayTypeTree)tree).type.tsym = (Symbol.TypeSymbol)newSymbol;
-            }
-            return;
-        case APPLY:
-            updateSymbol(((JCMethodInvocation)tree).meth, oldSymbol, newSymbol);
-            return;
-        default:
-            return;
-        }
-    }
-
     /** Return true if this is a nonstatic selection. */
     public static boolean nonstaticSelect(JCTree tree) {
         tree = skipParens(tree);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Constables.java	Mon Oct 02 18:45:11 2017 -0700
@@ -0,0 +1,609 @@
+/*
+ * Copyright (c) 2017, 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 com.sun.tools.javac.util;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.nio.charset.Charset;
+import java.util.Map;
+
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symbol.MethodSymbol;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
+import com.sun.tools.javac.code.Symbol.VarSymbol;
+import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.Type.ArrayType;
+import com.sun.tools.javac.code.Type.ClassType;
+import com.sun.tools.javac.code.Type.MethodType;
+import com.sun.tools.javac.code.TypeTag;
+import com.sun.tools.javac.code.Types;
+import com.sun.tools.javac.comp.AttrContext;
+import com.sun.tools.javac.comp.ConstablesVisitor;
+import com.sun.tools.javac.comp.Env;
+import com.sun.tools.javac.comp.Resolve;
+import com.sun.tools.javac.jvm.ClassFile;
+import com.sun.tools.javac.jvm.Pool;
+import com.sun.tools.javac.resources.CompilerProperties.Errors;
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCExpression;
+import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
+import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
+import com.sun.tools.javac.tree.TreeInfo;
+
+import static com.sun.tools.javac.code.Flags.STATIC;
+import static com.sun.tools.javac.code.TypeTag.ARRAY;
+import static com.sun.tools.javac.tree.JCTree.Tag.APPLY;
+import static com.sun.tools.javac.tree.JCTree.Tag.SELECT;
+
+/** This class is a support tool to parse a method descriptor and obtain a list of the types
+ *  represented in it.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public class Constables {
+
+    public Constables(Context context) {
+        types = Types.instance(context);
+        names = Names.instance(context);
+        syms = Symtab.instance(context);
+        rs = Resolve.instance(context);
+        log = Log.instance(context);
+        constablesVisitor = ConstablesVisitor.instance(context);
+        try {
+            methodHandleRefClass = Class.forName("java.lang.invoke.MethodHandleRef", false, null);
+            methodTypeRefClass = Class.forName("java.lang.invoke.MethodTypeRef", false, null);
+            classRefClass = Class.forName("java.lang.invoke.ClassRef", false, null);
+            constantRefClass = Class.forName("java.lang.invoke.ConstantRef", false, null);
+            constablesClass = Class.forName("java.lang.invoke.Constables", false, null);
+            bootstrapSpecifierClass = Class.forName("java.lang.invoke.BootstrapSpecifier", false, null);
+            dynamicConstantClass = Class.forName("java.lang.invoke.DynamicConstantRef", false, null);
+        } catch (ClassNotFoundException ex) {
+            methodHandleRefClass = null;
+            methodTypeRefClass = null;
+            constantRefClass = null;
+            classRefClass = null;
+            bootstrapSpecifierClass = null;
+            dynamicConstantClass = null;
+            constablesClass = null;
+        }
+    }
+
+    private final Types types;
+    private final Names names;
+    private final Symtab syms;
+    private final Resolve rs;
+    private final Log log;
+    private ModuleSymbol currentModule;
+    private final ConstablesVisitor constablesVisitor;
+
+    /** The unread portion of the currently read type is
+     *  signature[sigp..siglimit-1].
+     */
+    byte[] signature;
+    int sigp;
+    int siglimit;
+    boolean sigEnterPhase = false;
+    byte[] signatureBuffer;
+    int sbp;
+
+    /** Convert signature to type, where signature is a byte array segment.
+     */
+    public Type descriptorToType(String descriptor, ModuleSymbol currentModule, boolean methodDescriptor) {
+        byte[] sig = descriptor.getBytes(Charset.forName("UTF-8"));
+        signature = sig;
+        sigp = 0;
+        siglimit = sig.length - 1;
+        sbp = 0;
+        signatureBuffer = new byte[sig.length];
+        this.currentModule = currentModule;
+        try {
+            if (methodDescriptor) {
+                return internalMethodDescriptorToType();
+            } else { // type descriptor
+                return sigToType();
+            }
+        } catch (AssertionError ae) {
+            return Type.noType;
+        }
+    }
+
+    private Type internalMethodDescriptorToType() {
+        if (signature[sigp] != '(') {
+            throw new AssertionError("bad descriptor");
+        }
+        sigp++;
+        List<Type> argtypes = sigToTypes(')');
+        Type restype = sigToType();
+        return new MethodType(argtypes,
+                              restype,
+                              List.nil(),
+                              syms.methodClass);
+    }
+
+    /** Convert signature to type, where signature is implicit.
+     */
+    Type sigToType() {
+        switch ((char) signature[sigp]) {
+        case 'B':
+            sigp++;
+            return syms.byteType;
+        case 'C':
+            sigp++;
+            return syms.charType;
+        case 'D':
+            sigp++;
+            return syms.doubleType;
+        case 'F':
+            sigp++;
+            return syms.floatType;
+        case 'I':
+            sigp++;
+            return syms.intType;
+        case 'J':
+            sigp++;
+            return syms.longType;
+        case 'L':
+            {
+                Type t = classSigToType();
+                if (sigp < siglimit && signature[sigp] == '.') {
+                    throw new AssertionError("deprecated inner class signature syntax");
+                }
+                return t;
+            }
+        case 'S':
+            sigp++;
+            return syms.shortType;
+        case 'V':
+            sigp++;
+            return syms.voidType;
+        case 'Z':
+            sigp++;
+            return syms.booleanType;
+        case '[':
+            sigp++;
+            return new ArrayType(sigToType(), syms.arrayClass);
+        default:
+            throw new AssertionError("bad descriptor");
+        }
+    }
+
+    /** Convert class signature to type, where signature is implicit.
+     */
+    Type classSigToType() {
+        if (signature[sigp] != 'L') {
+            throw new AssertionError("bad descriptor");
+        }
+        sigp++;
+        Type outer = Type.noType;
+        int startSbp = sbp;
+
+        while (true) {
+            final byte c = signature[sigp++];
+            switch (c) {
+
+            case ';': {         // end
+                ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
+                                                         startSbp,
+                                                         sbp - startSbp));
+
+                try {
+                    return (outer == Type.noType) ?
+                            t.erasure(types) :
+                        new ClassType(outer, List.<Type>nil(), t);
+                } finally {
+                    sbp = startSbp;
+                }
+            }
+            case '.':
+                //we have seen an enclosing non-generic class
+                if (outer != Type.noType) {
+                    ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
+                                                 startSbp,
+                                                 sbp - startSbp));
+                    outer = new ClassType(outer, List.<Type>nil(), t);
+                }
+                signatureBuffer[sbp++] = (byte)'$';
+                continue;
+            case '/':
+                signatureBuffer[sbp++] = (byte)'.';
+                continue;
+            default:
+                signatureBuffer[sbp++] = c;
+                continue;
+            }
+        }
+    }
+
+    ClassSymbol enterClass(Name name) {
+        return syms.enterClass(currentModule, name);
+    }
+
+    /** Convert (implicit) signature to list of types
+     *  until `terminator' is encountered.
+     */
+    List<Type> sigToTypes(char terminator) {
+        List<Type> head = List.of(null);
+        List<Type> tail = head;
+        while (signature[sigp] != terminator)
+            tail = tail.setTail(List.of(sigToType()));
+        sigp++;
+        return head.tail;
+    }
+
+    public Object convertConstant(JCTree tree, Env<AttrContext> attrEnv, Object constant, ModuleSymbol currentModule) {
+        return convertConstant(tree, attrEnv, constant, currentModule, false);
+    }
+
+    public Object convertConstant(JCTree tree, Env<AttrContext> attrEnv, Object constant, ModuleSymbol currentModule, boolean bsmArg) {
+        if (methodHandleRefClass.isInstance(constant)) {
+            String name = (String)invokeReflectiveMethod(methodHandleRefClass, constant, "name");
+            int refKind = (int)invokeReflectiveMethod(methodHandleRefClass, constant, "refKind");
+            Object owner = invokeReflectiveMethod(methodHandleRefClass, constant, "owner");
+            String ownerDescriptor = (String)invokeReflectiveMethod(classRefClass, owner, "descriptorString");
+            Type ownerType = descriptorToType(ownerDescriptor, currentModule, false);
+            Object mtConstant = invokeReflectiveMethod(methodHandleRefClass, constant, "type");
+            String methodTypeDesc = (String)invokeReflectiveMethod(methodTypeRefClass, mtConstant, "descriptorString");
+            MethodType mType = (MethodType)descriptorToType(
+                    methodTypeDesc, currentModule, true);
+            Symbol refSymbol = getReferenceSymbol(refKind, ownerType.tsym, name, mType);
+            return new Pool.MethodHandle(refKind, refSymbol, types);
+        } else if (methodTypeRefClass.isInstance(constant)) {
+            String descriptor = (String)invokeReflectiveMethod(methodTypeRefClass, constant, "descriptorString");
+            return types.erasure(descriptorToType(descriptor, currentModule, true));
+        } else if (classRefClass.isInstance(constant)) {
+            String descriptor = (String)invokeReflectiveMethod(classRefClass, constant, "descriptorString");
+            if ((boolean)invokeReflectiveMethod(classRefClass, constant, "isPrimitive")) {
+                if (bsmArg) {
+                    Object condy = invokeReflectiveMethod(constablesClass, null, "reduce", new Class<?>[]{constantRefClass}, new Object[]{constant});
+                    return convertConstant(tree, attrEnv, condy, currentModule);
+                } else {
+                    return rs.resolveInternalField(tree, attrEnv, boxedClass(descriptor).type, names.TYPE);
+                }
+            }
+            Type type = descriptorToType(descriptor, currentModule, false);
+            return type.hasTag(ARRAY) ? type : type.tsym;
+        } else if (dynamicConstantClass.isInstance(constant)) {
+            Object classRef =
+                    invokeReflectiveMethod(dynamicConstantClass, constant, "type");
+            String descriptor = (String)invokeReflectiveMethod(classRefClass, classRef, "descriptorString");
+            Type type = descriptorToType(descriptor, attrEnv.enclClass.sym.packge().modle, false);
+            String name = (String)invokeReflectiveMethod(dynamicConstantClass, constant, "name");
+            Object mh = invokeReflectiveMethod(dynamicConstantClass, constant, "bootstrapMethod");
+            Pool.MethodHandle methodHandle = (Pool.MethodHandle)convertConstant(tree, attrEnv, mh, currentModule);
+            Object[] args = (Object[])invokeReflectiveMethod(dynamicConstantClass, constant, "bootstrapArgs");
+            Object[] convertedArgs = convertConstants(tree, attrEnv, args, currentModule, true);
+            return new Pool.ConstantDynamic(names.fromString(name), methodHandle, type, convertedArgs, types);
+        }
+        return constant;
+    }
+    // where
+        private ClassSymbol boxedClass(String descriptor) {
+            switch (descriptor) {
+                case "I": return syms.enterClass(syms.java_base, syms.boxedName[TypeTag.INT.ordinal()]);
+                case "J": return syms.enterClass(syms.java_base, syms.boxedName[TypeTag.LONG.ordinal()]);
+                case "S": return syms.enterClass(syms.java_base, syms.boxedName[TypeTag.SHORT.ordinal()]);
+                case "B": return syms.enterClass(syms.java_base, syms.boxedName[TypeTag.BYTE.ordinal()]);
+                case "C": return syms.enterClass(syms.java_base, syms.boxedName[TypeTag.CHAR.ordinal()]);
+                case "F": return syms.enterClass(syms.java_base, syms.boxedName[TypeTag.FLOAT.ordinal()]);
+                case "D": return syms.enterClass(syms.java_base, syms.boxedName[TypeTag.DOUBLE.ordinal()]);
+                case "Z": return syms.enterClass(syms.java_base, syms.boxedName[TypeTag.BOOLEAN.ordinal()]);
+                case "V": return syms.enterClass(syms.java_base, syms.boxedName[TypeTag.VOID.ordinal()]);
+                default:
+                    throw new AssertionError("invalid primitive descriptor " + descriptor);
+            }
+        }
+
+    public Object[] convertConstants(JCTree tree, Env<AttrContext> attrEnv, Object[] constants, ModuleSymbol currentModule, boolean bsmArgs) {
+        if (constants == null || constants.length == 0) {
+            return constants;
+        }
+        Object[] result = new Object[constants.length];
+        int i = 0;
+        for (Object constant : constants) {
+            result[i] = convertConstant(tree, attrEnv, constant, currentModule, bsmArgs);
+            i++;
+        }
+        return result;
+    }
+
+    public boolean isPrimitiveClassRef(Object constant) {
+        return classRefClass.isInstance(constant) &&
+                (boolean)invokeReflectiveMethod(classRefClass, constant, "isPrimitive");
+    }
+
+    public Class<?> methodHandleRefClass;
+    public Class<?> methodTypeRefClass;
+    public Class<?> classRefClass;
+    public Class<?> constantRefClass;
+    public Class<?> constablesClass;
+    public Class<?> bootstrapSpecifierClass;
+    public Class<?> dynamicConstantClass;
+
+    private Symbol getReferenceSymbol(int refKind, Symbol owner, String name, MethodType methodType) {
+        long flags = refKind == ClassFile.REF_getStatic ||
+                refKind == ClassFile.REF_putStatic ||
+                refKind == ClassFile.REF_invokeStatic ? STATIC : 0;
+        Name symbolName = refKind == ClassFile.REF_newInvokeSpecial ? names.init : names.fromString(name);
+        switch (refKind) {
+            case ClassFile.REF_newInvokeSpecial :
+            case ClassFile.REF_invokeVirtual:
+            case ClassFile.REF_invokeStatic:
+            case ClassFile.REF_invokeSpecial:
+            case ClassFile.REF_invokeInterface:
+                return new MethodSymbol(flags, symbolName, methodType, owner);
+            case ClassFile.REF_putField:
+                return new VarSymbol(flags, symbolName, methodType.argtypes.tail.head, owner);
+            case ClassFile.REF_putStatic:
+                return new VarSymbol(flags, symbolName, methodType.argtypes.head, owner);
+            case ClassFile.REF_getField:
+            case ClassFile.REF_getStatic:
+                return new VarSymbol(flags, symbolName, methodType.restype, owner);
+            default:
+                throw new AssertionError("invalid refKind value " + refKind);
+        }
+    }
+
+    public Object invokeReflectiveMethod(
+            Class<?> hostClass,
+            Object instance,
+            String methodName) {
+        return invokeReflectiveMethod(hostClass, instance, methodName, new Class<?>[0], new Object[0]);
+    }
+
+    public Object invokeReflectiveMethod(
+            Class<?> hostClass,
+            Object instance,
+            String methodName,
+            Class<?>[] argumentTypes,
+            Object[] arguments) {
+        Method theMethod;
+        try {
+            theMethod = hostClass.getDeclaredMethod(methodName, argumentTypes);
+            return theMethod.invoke(instance, arguments);
+        } catch (NoSuchMethodException |
+                SecurityException |
+                IllegalAccessException |
+                IllegalArgumentException |
+                InvocationTargetException ex) {
+            log.error(Errors.ReflectiveError(methodName, hostClass.getCanonicalName()));
+        }
+        return null;
+    }
+
+    public boolean isIntrinsicsIndy(JCTree tree) {
+        return isIntrinsicsIndy(TreeInfo.symbol(tree));
+    }
+
+    public boolean isIntrinsicsIndy(Symbol msym) {
+        return (msym != null &&
+                msym.owner != null &&
+                msym.owner.type != null &&
+                msym.owner.type.tsym == syms.intrinsicsType.tsym &&
+                msym.name == names.invokedynamic);
+    }
+
+    public boolean isIntrinsicsLDCInvocation(Symbol msym) {
+        return (msym != null &&
+                msym.owner != null &&
+                msym.owner.type != null &&
+                msym.owner.type.tsym == syms.intrinsicsType.tsym &&
+                msym.name == names.ldc);
+    }
+
+    /* This method doesnt verify that the annotated field is static it is assumed that
+     * it has to be
+     */
+    public Object foldTrackableField(final JCTree tree, final Env<AttrContext> env) {
+        Symbol sym = TreeInfo.symbol(tree);
+        boolean trackableConstant = sym.attribute(syms.trackableConstantType.tsym) != null &&
+                sym.packge().modle == syms.java_base;
+        if (trackableConstant) {
+            String className = sym.owner.type.tsym.flatName().toString();
+            try {
+                Class<?> constablesClass = Class.forName(className, false, null);
+                MemberKind mKind = getMemberKind(constablesClass, sym.name.toString());
+                if (mKind == MemberKind.METHOD) {
+                    // we are in the middle of a method invocation bail out
+                    return null;
+                }
+                Field theField = constablesClass.getField(sym.name.toString());
+                Object value = theField.get(null);
+                if (value != null) {
+                    return value;
+                }
+            } catch (ClassNotFoundException |
+                    NoSuchFieldException |
+                    IllegalAccessException ex) {
+                log.error(tree, Errors.ReflectiveError(sym.name.toString(), className));
+            }
+        }
+        return null;
+    }
+
+    enum MemberKind {
+        FIELD,
+        METHOD
+    }
+
+    MemberKind getMemberKind(Class<?> aClass, String name) {
+        try {
+            aClass.getField(name);
+            return MemberKind.FIELD;
+        } catch (NoSuchFieldException ex) {
+            return MemberKind.METHOD;
+        }
+    }
+
+    public Object foldMethodInvocation(final JCMethodInvocation tree, final Env<AttrContext> env) {
+        Symbol msym = TreeInfo.symbol(tree.meth);
+        Object constant = null;
+        boolean trackableConstant = msym.attribute(syms.trackableConstantType.tsym) != null &&
+                msym.packge().modle == syms.java_base;
+        boolean isLDC = msym.owner.type.tsym == syms.intrinsicsType.tsym && msym.name == names.ldc;
+        if (trackableConstant || isLDC) {
+            List<Object> constantArgumentValues = extractAllConstansOrNone(tree.args);
+            boolean allConstants = tree.args.isEmpty() == constantArgumentValues.isEmpty();
+            if (allConstants) {
+                if (trackableConstant) {
+                    constant = invokeConstablesMethod(tree, env, constantArgumentValues);
+                } else if (isLDC) {
+                    constant = constantArgumentValues.head;
+                }
+            }
+            if (constant != null) {
+                return constant;
+            }
+        }
+        return null;
+    }
+
+    public List<Object> extractAllConstansOrNone(List<JCExpression> args) {
+        ListBuffer<Object> constantArgumentValues = new ListBuffer<>();
+        for (JCExpression arg: args) {
+            Object argConstant = arg.type.constValue();
+            if (argConstant != null) {
+                constantArgumentValues.add(argConstant);
+            } else {
+                argConstant = constablesVisitor.elementToConstantMap.get(arg) != null ?
+                        constablesVisitor.elementToConstantMap.get(arg) :
+                        constablesVisitor.elementToConstantMap.get(TreeInfo.symbol(arg));
+                if (argConstant != null) {
+                    constantArgumentValues.add(argConstant);
+                } else {
+                    return List.nil();
+                }
+            }
+        }
+        return constantArgumentValues.toList();
+    }
+
+    // where
+        Object invokeConstablesMethod(
+                final JCMethodInvocation tree,
+                final Env<AttrContext> env,
+                List<Object> constantArgumentValues) {
+            String className = "";
+            Name methodName = names.empty;
+            try {
+                Symbol msym = TreeInfo.symbol(tree.meth);
+                JCTree qualifierTree = (tree.meth.hasTag(SELECT))
+                    ? ((JCFieldAccess) tree.meth).selected
+                    : null;
+                Object instance = constablesVisitor.elementToConstantMap.get(qualifierTree);
+                className = msym.owner.type.tsym.flatName().toString();
+                methodName = msym.name;
+                Class<?> constablesClass = Class.forName(className, false, null);
+                MethodType mt = msym.type.asMethodType();
+                java.util.List<Class<?>> argumentTypes =
+                        mt.argtypes.stream().map(t -> getClassForType(t)).collect(List.collector());
+                Method theMethod = constablesClass.getDeclaredMethod(methodName.toString(),
+                        argumentTypes.toArray(new Class<?>[argumentTypes.size()]));
+                int modifiers = theMethod.getModifiers();
+                Object[] args = boxArgs(
+                        mt.argtypes,
+                        constantArgumentValues,
+                        tree.varargsElement);
+                if ((modifiers & Modifier.STATIC) == 0) {
+                    return (instance != null) ? theMethod.invoke(instance, args) : null;
+                }
+                return theMethod.invoke(null, args);
+            } catch (ClassNotFoundException |
+                    SecurityException |
+                    NoSuchMethodException |
+                    IllegalAccessException |
+                    IllegalArgumentException |
+                    InvocationTargetException ex) {
+                log.error(tree, Errors.ReflectiveError(methodName.toString(), className));
+                return null;
+            }
+        }
+
+        Class<?> getClassForType(Type t) {
+            try {
+                if (t.isPrimitiveOrVoid()) {
+                    return t.getTag().theClass;
+                } else {
+                    return Class.forName(getFlatName(t), false, null);
+                }
+            } catch (ClassNotFoundException ex) {
+                return null;
+            }
+        }
+
+        String getFlatName(Type t) {
+            String flatName = t.tsym.flatName().toString();
+            if (t.hasTag(ARRAY)) {
+                flatName = "";
+                while (t.hasTag(ARRAY)) {
+                    ArrayType at = (ArrayType)t;
+                    flatName += "[";
+                    t = at.elemtype;
+                }
+                flatName += "L" + t.tsym.flatName().toString() + ';';
+            }
+            return flatName;
+        }
+
+        Object[] boxArgs(List<Type> parameters, List<Object> _args, Type varargsElement) {
+            java.util.List<Object> result = new java.util.ArrayList<>();
+            List<Object> args = _args;
+            if (parameters.isEmpty()) return new Object[0];
+            while (parameters.tail.nonEmpty()) {
+                result.add(args.head);
+                args = args.tail;
+                parameters = parameters.tail;
+            }
+            if (varargsElement != null) {
+                java.util.List<Object> elems = new java.util.ArrayList<>();
+                while (args.nonEmpty()) {
+                    elems.add(args.head);
+                    args = args.tail;
+                }
+                Class<?> arrayClass = null;
+                try {
+                    arrayClass = Class.forName(getFlatName(varargsElement), false, null);
+                } catch (ClassNotFoundException ex) {}
+                Object arr = Array.newInstance(arrayClass, elems.size());
+                for (int i = 0; i < elems.size(); i++) {
+                    Array.set(arr, i, elems.get(i));
+                }
+                result.add(arr);
+            } else {
+                if (args.length() != 1) throw new AssertionError(args);
+                result.add(args.head);
+            }
+            return result.toArray();
+        }
+}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/SpecialConstantUtils.java	Mon Oct 02 18:27:12 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,403 +0,0 @@
-/*
- * Copyright (c) 2016, 2017, 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 com.sun.tools.javac.util;
-
-import java.lang.reflect.Field;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.nio.charset.Charset;
-
-import com.sun.tools.javac.code.Symbol;
-import com.sun.tools.javac.code.Symbol.ClassSymbol;
-import com.sun.tools.javac.code.Symbol.MethodSymbol;
-import com.sun.tools.javac.code.Symbol.ModuleSymbol;
-import com.sun.tools.javac.code.Symbol.VarSymbol;
-import com.sun.tools.javac.code.Symtab;
-import com.sun.tools.javac.code.Type;
-import com.sun.tools.javac.code.Type.ArrayType;
-import com.sun.tools.javac.code.Type.ClassType;
-import com.sun.tools.javac.code.Type.MethodType;
-import com.sun.tools.javac.code.Types;
-import com.sun.tools.javac.comp.AttrContext;
-import com.sun.tools.javac.comp.Env;
-import com.sun.tools.javac.comp.Resolve;
-import com.sun.tools.javac.jvm.ClassFile;
-import com.sun.tools.javac.jvm.Pool;
-import com.sun.tools.javac.resources.CompilerProperties.Errors;
-import com.sun.tools.javac.tree.JCTree;
-import com.sun.tools.javac.tree.TreeInfo;
-
-import static com.sun.tools.javac.code.Flags.STATIC;
-import static com.sun.tools.javac.code.TypeTag.ARRAY;
-import static com.sun.tools.javac.tree.JCTree.Tag.APPLY;
-
-/** This class is a support tool to parse a method descriptor and obtain a list of the types
- *  represented in it.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- */
-public class SpecialConstantUtils {
-
-    public SpecialConstantUtils(Context context) {
-        types = Types.instance(context);
-        names = Names.instance(context);
-        syms = Symtab.instance(context);
-        rs = Resolve.instance(context);
-        log = Log.instance(context);
-        try {
-            methodHandleRefClass = Class.forName("java.lang.invoke.MethodHandleRef", false, null);
-            methodTypeRefClass = Class.forName("java.lang.invoke.MethodTypeRef", false, null);
-            classRefClass = Class.forName("java.lang.invoke.ClassRef", false, null);
-            constantRefClass = Class.forName("java.lang.invoke.ConstantRef", false, null);
-            constablesClass = Class.forName("java.lang.invoke.Constables", false, null);
-            bootstrapSpecifierClass = Class.forName("java.lang.invoke.BootstrapSpecifier", false, null);
-            dynamicConstantClass = Class.forName("java.lang.invoke.DynamicConstantRef", false, null);
-        } catch (ClassNotFoundException ex) {
-            methodHandleRefClass = null;
-            methodTypeRefClass = null;
-            constantRefClass = null;
-            classRefClass = null;
-            bootstrapSpecifierClass = null;
-            dynamicConstantClass = null;
-            constablesClass = null;
-        }
-    }
-
-    final Types types;
-    final Names names;
-    final Symtab syms;
-    final Resolve rs;
-    final Log log;
-    ModuleSymbol currentModule;
-
-    /** The unread portion of the currently read type is
-     *  signature[sigp..siglimit-1].
-     */
-    byte[] signature;
-    int sigp;
-    int siglimit;
-    boolean sigEnterPhase = false;
-    byte[] signatureBuffer;
-    int sbp;
-
-    /** Convert signature to type, where signature is a byte array segment.
-     */
-    public Type descriptorToType(String descriptor, ModuleSymbol currentModule, boolean methodDescriptor) {
-        byte[] sig = descriptor.getBytes(Charset.forName("UTF-8"));
-        signature = sig;
-        sigp = 0;
-        siglimit = sig.length - 1;
-        sbp = 0;
-        signatureBuffer = new byte[sig.length];
-        this.currentModule = currentModule;
-        try {
-            if (methodDescriptor) {
-                return internalMethodDescriptorToType();
-            } else { // type descriptor
-                return sigToType();
-            }
-        } catch (AssertionError ae) {
-            return Type.noType;
-        }
-    }
-
-    private Type internalMethodDescriptorToType() {
-        if (signature[sigp] != '(') {
-            throw new AssertionError("bad descriptor");
-        }
-        sigp++;
-        List<Type> argtypes = sigToTypes(')');
-        Type restype = sigToType();
-        return new MethodType(argtypes,
-                              restype,
-                              List.nil(),
-                              syms.methodClass);
-    }
-
-    /** Convert signature to type, where signature is implicit.
-     */
-    Type sigToType() {
-        switch ((char) signature[sigp]) {
-        case 'B':
-            sigp++;
-            return syms.byteType;
-        case 'C':
-            sigp++;
-            return syms.charType;
-        case 'D':
-            sigp++;
-            return syms.doubleType;
-        case 'F':
-            sigp++;
-            return syms.floatType;
-        case 'I':
-            sigp++;
-            return syms.intType;
-        case 'J':
-            sigp++;
-            return syms.longType;
-        case 'L':
-            {
-                Type t = classSigToType();
-                if (sigp < siglimit && signature[sigp] == '.') {
-                    throw new AssertionError("deprecated inner class signature syntax");
-                }
-                return t;
-            }
-        case 'S':
-            sigp++;
-            return syms.shortType;
-        case 'V':
-            sigp++;
-            return syms.voidType;
-        case 'Z':
-            sigp++;
-            return syms.booleanType;
-        case '[':
-            sigp++;
-            return new ArrayType(sigToType(), syms.arrayClass);
-        default:
-            throw new AssertionError("bad descriptor");
-        }
-    }
-
-    /** Convert class signature to type, where signature is implicit.
-     */
-    Type classSigToType() {
-        if (signature[sigp] != 'L') {
-            throw new AssertionError("bad descriptor");
-        }
-        sigp++;
-        Type outer = Type.noType;
-        int startSbp = sbp;
-
-        while (true) {
-            final byte c = signature[sigp++];
-            switch (c) {
-
-            case ';': {         // end
-                ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
-                                                         startSbp,
-                                                         sbp - startSbp));
-
-                try {
-                    return (outer == Type.noType) ?
-                            t.erasure(types) :
-                        new ClassType(outer, List.<Type>nil(), t);
-                } finally {
-                    sbp = startSbp;
-                }
-            }
-            case '.':
-                //we have seen an enclosing non-generic class
-                if (outer != Type.noType) {
-                    ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
-                                                 startSbp,
-                                                 sbp - startSbp));
-                    outer = new ClassType(outer, List.<Type>nil(), t);
-                }
-                signatureBuffer[sbp++] = (byte)'$';
-                continue;
-            case '/':
-                signatureBuffer[sbp++] = (byte)'.';
-                continue;
-            default:
-                signatureBuffer[sbp++] = c;
-                continue;
-            }
-        }
-    }
-
-    ClassSymbol enterClass(Name name) {
-        return syms.enterClass(currentModule, name);
-    }
-
-    /** Convert (implicit) signature to list of types
-     *  until `terminator' is encountered.
-     */
-    List<Type> sigToTypes(char terminator) {
-        List<Type> head = List.of(null);
-        List<Type> tail = head;
-        while (signature[sigp] != terminator)
-            tail = tail.setTail(List.of(sigToType()));
-        sigp++;
-        return head.tail;
-    }
-
-    public Object convertConstant(JCTree tree, Env<AttrContext> attrEnv, Object constant, ModuleSymbol currentModule) {
-        return convertConstant(tree, attrEnv, constant, currentModule, false);
-    }
-
-    public Object convertConstant(JCTree tree, Env<AttrContext> attrEnv, Object constant, ModuleSymbol currentModule, boolean bsmArg) {
-        if (methodHandleRefClass.isInstance(constant)) {
-            String name = (String)invokeReflectiveMethod(methodHandleRefClass, constant, "name");
-            int refKind = (int)invokeReflectiveMethod(methodHandleRefClass, constant, "refKind");
-            Object owner = invokeReflectiveMethod(methodHandleRefClass, constant, "owner");
-            String ownerDescriptor = (String)invokeReflectiveMethod(classRefClass, owner, "descriptorString");
-            Type ownerType = descriptorToType(ownerDescriptor, currentModule, false);
-            Object mtConstant = invokeReflectiveMethod(methodHandleRefClass, constant, "type");
-            String methodTypeDesc = (String)invokeReflectiveMethod(methodTypeRefClass, mtConstant, "descriptorString");
-            MethodType mType = (MethodType)descriptorToType(
-                    methodTypeDesc, currentModule, true);
-            Symbol refSymbol = getReferenceSymbol(refKind, ownerType.tsym, name, mType);
-            return new Pool.MethodHandle(refKind, refSymbol, types);
-        } else if (methodTypeRefClass.isInstance(constant)) {
-            String descriptor = (String)invokeReflectiveMethod(methodTypeRefClass, constant, "descriptorString");
-            return types.erasure(descriptorToType(descriptor, currentModule, true));
-        } else if (classRefClass.isInstance(constant)) {
-            String descriptor = (String)invokeReflectiveMethod(classRefClass, constant, "descriptorString");
-            if ((boolean)invokeReflectiveMethod(classRefClass, constant, "isPrimitive")) {
-                if (bsmArg) {
-                    Object condy = invokeReflectiveMethod(constablesClass, null, "reduce", new Class<?>[]{constantRefClass}, new Object[]{constant});
-                    return convertConstant(tree, attrEnv, condy, currentModule);
-                } else {
-                    return rs.resolveInternalField(tree, attrEnv, types.boxedClass(descriptor).type, names.TYPE);
-                }
-            }
-            Type type = descriptorToType(descriptor, currentModule, false);
-            return type.hasTag(ARRAY) ? type : type.tsym;
-        } else if (dynamicConstantClass.isInstance(constant)) {
-            String name = (String)invokeReflectiveMethod(dynamicConstantClass, constant, "name");
-            Object mh = invokeReflectiveMethod(dynamicConstantClass, constant, "bootstrapMethod");
-            Pool.MethodHandle methodHandle = (Pool.MethodHandle)convertConstant(tree, attrEnv, mh, currentModule);
-            Object[] args = (Object[])invokeReflectiveMethod(dynamicConstantClass, constant, "bootstrapArgs");
-            Object[] convertedArgs = convertConstants(tree, attrEnv, args, currentModule, true);
-            return new Pool.ConstantDynamic(names.fromString(name), methodHandle, convertedArgs, types);
-        }
-        return constant;
-    }
-
-    public Object[] convertConstants(JCTree tree, Env<AttrContext> attrEnv, Object[] constants, ModuleSymbol currentModule, boolean bsmArgs) {
-        if (constants == null || constants.length == 0) {
-            return constants;
-        }
-        Object[] result = new Object[constants.length];
-        int i = 0;
-        for (Object constant : constants) {
-            result[i] = convertConstant(tree, attrEnv, constant, currentModule, bsmArgs);
-            i++;
-        }
-        return result;
-    }
-
-    public boolean isPrimitiveClassRef(Object constant) {
-        return classRefClass.isInstance(constant) &&
-                (boolean)invokeReflectiveMethod(classRefClass, constant, "isPrimitive");
-    }
-
-    public Class<?> methodHandleRefClass;
-    public Class<?> methodTypeRefClass;
-    public Class<?> classRefClass;
-    public Class<?> constantRefClass;
-    public Class<?> constablesClass;
-    public Class<?> bootstrapSpecifierClass;
-    public Class<?> dynamicConstantClass;
-
-    private Symbol getReferenceSymbol(int refKind, Symbol owner, String name, MethodType methodType) {
-        long flags = refKind == ClassFile.REF_getStatic ||
-                refKind == ClassFile.REF_putStatic ||
-                refKind == ClassFile.REF_invokeStatic ? STATIC : 0;
-        Name symbolName = refKind == ClassFile.REF_newInvokeSpecial ? names.init : names.fromString(name);
-        switch (refKind) {
-            case ClassFile.REF_newInvokeSpecial :
-            case ClassFile.REF_invokeVirtual:
-            case ClassFile.REF_invokeStatic:
-            case ClassFile.REF_invokeSpecial:
-            case ClassFile.REF_invokeInterface:
-                return new MethodSymbol(flags, symbolName, methodType, owner);
-            case ClassFile.REF_putField:
-                return new VarSymbol(flags, symbolName, methodType.argtypes.tail.head, owner);
-            case ClassFile.REF_putStatic:
-                return new VarSymbol(flags, symbolName, methodType.argtypes.head, owner);
-            case ClassFile.REF_getField:
-            case ClassFile.REF_getStatic:
-                return new VarSymbol(flags, symbolName, methodType.restype, owner);
-            default:
-                throw new AssertionError("invalid refKind value " + refKind);
-        }
-    }
-
-    public Object invokeReflectiveMethod(
-            Class<?> hostClass,
-            Object instance,
-            String methodName) {
-        return invokeReflectiveMethod(hostClass, instance, methodName, new Class<?>[0], new Object[0]);
-    }
-
-    public Object invokeReflectiveMethod(
-            Class<?> hostClass,
-            Object instance,
-            String methodName,
-            Class<?>[] argumentTypes,
-            Object[] arguments) {
-        Method theMethod;
-        try {
-            theMethod = hostClass.getDeclaredMethod(methodName, argumentTypes);
-            return theMethod.invoke(instance, arguments);
-        } catch (NoSuchMethodException |
-                SecurityException |
-                IllegalAccessException |
-                IllegalArgumentException |
-                InvocationTargetException ex) {
-            log.error(Errors.ReflectiveError(methodName, hostClass.getCanonicalName()));
-        }
-        return null;
-    }
-
-    public boolean isIntrinsicsIndy(JCTree tree) {
-        return isIntrinsicsIndy(TreeInfo.symbol(tree));
-    }
-
-    public boolean isIntrinsicsIndy(Symbol msym) {
-        return (msym != null &&
-                msym.owner != null &&
-                msym.owner.type != null &&
-                msym.owner.type.tsym == syms.intrinsicsType.tsym &&
-                msym.name == names.invokedynamic);
-    }
-
-    public boolean isIntrinsicsLDCInvocation(Symbol msym) {
-        return (msym != null &&
-                msym.owner != null &&
-                msym.owner.type != null &&
-                msym.owner.type.tsym == syms.intrinsicsType.tsym &&
-                msym.name == names.ldc);
-    }
-
-    public boolean isIntrinsicsLDCInvocation(JCTree tree) {
-        Symbol msym = TreeInfo.symbol(tree);
-        return (tree.hasTag(APPLY) &&
-                msym != null &&
-                msym.owner != null &&
-                msym.owner.type != null &&
-                msym.owner.type.tsym == syms.intrinsicsType.tsym &&
-                msym.name == names.ldc);
-    }
-}