changeset 50339:be1ff3649a9c condy-folding

Clean up canonicalization mechanism; undo some refactorings that caused bootstrap errors
author briangoetz
date Fri, 20 Apr 2018 16:45:02 -0400
parents 0d1b8810b899
children b1d3c727cf5b
files src/java.base/share/classes/java/lang/invoke/constant/ConstantClassDesc.java src/java.base/share/classes/java/lang/invoke/constant/ConstantDescs.java src/java.base/share/classes/java/lang/invoke/constant/ConstantMethodHandleDesc.java src/java.base/share/classes/java/lang/invoke/constant/ConstantMethodTypeDesc.java src/java.base/share/classes/java/lang/invoke/constant/DynamicCallSiteDesc.java src/java.base/share/classes/java/lang/invoke/constant/DynamicConstantDesc.java src/java.base/share/classes/java/lang/invoke/constant/EnumDesc.java test/jdk/java/lang/invoke/constant/ClassRefTest.java test/jdk/java/lang/invoke/constant/MethodHandleRefTest.java
diffstat 9 files changed, 109 insertions(+), 57 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/java/lang/invoke/constant/ConstantClassDesc.java	Thu Apr 19 17:38:29 2018 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/constant/ConstantClassDesc.java	Fri Apr 20 16:45:02 2018 -0400
@@ -32,6 +32,7 @@
 
 import jdk.internal.lang.annotation.Foldable;
 
+import static java.lang.invoke.constant.ConstantDescs.BSM_CLASSDESC;
 import static java.lang.invoke.constant.ConstantDescs.CR_ClassDesc;
 import static java.lang.invoke.constant.ConstantDescs.CR_String;
 import static java.lang.invoke.constant.ConstantUtils.dropFirstAndLastChar;
