changeset 48626:a58eab16f75a condy-folding

removing classes NamedClassRef and PrimitiveClassRef, creating a condy for ClassRefs with a primitive descriptor field BSM_PRIMITIVE_CLASS at class SymbolicRefs was made public in order to use it to build the condy for primitive classes some changes to ConstantFoldingHarness to direct the output of the test's class files to test.classes
author vromero
date Sat, 06 Jan 2018 16:57:20 -0500
parents 5c5bc69f593b
children d41afc5e283e
files src/java.base/share/classes/java/lang/sym/ClassRef.java src/java.base/share/classes/java/lang/sym/NamedClassRef.java src/java.base/share/classes/java/lang/sym/PrimitiveClassRef.java src/java.base/share/classes/java/lang/sym/SymbolicRefs.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ConstablesVisitor.java src/jdk.compiler/share/classes/com/sun/tools/javac/util/Constables.java test/langtools/tools/javac/specialConstantFolding/harness/ConstantFoldingHarness.java test/langtools/tools/javac/specialConstantFolding/harness/tests/InstanceTrackableMethodsTest.java
diffstat 8 files changed, 174 insertions(+), 293 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/java/lang/sym/ClassRef.java	Thu Jan 04 19:07:08 2018 -0500
+++ b/src/java.base/share/classes/java/lang/sym/ClassRef.java	Sat Jan 06 16:57:20 2018 -0500
@@ -26,12 +26,32 @@
 
 import java.lang.annotation.Foldable;
 import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Array;
+import java.util.Objects;
 import java.util.Optional;
+import java.util.regex.Pattern;
+import java.util.stream.Stream;
+
+import sun.invoke.util.Wrapper;
+
+import static java.util.Objects.requireNonNull;
+import static java.util.stream.Collectors.joining;
 
 /**
  * A descriptor for a {@linkplain Class} constant.
  */