@@ -45,9 +46,6 @@
  */
 public class ConstantClassDesc implements ClassDesc {
     @Foldable
-    private static final ConstantMethodHandleDesc BSM_CLASSDESC
-            = ConstantDescs.ofConstantBootstrap(ClassDesc.of("java.lang.invoke.constant", "ConstantClassDesc"),
-                                                "constantBootstrap", CR_ClassDesc, CR_String);
     private static final Pattern TYPE_DESC = Pattern.compile("(\\[*)(V|I|J|S|B|C|F|D|Z|L[^/.\\[;][^.\\[;]*;)");
 
     private final String descriptor;
--- a/src/java.base/share/classes/java/lang/invoke/constant/ConstantDescs.java	Thu Apr 19 17:38:29 2018 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/constant/ConstantDescs.java	Fri Apr 20 16:45:02 2018 -0400
@@ -345,6 +345,30 @@
             = MethodHandleDesc.of(MethodHandleDesc.Kind.STATIC, CR_VarHandleDesc, "ofArray",
                                   CR_VarHandleDesc, CR_ClassDesc);
 
+    static final ConstantMethodHandleDesc BSM_CLASSDESC
+            = ConstantDescs.ofConstantBootstrap(ClassDesc.of("java.lang.invoke.constant", "ConstantClassDesc"),
+                                                "constantBootstrap", CR_ClassDesc, CR_String);
+
+    static final ConstantMethodHandleDesc BSM_METHODTYPEDESC
+            = ConstantDescs.ofConstantBootstrap(ClassDesc.of("java.lang.invoke.constant", "ConstantMethodTypeDesc"),
+                                                "constantBootstrap", CR_MethodTypeDesc, CR_String);
+
+    static final ConstantMethodHandleDesc BSM_METHODHANDLEDESC
+            = ConstantDescs.ofConstantBootstrap(ClassDesc.of("java.lang.invoke.constant", "ConstantMethodHandleDesc"),
+                                                "constantBootstrap", CR_MethodHandleDesc,
+                                                CR_String, CR_String, CR_String, CR_String);
+
+    static final ConstantMethodHandleDesc BSM_ENUMDESC
+            = ConstantDescs.ofConstantBootstrap(ClassDesc.of("java.lang.invoke.constant", "EnumDesc"),
+                                                "constantBootstrap", CR_EnumDesc, CR_String, CR_String);
+
+    static final ConstantMethodHandleDesc BSM_DYNAMICCONSTANTDESC
+            = ConstantDescs.ofConstantBootstrap(ClassDesc.of("java.lang.invoke.constant", "DynamicConstantDesc"),
+                                                "constantBootstrap",
+                                                CR_DynamicConstantDesc,
+                                                CR_String, CR_String, CR_String, CR_String, CR_String, CR_ConstantDesc.array());
+
+
     /**
      * Return a {@link MethodHandleDesc} corresponding to a bootstrap method for
      * an {@code invokedynamic} callsite, which is a static method whose leading
--- a/src/java.base/share/classes/java/lang/invoke/constant/ConstantMethodHandleDesc.java	Thu Apr 19 17:38:29 2018 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/constant/ConstantMethodHandleDesc.java	Fri Apr 20 16:45:02 2018 -0400
@@ -33,8 +33,8 @@
 
 import jdk.internal.lang.annotation.Foldable;
 
+import static java.lang.invoke.constant.ConstantDescs.BSM_METHODHANDLEDESC;
 import static java.lang.invoke.constant.ConstantDescs.CR_MethodHandleDesc;
-import static java.lang.invoke.constant.ConstantDescs.CR_String;
 import static java.lang.invoke.constant.ConstantUtils.validateClassOrInterface;
 import static java.lang.invoke.constant.ConstantUtils.validateMemberName;
 import static java.lang.invoke.constant.MethodHandleDesc.Kind.CONSTRUCTOR;
@@ -46,11 +46,6 @@
  * a {@code Constant_MethodHandle_info} entry in the constant pool of a classfile.
  */
 public class ConstantMethodHandleDesc implements MethodHandleDesc {
-    @Foldable
-    private static final ConstantMethodHandleDesc BSM_METHODHANDLEDESC
-            = ConstantDescs.ofConstantBootstrap(ClassDesc.of("java.lang.invoke.constant", "ConstantMethodHandleDesc"),
-                                                "constantBootstrap", CR_MethodHandleDesc,
-                                                CR_String, CR_String, CR_String, CR_String);
 
     private final Kind kind;
     private final ClassDesc owner;
@@ -73,7 +68,6 @@
      * is not {@code void}
      */
     ConstantMethodHandleDesc(Kind kind, ClassDesc owner, String name, MethodTypeDesc type) {
-        super();
         if (kind == CONSTRUCTOR)
             name = "<init>";
 
@@ -215,7 +209,7 @@
     public static MethodHandleDesc constantBootstrap(MethodHandles.Lookup lookup, String name, Class<ClassDesc> clazz,
                                                      String bsmKindName, String memberOwner, String memberName, String memberType) {
         return MethodHandleDesc.of(MethodHandleDesc.Kind.valueOf(bsmKindName),
-                                   ClassDesc.ofDescriptor(memberOwner), name,
+                                   ClassDesc.ofDescriptor(memberOwner), memberName,
                                    MethodTypeDesc.ofDescriptor(memberType));
     }
 
--- a/src/java.base/share/classes/java/lang/invoke/constant/ConstantMethodTypeDesc.java	Thu Apr 19 17:38:29 2018 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/constant/ConstantMethodTypeDesc.java	Fri Apr 20 16:45:02 2018 -0400
@@ -35,6 +35,7 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import static java.lang.invoke.constant.ConstantDescs.BSM_METHODTYPEDESC;
 import static java.lang.invoke.constant.ConstantDescs.CR_MethodTypeDesc;
 import static java.lang.invoke.constant.ConstantDescs.CR_String;
 import static java.util.Objects.requireNonNull;
@@ -45,10 +46,6 @@
  * {@code Constant_MethodType_info} entry in the constant pool of a classfile.
  */
 public final class ConstantMethodTypeDesc implements MethodTypeDesc {
-    @Foldable
-    private static final ConstantMethodHandleDesc BSM_METHODTYPEDESC
-            = ConstantDescs.ofConstantBootstrap(ClassDesc.of("java.lang.invoke.constant", "ConstantMethodTypeDesc"),
-                                                "constantBootstrap", CR_MethodTypeDesc, CR_String);
 
     private static final Pattern TYPE_DESC = Pattern.compile("(\\[*)(V|I|J|S|B|C|F|D|Z|L[^/.\\[;][^.\\[;]*;)");
     private static final Pattern pattern = Pattern.compile("\\((.*)\\)(.*)");
--- a/src/java.base/share/classes/java/lang/invoke/constant/DynamicCallSiteDesc.java	Thu Apr 19 17:38:29 2018 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/constant/DynamicCallSiteDesc.java	Fri Apr 20 16:45:02 2018 -0400
@@ -95,6 +95,7 @@
      * @param bootstrapArgs {@link ConstantDesc}s describing the static arguments
      *                      to the bootstrap, that would appear in the
      *                      {@code BootstrapMethods} attribute
+     * @return the nominal descriptor
      * @throws NullPointerException if any parameter is null
      * @throws IllegalArgumentException if the invocation name has the incorrect
      * format
@@ -136,6 +137,7 @@
      * @param invocationType a {@link MethodTypeDesc} describing the invocation
      *                       type that would appear in the {@code NameAndType}
      *                       operand of the {@code invokedynamic}
+     * @return the nominal descriptor
      * @throws NullPointerException if any parameter is null
      * @throws IllegalArgumentException if the invocation name has the incorrect
      * format
--- a/src/java.base/share/classes/java/lang/invoke/constant/DynamicConstantDesc.java	Thu Apr 19 17:38:29 2018 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/constant/DynamicConstantDesc.java	Fri Apr 20 16:45:02 2018 -0400
@@ -37,9 +37,13 @@
 
 import jdk.internal.lang.annotation.Foldable;
 
+import static java.lang.invoke.constant.ConstantDescs.BSM_DYNAMICCONSTANTDESC;
+import static java.lang.invoke.constant.ConstantDescs.CR_Class;
 import static java.lang.invoke.constant.ConstantDescs.CR_ConstantDesc;
 import static java.lang.invoke.constant.ConstantDescs.CR_DynamicConstantDesc;
+import static java.lang.invoke.constant.ConstantDescs.CR_Enum;
 import static java.lang.invoke.constant.ConstantDescs.CR_String;
+import static java.lang.invoke.constant.ConstantDescs.CR_VarHandle;
 import static java.lang.invoke.constant.ConstantUtils.validateMemberName;
 import static java.util.Objects.requireNonNull;
 import static java.util.stream.Collectors.joining;
@@ -57,33 +61,18 @@
 public abstract class DynamicConstantDesc<T>
         implements ConstantDesc<T>, Constable<ConstantDesc<T>> {
 
-    @Foldable
-    private static final ConstantMethodHandleDesc BSM_DYNAMICCONSTANTDESC
-            = ConstantDescs.ofConstantBootstrap(ClassDesc.of("java.lang.invoke.constant", "DynamicConstantDesc"),
-                                                "constantBootstrap",
-                                                CR_DynamicConstantDesc,
-                                                CR_String, CR_String, CR_String, CR_String, CR_String, CR_ConstantDesc.array());
-
     private final ConstantMethodHandleDesc bootstrapMethod;
     private final ConstantDesc<?>[] bootstrapArgs;
     private final String constantName;
     private final ClassDesc constantType;
 
-    @SuppressWarnings("rawtypes")
-    private static final Map<MethodHandleDesc, Function<DynamicConstantDesc, ConstantDesc<?>>> canonicalMap
-            = Map.ofEntries(Map.entry(ConstantDescs.BSM_PRIMITIVE_CLASS, d -> ClassDesc.ofDescriptor(d.constantName)),
-                            Map.entry(ConstantDescs.BSM_ENUM_CONSTANT, d -> EnumDesc.of(d.constantType, d.constantName)),
-                            Map.entry(ConstantDescs.BSM_NULL_CONSTANT, d -> ConstantDescs.NULL),
-                            Map.entry(ConstantDescs.BSM_VARHANDLE_STATIC_FIELD,
-                                      d -> VarHandleDesc.ofStaticField((ClassDesc) d.bootstrapArgs[0],
-                                                                       (String) d.bootstrapArgs[1],
-                                                                       (ClassDesc) d.bootstrapArgs[2])),
-                            Map.entry(ConstantDescs.BSM_VARHANDLE_FIELD,
-                                      d -> VarHandleDesc.ofField((ClassDesc) d.bootstrapArgs[0],
-                                                                 (String) d.bootstrapArgs[1],
-                                                                 (ClassDesc) d.bootstrapArgs[2])),
-                            Map.entry(ConstantDescs.BSM_VARHANDLE_ARRAY,
-                                      d -> VarHandleDesc.ofArray((ClassDesc) d.bootstrapArgs[0]))
+    private static final Map<MethodHandleDesc, Function<DynamicConstantDesc<?>, ConstantDesc<?>>> canonicalMap
+            = Map.ofEntries(Map.entry(ConstantDescs.BSM_PRIMITIVE_CLASS, DynamicConstantDesc::canonicalizePrimitiveClass),
+                            Map.entry(ConstantDescs.BSM_ENUM_CONSTANT, DynamicConstantDesc::canonicalizeEnum),
+                            Map.entry(ConstantDescs.BSM_NULL_CONSTANT, DynamicConstantDesc::canonicalizeNull),
+                            Map.entry(ConstantDescs.BSM_VARHANDLE_STATIC_FIELD, DynamicConstantDesc::canonicalizeStaticFieldVarHandle),
+                            Map.entry(ConstantDescs.BSM_VARHANDLE_FIELD, DynamicConstantDesc::canonicalizeFieldVarHandle),
+                            Map.entry(ConstantDescs.BSM_VARHANDLE_ARRAY, DynamicConstantDesc::canonicalizeArrayVarHandle)
     );
 
     /**
@@ -172,19 +161,7 @@
                                                  ClassDesc constantType,
                                                  ConstantDesc<?>[] bootstrapArgs) {
         return DynamicConstantDesc.<T>of(bootstrapMethod, constantName, constantType, bootstrapArgs)
-                .canonicalize();
-    }
-
-    private ConstantDesc<T> canonicalize() {
-        // @@@ Existing map-based approach is cute but not very robust; need to add more checking of target DCDesc
-        @SuppressWarnings("rawtypes")
-        Function<DynamicConstantDesc, ConstantDesc<?>> f = canonicalMap.get(bootstrapMethod);
-        if (f != null) {
-            @SuppressWarnings("unchecked")
-            ConstantDesc<T> converted = (ConstantDesc<T>) f.apply(this);
-            return converted;
-        }
-        return this;
+                .tryCanonicalize();
     }
 
     /**
@@ -212,7 +189,7 @@
                                                String constantName,
                                                ClassDesc constantType,
                                                ConstantDesc<?>[] bootstrapArgs) {
-        return new DynamicConstantDesc<T>(bootstrapMethod, constantName, constantType, bootstrapArgs) { };
+        return new DynamicConstantDesc<>(bootstrapMethod, constantName, constantType, bootstrapArgs) {};
     }
 
     /**
@@ -442,6 +419,68 @@
 
     }
 
+    private ConstantDesc<T> tryCanonicalize() {
+        Function<DynamicConstantDesc<?>, ConstantDesc<?>> f = canonicalMap.get(bootstrapMethod);
+        if (f != null) {
+            try {
+                @SuppressWarnings("unchecked")
+                ConstantDesc<T> converted = (ConstantDesc<T>) f.apply(this);
+                return converted;
+            }
+            catch (Throwable t) {
+                return this;
+            }
+        }
+        return this;
+    }
+
+    private static ConstantDesc<?> canonicalizeNull(DynamicConstantDesc<?> desc) {
+        if (desc.bootstrapArgs.length != 0)
+            return desc;
+        return ConstantDescs.NULL;
+    }
+
+    private static ConstantDesc<?> canonicalizeEnum(DynamicConstantDesc<?> desc) {
+        if (desc.bootstrapArgs.length != 0
+            || !desc.constantType().equals(CR_Enum)
+            || desc.constantName == null)
+            return desc;
+        return EnumDesc.of(desc.constantType, desc.constantName);
+    }
+
+    private static ConstantDesc<?> canonicalizePrimitiveClass(DynamicConstantDesc<?> desc) {
+        if (desc.bootstrapArgs.length != 0
+            || !desc.constantType().equals(CR_Class)
+            || desc.constantName == null)
+            return desc;
+        return ClassDesc.ofDescriptor(desc.constantName);
+    }
+
+    private static ConstantDesc<?> canonicalizeStaticFieldVarHandle(DynamicConstantDesc<?> desc) {
+        if (desc.bootstrapArgs.length != 3
+            || !desc.constantType().equals(CR_VarHandle))
+            return desc;
+        return VarHandleDesc.ofStaticField((ClassDesc) desc.bootstrapArgs[0],
+                                           (String) desc.bootstrapArgs[1],
+                                           (ClassDesc) desc.bootstrapArgs[2]);
+    }
+
+    private static ConstantDesc<?> canonicalizeFieldVarHandle(DynamicConstantDesc<?> desc) {
+        if (desc.bootstrapArgs.length != 3
+            || !desc.constantType().equals(CR_VarHandle))
+            return desc;
+        return VarHandleDesc.ofField((ClassDesc) desc.bootstrapArgs[0],
+                                     (String) desc.bootstrapArgs[1],
+                                     (ClassDesc) desc.bootstrapArgs[2]);
+    }
+
+    private static ConstantDesc<?> canonicalizeArrayVarHandle(DynamicConstantDesc<?> desc) {
+        if (desc.bootstrapArgs.length != 1
+            || !desc.constantType().equals(CR_VarHandle))
+            return desc;
+        return VarHandleDesc.ofArray((ClassDesc) desc.bootstrapArgs[0]);
+    }
+
     @Override
     public final boolean equals(Object o) {
         if (this == o) return true;
--- a/src/java.base/share/classes/java/lang/invoke/constant/EnumDesc.java	Thu Apr 19 17:38:29 2018 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/constant/EnumDesc.java	Fri Apr 20 16:45:02 2018 -0400
@@ -29,6 +29,7 @@
 import java.lang.invoke.MethodHandles;
 import java.util.Optional;
 
+import static java.lang.invoke.constant.ConstantDescs.BSM_ENUMDESC;
 import static java.lang.invoke.constant.ConstantDescs.CR_EnumDesc;
 import static java.lang.invoke.constant.ConstantDescs.CR_String;
 import static java.lang.invoke.constant.ConstantUtils.validateMemberName;
@@ -43,11 +44,6 @@
 public final class EnumDesc<E extends Enum<E>>
         extends DynamicConstantDesc<E> {
 
-    @Foldable
-    private static final ConstantMethodHandleDesc BSM_ENUMDESC
-            = ConstantDescs.ofConstantBootstrap(ClassDesc.of("java.lang.invoke.constant", "EnumDesc"),
-                                                "constantBootstrap", CR_EnumDesc, CR_String, CR_String);
-
     /**
      * Construct a nominal descriptor for the specified {@code enum} class and name.
      *
--- a/test/jdk/java/lang/invoke/constant/ClassRefTest.java	Thu Apr 19 17:38:29 2018 -0400
+++ b/test/jdk/java/lang/invoke/constant/ClassRefTest.java	Fri Apr 20 16:45:02 2018 -0400
@@ -43,6 +43,7 @@
 
 /**
  * @test
+ * @compile -XDfolding=false ClassRefTest.java
  * @run testng ClassRefTest
  * @summary unit tests for java.lang.invoke.constant.ClassRef
  */
--- a/test/jdk/java/lang/invoke/constant/MethodHandleRefTest.java	Thu Apr 19 17:38:29 2018 -0400
+++ b/test/jdk/java/lang/invoke/constant/MethodHandleRefTest.java	Fri Apr 20 16:45:02 2018 -0400
@@ -57,8 +57,9 @@
 
 /**
  * @test
+ * @compile -XDfolding=false MethodHandleRefTest.java
  * @run testng MethodHandleRefTest
- * @summary unit tests for java.lang.invoke.constant.MethodHandleRefTest
+ * @summary unit tests for java.lang.invoke.constant.MethodHandleDesc
  */
 @Test
 public class MethodHandleRefTest extends SymbolicRefTest {