-public interface ClassRef extends SymbolicRef.WithTypeDescriptor<Class<?>> {
+public class ClassRef implements SymbolicRef.WithTypeDescriptor<Class<?>> {
+    private static final Pattern TYPE_DESC = Pattern.compile("(\\[*)(V|I|J|S|B|C|F|D|Z|L[^/.\\[;][^.\\[;]*;)");
+
+    private final String descriptor;
+
+    private ClassRef(String descriptor) {
+        // @@@ Replace validation with a lower-overhead mechanism than regex
+        if (descriptor == null
+            || !TYPE_DESC.matcher(descriptor).matches())
+            throw new IllegalArgumentException(String.format("%s is not a valid type descriptor", descriptor));
+        this.descriptor = descriptor;
+    }
 
     /**
      * Create a {@linkplain ClassRef} from a dot-separated class name
@@ -42,7 +62,7 @@
      * describe a valid class name
      */
     @Foldable
-    static ClassRef of(String name) {
+    public static ClassRef of(String name) {
         return ClassRef.ofDescriptor("L" + name.replace('.', '/') + ";");
     }
 
@@ -55,7 +75,7 @@
      * @throws IllegalArgumentException if the package name or class name are not in the correct format
      */
     @Foldable
-    static ClassRef of(String packageName, String className) {
+    public static ClassRef of(String packageName, String className) {
         return ofDescriptor("L" + packageName.replace('.', '/') + (packageName.length() > 0 ? "/" : "") + className + ";");
     }
 
@@ -69,13 +89,11 @@
      * describe a valid class descriptor
      */
     @Foldable
-    static ClassRef ofDescriptor(String descriptor) {
-        if (descriptor == null)
-            throw new NullPointerException("descriptor");
-        else if (descriptor.length() == 1)
-            return new PrimitiveClassRef(descriptor);
-        else
-            return new NamedClassRef(descriptor);
+    public static ClassRef ofDescriptor(String descriptor) {
+        requireNonNull(descriptor);
+        if (!TYPE_DESC.matcher(descriptor).matches())
+            throw new IllegalArgumentException(String.format("%s is not a valid type descriptor", descriptor));
+        return new ClassRef(descriptor);
     }
 
     /**
@@ -85,8 +103,8 @@
      * @return a {@linkplain ClassRef} describing an array type
      */
     @Foldable
-    default ClassRef array() {
-        return ClassRef.ofDescriptor("[" + descriptorString());
+    public ClassRef array() {
+        return ClassRef.ofDescriptor("[" + descriptor);
     }
 
     /**
@@ -94,14 +112,25 @@
      * non-array reference type described by this {@linkplain ClassRef}
      */
     @Foldable
-    ClassRef inner(String innerName);
+    public ClassRef inner(String innerName) {
+        if (!descriptor.startsWith("L"))
+            throw new IllegalStateException("Outer class is not a non-array reference type");
+        return ClassRef.ofDescriptor(descriptor.substring(0, descriptor.length() - 1) + "$" + innerName + ";");
+    }
 
     /**
      * Create a {@linkplain ClassRef} describing an inner class of the
      * non-array reference type described by this {@linkplain ClassRef}
      */
     @Foldable
-    ClassRef inner(String firstInnerName, String... moreInnerNames);
+    public ClassRef inner(String firstInnerName, String... moreInnerNames) {
+        if (!descriptor.startsWith("L"))
+            throw new IllegalStateException("Outer class is not a non-array reference type");
+        return moreInnerNames.length == 0
+               ? inner(firstInnerName)
+               : ClassRef.ofDescriptor(descriptor.substring(0, descriptor.length() - 1) + "$" + firstInnerName
+                                       + Stream.of(moreInnerNames).collect(joining("$", "$", "")) + ";");
+    }
 
     /**
      * Returns whether this {@linkplain ClassRef}
@@ -109,8 +138,8 @@
      * @return whether this {@linkplain ClassRef}
      * describes an array type
      */
-    default boolean isArray() {
-        return descriptorString().startsWith("[");
+    public boolean isArray() {
+        return descriptor.startsWith("[");
     }
 
     /**
@@ -119,8 +148,8 @@
      * @return whether this {@linkplain ClassRef}
      * describes a primitive type
      */
-    default boolean isPrimitive() {
-        return descriptorString().length() == 1;
+    public boolean isPrimitive() {
+        return descriptor.length() == 1;
     }
 
     /**
@@ -131,21 +160,93 @@
      * {@linkplain ClassRef}
      */
     @Foldable
-    default ClassRef componentType() {
+    public ClassRef componentType() {
         if (!isArray())
             throw new IllegalStateException();
-        return ClassRef.ofDescriptor(descriptorString().substring(1));
+        return ClassRef.ofDescriptor(descriptor.substring(1));
     }
 
     /**
      * Return the canonical name of the type described by this descriptor
      * @return the canonical name of the type described by this descriptor
      */
-    String canonicalName();
+    public String canonicalName() {
+        if (descriptor.length() == 1)
+            return Wrapper.forBasicType(descriptor.charAt(0)).primitiveSimpleName();
+        else if (descriptor.startsWith("L"))
+            return descriptor.substring(1, descriptor.length() - 1).replace('/', '.');
+        else if (descriptor.startsWith(("["))) {
+            int depth=arrayDepth();
+            ClassRef c = this;
+            for (int i=0; i<depth; i++)
+                c = c.componentType();
+            StringBuilder sb = new StringBuilder(descriptor.length() + 2*depth);
+            sb.append(c.canonicalName());
+            for (int i=0; i<depth; i++)
+                sb.append("[]");
+            return sb.toString();
+        }
+        else
+            throw new IllegalStateException(descriptor);
+    }
+
+    private int arrayDepth() {
+        int depth = 0;
+        while (descriptor.charAt(depth) == '[')
+            depth++;
+        return depth;
+    }
 
     @Override
-    default Optional<? extends SymbolicRef<Class<?>>> toSymbolicRef(MethodHandles.Lookup lookup) {
+    public Class<?> resolveRef(MethodHandles.Lookup lookup) throws ReflectiveOperationException {
+        if (isPrimitive()) {
+            return Wrapper.forBasicType(descriptor.charAt(0)).primitiveType();
+        }
+        else {
+            ClassRef c = this;
+            int depth = arrayDepth();
+            for (int i=0; i<depth; i++)
+                c = c.componentType();
+
+            if (c.descriptor.length() == 1)
+                return Class.forName(descriptor, true, lookup.lookupClass().getClassLoader());
+            else {
+                Class<?> clazz = Class.forName(c.descriptor.substring(1, c.descriptor.length() - 1).replace('/', '.'), true, lookup.lookupClass().getClassLoader());
+                for (int i = 0; i < depth; i++)
+                    clazz = Array.newInstance(clazz, 0).getClass();
+                return clazz;
+            }
+        }
+    }
+
+    @Override
+    @Foldable
+    public String descriptorString() {
+        return descriptor;
+    }
+
+    @Override
+    public Optional<? extends SymbolicRef<Class<?>>> toSymbolicRef(MethodHandles.Lookup lookup) {
         return Optional.of(DynamicConstantRef.<Class<?>>of(SymbolicRefs.BSM_INVOKE)
-                                   .withArgs(SymbolicRefs.MHR_CLASSREF_FACTORY, descriptorString()));
+                                   .withArgs(SymbolicRefs.MHR_CLASSREF_FACTORY, 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.descriptor);
+    }
+
+    @Override
+    public int hashCode() {
+        return descriptor != null ? descriptor.hashCode() : 0;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("ClassRef[%s]", canonicalName());
     }
 }
--- a/src/java.base/share/classes/java/lang/sym/NamedClassRef.java	Thu Jan 04 19:07:08 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,136 +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.annotation.Foldable;
-import java.lang.invoke.MethodHandles;
-import java.lang.reflect.Array;
-import java.util.Objects;
-import java.util.regex.Pattern;
-import java.util.stream.Stream;
-
-import static java.util.stream.Collectors.joining;
-
-/**
- * NamedClassRef
- *
- * @author Brian Goetz
- */
-public final class NamedClassRef implements ClassRef {
-    static final Pattern TYPE_DESC = Pattern.compile("(\\[*)(V|I|J|S|B|C|F|D|Z|L[^/.\\[;][^.\\[;]*;)");
-
-    private final String descriptor;
-
-    NamedClassRef(String descriptor) {
-        if (descriptor == null
-            || !TYPE_DESC.matcher(descriptor).matches())
-            throw new IllegalArgumentException(String.format("%s is not a valid type descriptor", descriptor));
-        this.descriptor = descriptor;
-    }
-
-    /**
-     * Create a {@linkplain ClassRef} describing an inner class of the
-     * non-array reference type described by this {@linkplain ClassRef}
-     */
-    @Foldable
-    public ClassRef inner(String innerName) {
-        if (!descriptor.startsWith("L"))
-            throw new IllegalStateException("Outer class is not a non-array reference type");
-        return ClassRef.ofDescriptor(descriptor.substring(0, descriptor.length() - 1) + "$" + innerName + ";");
-    }
-
-    /**
-     * Create a {@linkplain ClassRef} describing an inner class of the
-     * non-array reference type described by this {@linkplain ClassRef}
-     */
-    @Foldable
-    public ClassRef inner(String firstInnerName, String... moreInnerNames) {
-        if (!descriptor.startsWith("L"))
-            throw new IllegalStateException("Outer class is not a non-array reference type");
-        return moreInnerNames.length == 0
-               ? inner(firstInnerName)
-               : ClassRef.ofDescriptor(descriptor.substring(0, descriptor.length() - 1) + "$" + firstInnerName
-                                       + Stream.of(moreInnerNames).collect(joining("$", "$", "")) + ";");
-    }
-
-    @Override
-    @Foldable
-    public String descriptorString() {
-        return descriptor;
-    }
-
-    /**
-     * Return the canonical name of the type described by this descriptor
-     * @return the canonical name of the type described by this descriptor
-     */
-    public String canonicalName() {
-        // @@@ Arrays?
-        return descriptor.substring(1, descriptor.length() - 1).replace('/', '.');
-    }
-
-    /**
-     * Resolve to a Class
-     * @param lookup the lookup
-     * @return return the class
-     * @throws ReflectiveOperationException exception
-     */
-    public Class<?> resolveRef(MethodHandles.Lookup lookup) throws ReflectiveOperationException {
-        ClassRef comp = this;
-        int depth = 0;
-        while (comp.isArray()) {
-            ++depth;
-            comp = comp.componentType();
-        }
-        String compDescr = comp.descriptorString();
-
-        if (compDescr.length() == 1)
-            return Class.forName(descriptor, true, lookup.lookupClass().getClassLoader());
-        else {
-            Class<?> clazz = Class.forName(compDescr.substring(1, compDescr.length() - 1).replace('/', '.'), true, lookup.lookupClass().getClassLoader());
-            for (int i = 0; i < depth; i++)
-                clazz = Array.newInstance(clazz, 0).getClass();
-            return clazz;
-        }
-    }
-
-    @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(descriptorString(), constant.descriptorString());
-    }
-
-    @Override
-    public int hashCode() {
-        return descriptorString() != null ? descriptorString().hashCode() : 0;
-    }
-
-    @Override
-    public String toString() {
-        return String.format("ClassRef[%s]", descriptorString());
-    }
-}
--- a/src/java.base/share/classes/java/lang/sym/PrimitiveClassRef.java	Thu Jan 04 19:07:08 2018 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +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.annotation.Foldable;
-import java.lang.invoke.MethodHandles;
-import java.util.Objects;
-
-import sun.invoke.util.Wrapper;
-
-/**
- * PrimitiveClassRef
- *
- * @author Brian Goetz
- */
-class PrimitiveClassRef extends DynamicConstantRef<Class<?>> implements ClassRef {
-    private final String descriptor;
-
-    PrimitiveClassRef(String descriptor) {
-        super(SymbolicRefs.BSM_PRIMITIVE_CLASS, checkDescriptor(descriptor), SymbolicRefs.CR_Class);
-        this.descriptor = descriptor;
-    }
-
-    private static String checkDescriptor(String descriptor) {
-        if (descriptor == null
-            || descriptor.length() != 1
-            || "IJCSBFDZV".indexOf(descriptor.charAt(0)) < 0)
-            throw new IllegalArgumentException("Invalid primitive type descriptor " + descriptor);
-        return descriptor;
-    }
-
-    @Override
-    public String canonicalName() {
-        return Wrapper.forBasicType(descriptor.charAt(0)).primitiveSimpleName();
-    }
-
-    @Override
-    @Foldable
-    public String descriptorString() {
-        return descriptor;
-    }
-
-    @Override
-    public ClassRef inner(String innerName) {
-        throw new IllegalStateException("Outer class is not a non-array reference type");
-    }
-
-    @Override
-    public ClassRef inner(String firstInnerName, String... moreInnerNames) {
-        throw new IllegalStateException("Outer class is not a non-array reference type");
-    }
-
-    @Override
-    public Class<?> resolveRef(MethodHandles.Lookup lookup) {
-        return Wrapper.forBasicType(descriptor.charAt(0)).primitiveType();
-    }
-
-    @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(descriptorString(), constant.descriptorString());
-    }
-
-    @Override
-    public int hashCode() {
-        return descriptorString() != null ? descriptorString().hashCode() : 0;
-    }
-
-    @Override
-    public String toString() {
-        return String.format("ClassRef[%s]", descriptorString());
-    }
-}
-
--- a/src/java.base/share/classes/java/lang/sym/SymbolicRefs.java	Thu Jan 04 19:07:08 2018 -0500
+++ b/src/java.base/share/classes/java/lang/sym/SymbolicRefs.java	Sat Jan 06 16:57:20 2018 -0500
@@ -163,7 +163,7 @@
     static final ClassRef CR_ConstantBootstraps = ClassRef.of("java.lang.invoke.ConstantBootstraps");
 
     @Foldable
-    static final MethodHandleRef BSM_PRIMITIVE_CLASS
+    public static final MethodHandleRef BSM_PRIMITIVE_CLASS
             = MethodHandleRef.ofCondyBootstrap(CR_ConstantBootstraps, "primitiveClass", CR_Class);
 
     @Foldable
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ConstablesVisitor.java	Thu Jan 04 19:07:08 2018 -0500
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ConstablesVisitor.java	Sat Jan 06 16:57:20 2018 -0500
@@ -289,7 +289,7 @@
                     if (invocationName.isEmpty()) {
                         log.error(tree.args.tail.head.pos(), Errors.InvocationNameCannotBeEmpty);
                     }
-                    Object mh = constables.invokeReflectiveMethod(constables.bootstrapSpecifierClass,
+                    Object mh = constables.invokeMethodReflectively(constables.bootstrapSpecifierClass,
                             bootstrapSpecifier, "method");
                     Pool.MethodHandle mHandle = (Pool.MethodHandle)constables
                             .convertConstant(tree, attrEnv, mh, attrEnv.enclClass.sym.packge().modle);
@@ -309,7 +309,7 @@
                     ListBuffer<Type> arguments = new ListBuffer<>();
                     tree.args = tree.args.tail.tail;
                     tree.args.forEach(arg -> arguments.add(arg.type));
-                    Object[] bsmArgs = (Object[])constables.invokeReflectiveMethod(constables.bootstrapSpecifierClass, bootstrapSpecifier, "arguments");
+                    Object[] bsmArgs = (Object[])constables.invokeMethodReflectively(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(
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Constables.java	Thu Jan 04 19:07:08 2018 -0500
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Constables.java	Sat Jan 06 16:57:20 2018 -0500
@@ -88,18 +88,18 @@
             methodHandleRefClass = Class.forName("java.lang.sym.MethodHandleRef", false, null);
             methodTypeRefClass = Class.forName("java.lang.sym.MethodTypeRef", false, null);
             classRefClass = Class.forName("java.lang.sym.ClassRef", false, null);
-            namedClassRefClass = Class.forName("java.lang.sym.NamedClassRef", false, null);
             constantRefClass = Class.forName("java.lang.sym.SymbolicRef", false, null);
             bootstrapSpecifierClass = Class.forName("java.lang.sym.BootstrapSpecifier", false, null);
             dynamicConstantClass = Class.forName("java.lang.sym.DynamicConstantRef", false, null);
+            symRefs = Class.forName("java.lang.sym.SymbolicRefs", false, null);
         } catch (ClassNotFoundException ex) {
             methodHandleRefClass = null;
             methodTypeRefClass = null;
             constantRefClass = null;
             classRefClass = null;
-            namedClassRefClass = null;
             bootstrapSpecifierClass = null;
             dynamicConstantClass = null;
+            symRefs = null;
         }
     }
 
@@ -271,13 +271,13 @@
 
     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");
+            String name = (String)invokeMethodReflectively(methodHandleRefClass, constant, "name");
+            int refKind = (int)invokeMethodReflectively(methodHandleRefClass, constant, "refKind");
+            Object owner = invokeMethodReflectively(methodHandleRefClass, constant, "owner");
+            String ownerDescriptor = (String)invokeMethodReflectively(classRefClass, owner, "descriptorString");
             Type ownerType = descriptorToType(ownerDescriptor, currentModule, false);
-            Object mtConstant = invokeReflectiveMethod(methodHandleRefClass, constant, "type");
-            String methodTypeDesc = (String)invokeReflectiveMethod(methodTypeRefClass, mtConstant, "descriptorString");
+            Object mtConstant = invokeMethodReflectively(methodHandleRefClass, constant, "type");
+            String methodTypeDesc = (String)invokeMethodReflectively(methodTypeRefClass, mtConstant, "descriptorString");
             MethodType mType = (MethodType)descriptorToType(
                     methodTypeDesc, currentModule, true);
             Symbol refSymbol = getReferenceSymbol(refKind, ownerType.tsym, name, mType);
@@ -295,10 +295,16 @@
                     new Pool.MethodHandle.DumbMethodHandleCheckHelper(refKind, refSymbol));
             return mHandle;
         } else if (methodTypeRefClass.isInstance(constant)) {
-            String descriptor = (String)invokeReflectiveMethod(methodTypeRefClass, constant, "descriptorString");
+            String descriptor = (String)invokeMethodReflectively(methodTypeRefClass, constant, "descriptorString");
             return types.erasure(descriptorToType(descriptor, currentModule, true));
-        } else if (namedClassRefClass.isInstance(constant)) {
-            String descriptor = (String)invokeReflectiveMethod(classRefClass, constant, "descriptorString");
+        } else if (classRefClass.isInstance(constant)) {
+            String descriptor = (String)invokeMethodReflectively(classRefClass, constant, "descriptorString");
+            if (descriptor.length() == 1) {
+                Object BSM_PRIMITIVE_CLASS = getFieldValueReflectively(symRefs, null, "BSM_PRIMITIVE_CLASS");
+                Pool.MethodHandle methodHandle = (Pool.MethodHandle)convertConstant(tree, attrEnv,
+                        BSM_PRIMITIVE_CLASS, currentModule);
+                return new Pool.ConstantDynamic(names.fromString(descriptor), methodHandle, new Object[0], types);
+            }
             Type type = descriptorToType(descriptor, currentModule, false);
             Symbol symToLoad;
             if (!type.hasTag(ARRAY)) {
@@ -318,13 +324,13 @@
             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");
+                    invokeMethodReflectively(dynamicConstantClass, constant, "type");
+            String descriptor = (String)invokeMethodReflectively(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");
+            String name = (String)invokeMethodReflectively(dynamicConstantClass, constant, "name");
+            Object mh = invokeMethodReflectively(dynamicConstantClass, constant, "bootstrapMethod");
             Pool.MethodHandle methodHandle = (Pool.MethodHandle)convertConstant(tree, attrEnv, mh, currentModule);
-            Object[] args = (Object[])invokeReflectiveMethod(dynamicConstantClass, constant, "bootstrapArgs");
+            Object[] args = (Object[])invokeMethodReflectively(dynamicConstantClass, constant, "bootstrapArgs");
             Object[] convertedArgs = convertConstants(tree, attrEnv, args, currentModule, true);
             return new Pool.ConstantDynamic(names.fromString(name), methodHandle, type, convertedArgs, types);
         }
@@ -389,10 +395,10 @@
     public Class<?> methodHandleRefClass;
     public Class<?> methodTypeRefClass;
     public Class<?> classRefClass;
-    public Class<?> namedClassRefClass;
     public Class<?> constantRefClass;
     public Class<?> bootstrapSpecifierClass;
     public Class<?> dynamicConstantClass;
+    public Class<?> symRefs;
 
     private Symbol getReferenceSymbol(int refKind, Symbol owner, String name, MethodType methodType) {
         long flags = refKind == ClassFile.REF_getStatic ||
@@ -418,14 +424,14 @@
         }
     }
 
-    public Object invokeReflectiveMethod(
+    public Object invokeMethodReflectively(
             Class<?> hostClass,
             Object instance,
             String methodName) {
-        return invokeReflectiveMethod(hostClass, instance, methodName, new Class<?>[0], new Object[0]);
+        return invokeMethodReflectively(hostClass, instance, methodName, new Class<?>[0], new Object[0]);
     }
 
-    public Object invokeReflectiveMethod(
+    public Object invokeMethodReflectively(
             Class<?> hostClass,
             Object instance,
             String methodName,
@@ -486,20 +492,28 @@
                     // 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) {
+                return getFieldValueReflectively(constablesClass, null, sym.name.toString());
+            } catch (ClassNotFoundException ex) {
                 log.error(tree, Errors.ReflectiveError(sym.name.toString(), className, ex.getCause().getLocalizedMessage()));
             }
         }
         return null;
     }
 
+    Object getFieldValueReflectively(Class<?> hostClass, Object instance, String fieldName) {
+        try {
+            return hostClass.getField(fieldName).get(instance);
+        } catch (NoSuchFieldException | IllegalAccessException ex) {
+            Throwable e = (ex.getCause() == null) ? ex : ex.getCause();
+            String msg = e.getLocalizedMessage();
+            if (msg == null)
+                msg = e.toString();
+            log.error(Errors.ReflectiveError(fieldName, hostClass.getCanonicalName(), msg));
+            e.printStackTrace(System.err);
+        }
+        return null;
+    }
+
     enum MemberKind {
         FIELD,
         METHOD
--- a/test/langtools/tools/javac/specialConstantFolding/harness/ConstantFoldingHarness.java	Thu Jan 04 19:07:08 2018 -0500
+++ b/test/langtools/tools/javac/specialConstantFolding/harness/ConstantFoldingHarness.java	Sat Jan 06 16:57:20 2018 -0500
@@ -63,6 +63,7 @@
 
     static final JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
     static final StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
+    static final String testOut = System.getProperty("test.classes");
 
     public static void main(String[] args) throws Throwable {
         boolean anyTest = false;
@@ -71,7 +72,7 @@
             fm.setLocation(SOURCE_PATH, Arrays.asList(new File(testDir, "tests")));
 
             // Make sure classes are written to scratch dir.
-            fm.setLocation(CLASS_OUTPUT, Arrays.asList(new File(".")));
+            fm.setLocation(CLASS_OUTPUT, Arrays.asList(new File(testOut)));
             for (JavaFileObject jfo : fm.list(SOURCE_PATH, "", Collections.singleton(SOURCE), true)) {
                 anyTest = true;
                 new ConstantFoldingHarness(jfo).checkAndExecute();
@@ -122,7 +123,7 @@
         }
 
         File javaFile = new File(jfo.getName());
-        File classFile = new File(javaFile.getName().replace(".java", ".class"));
+        File classFile = new File(testOut, javaFile.getName().replace(".java", ".class"));
         checkClassFile(classFile);
 
         //check all candidates have been used up
@@ -137,7 +138,7 @@
             System.err.println("executing the test case");
             new JavaTask(tb)
                     .includeStandardOptions(false)
-                    .classpath(System.getProperty("user.dir"))
+                    .classpath(testOut)
                     .vmOptions("--add-exports", "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED")
                     .className(classFile.getName().replace(".class", ""))
                     .run();
--- a/test/langtools/tools/javac/specialConstantFolding/harness/tests/InstanceTrackableMethodsTest.java	Thu Jan 04 19:07:08 2018 -0500
+++ b/test/langtools/tools/javac/specialConstantFolding/harness/tests/InstanceTrackableMethodsTest.java	Sat Jan 06 16:57:20 2018 -0500
@@ -24,7 +24,7 @@
     }
 
     @InstructionInfo(bytecodePosition=6, values={"CONSTANT_Class_info", "[Ljava/lang/String;"})
-    @InstructionInfo(bytecodePosition=16, values={"CONSTANT_Class_info", "[Ljava/lang/String;"})
+    @InstructionInfo(bytecodePosition=14, values={"CONSTANT_Class_info", "[Ljava/lang/String;"})
     void test2() {
         ClassRef stringClass = ClassRef.ofDescriptor("Ljava/lang/String;");
         Class<?> stringArrClass = ldc(stringClass.array());