changeset 49318:c4453cddffe1 condy-folding

Better toString() and toConstantRef() implementations
author briangoetz
date Mon, 05 Mar 2018 18:02:36 -0500
parents 3f0706d6e402
children 36326b5ae7a1
files src/java.base/share/classes/java/lang/sym/ConstantClassRef.java src/java.base/share/classes/java/lang/sym/ConstantMethodHandleRef.java src/java.base/share/classes/java/lang/sym/ConstantMethodTypeRef.java src/java.base/share/classes/java/lang/sym/ConstantRefs.java src/java.base/share/classes/java/lang/sym/DynamicConstantRef.java src/java.base/share/classes/java/lang/sym/EnumRef.java src/java.base/share/classes/java/lang/sym/MethodHandleRef.java src/java.base/share/classes/java/lang/sym/RefBootstraps.java src/java.base/share/classes/java/lang/sym/package-info.java
diffstat 9 files changed, 196 insertions(+), 40 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/java/lang/sym/ConstantClassRef.java	Mon Mar 05 17:41:29 2018 -0500
+++ b/src/java.base/share/classes/java/lang/sym/ConstantClassRef.java	Mon Mar 05 18:02:36 2018 -0500
@@ -93,8 +93,7 @@
 
     @Override
     public Optional<? extends ConstantRef<? super ConstantRef<Class<?>>>> toConstantRef(MethodHandles.Lookup lookup) {
-        return DynamicConstantRef.symbolizeHelper(lookup, ConstantRefs.MHR_CLASSREF_FACTORY,
-                                                  CR_ClassRef, descriptorString());
+        return Optional.of(DynamicConstantRef.of(RefBootstraps.BSM_CLASSREF, CR_ClassRef).withArgs(descriptor));
     }
 
     @Override
--- a/src/java.base/share/classes/java/lang/sym/ConstantMethodHandleRef.java	Mon Mar 05 17:41:29 2018 -0500
+++ b/src/java.base/share/classes/java/lang/sym/ConstantMethodHandleRef.java	Mon Mar 05 18:02:36 2018 -0500
@@ -32,6 +32,7 @@
 import java.util.Objects;
 import java.util.Optional;
 
+import static java.lang.sym.ConstantRefs.CR_MethodTypeRef;
 import static java.lang.sym.MethodHandleRef.Kind.CONSTRUCTOR;
 import static java.lang.sym.ConstantRefs.CR_MethodHandleRef;
 import static java.util.Objects.requireNonNull;
@@ -173,8 +174,8 @@
 
     @Override
     public Optional<? extends ConstantRef<? super ConstantRef<MethodHandle>>> toConstantRef(MethodHandles.Lookup lookup) {
-        return DynamicConstantRef.symbolizeHelper(lookup, ConstantRefs.MHR_METHODHANDLEREF_FACTORY, CR_MethodHandleRef,
-                                                  kind, owner, name, type);
+        return Optional.of(DynamicConstantRef.of(RefBootstraps.BSM_METHODHANDLEREF, CR_MethodHandleRef)
+                                             .withArgs(kind.toString(), owner.descriptorString(), name, type.descriptorString()));
     }
 
     @Override
--- a/src/java.base/share/classes/java/lang/sym/ConstantMethodTypeRef.java	Mon Mar 05 17:41:29 2018 -0500
+++ b/src/java.base/share/classes/java/lang/sym/ConstantMethodTypeRef.java	Mon Mar 05 18:02:36 2018 -0500
@@ -34,6 +34,7 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import static java.lang.sym.ConstantRefs.CR_ClassRef;
 import static java.lang.sym.ConstantRefs.CR_MethodTypeRef;
 import static java.util.Objects.requireNonNull;
 
@@ -174,7 +175,7 @@
 
     @Override
     public Optional<? extends ConstantRef<? super ConstantRef<MethodType>>> toConstantRef(MethodHandles.Lookup lookup) {
-        return DynamicConstantRef.symbolizeHelper(lookup, ConstantRefs.MHR_METHODTYPEREF_FACTORY, CR_MethodTypeRef, descriptorString());
+        return Optional.of(DynamicConstantRef.of(RefBootstraps.BSM_METHODTYPEREF, CR_MethodTypeRef).withArgs(descriptorString()));
     }
 
     @Override
--- a/src/java.base/share/classes/java/lang/sym/ConstantRefs.java	Mon Mar 05 17:41:29 2018 -0500
+++ b/src/java.base/share/classes/java/lang/sym/ConstantRefs.java	Mon Mar 05 18:02:36 2018 -0500
@@ -298,10 +298,6 @@
     static final MethodHandleRef MHR_METHODHANDLEREF_ASTYPE
             = MethodHandleRef.of(MethodHandleRef.Kind.VIRTUAL, CR_MethodHandleRef, "asType", CR_MethodHandleRef, CR_MethodTypeRef);
 
-    static final MethodHandleRef MHR_DYNAMICCONSTANTREF_FACTORY_VARARGS
-            = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_DynamicConstantRef, "of",
-                                 CR_DynamicConstantRef, CR_MethodHandleRef, CR_String, CR_ClassRef, CR_ConstantRef.array());
-
     static final MethodHandleRef MHR_DYNAMICCONSTANTREF_FACTORY
             = MethodHandleRef.of(MethodHandleRef.Kind.STATIC, CR_DynamicConstantRef, "of",
                                  CR_DynamicConstantRef, CR_MethodHandleRef, CR_String, CR_ClassRef);
--- a/src/java.base/share/classes/java/lang/sym/DynamicConstantRef.java	Mon Mar 05 17:41:29 2018 -0500
+++ b/src/java.base/share/classes/java/lang/sym/DynamicConstantRef.java	Mon Mar 05 18:02:36 2018 -0500
@@ -35,12 +35,9 @@
 import java.util.function.Function;
 import java.util.stream.Stream;
 
-import static java.lang.sym.ConstantRefs.CR_ClassRef;
-import static java.lang.sym.ConstantRefs.CR_ConstantRef;
 import static java.lang.sym.ConstantRefs.CR_DynamicConstantRef;
-import static java.lang.sym.ConstantRefs.CR_MethodHandleRef;
-import static java.lang.sym.ConstantRefs.CR_String;
 import static java.util.Objects.requireNonNull;
+import static java.util.stream.Collectors.joining;
 
 /**
  * A nominal reference for a dynamic constant (one described in the constant
@@ -52,7 +49,7 @@
  * @param <T> the type of the dynamic constant
  */
 public abstract class DynamicConstantRef<T> implements ConstantRef<T>, Constable<ConstantRef<T>> {
-    private final MethodHandleRef bootstrapMethod;
+    private final ConstantMethodHandleRef bootstrapMethod;
     private final ConstantRef<?>[] bootstrapArgs;
     private final String name;
     private final ClassRef type;
@@ -85,10 +82,15 @@
      * @param bootstrapArgs The static arguments to the bootstrap, that would
      *                      appear in the {@code BootstrapMethods} attribute
      * @throws NullPointerException if any argument is null
+     * @throws IllegalArgumentException if the bootstrap method is not a
+     * {@link ConstantMethodHandleRef}
      * @throws IllegalArgumentException if {@code name.length()} is zero
      */
     protected DynamicConstantRef(MethodHandleRef bootstrapMethod, String name, ClassRef type, ConstantRef<?>... bootstrapArgs) {
-        this.bootstrapMethod = requireNonNull(bootstrapMethod);
+        requireNonNull(bootstrapMethod);
+        if (!(bootstrapMethod instanceof ConstantMethodHandleRef))
+            throw new IllegalArgumentException("bootstrap method must be a ConstantMethodHandleRef");
+        this.bootstrapMethod = (ConstantMethodHandleRef) bootstrapMethod;
         this.name = requireNonNull(name);
         this.type = requireNonNull(type);
         this.bootstrapArgs = requireNonNull(bootstrapArgs).clone();
@@ -306,18 +308,14 @@
 
     @Override
     public Optional<? extends ConstantRef<? super ConstantRef<T>>> toConstantRef(MethodHandles.Lookup lookup) {
-        try {
-            ConstantRef<?>[] args = new ConstantRef<?>[bootstrapArgs.length + 1];
-            args[0] = DynamicConstantRef.ofInvoke(ConstantRefs.MHR_DYNAMICCONSTANTREF_FACTORY, CR_DynamicConstantRef,
-                                          bootstrapMethod.toConstantRef().orElseThrow(),
-                                          name, type.toConstantRef().orElseThrow());
-            for (int i=0; i<bootstrapArgs.length; i++)
-                args[i+1] = ((Constable<?>) bootstrapArgs[i]).toConstantRef(lookup).orElseThrow();
-            return Optional.of(DynamicConstantRef.ofInvoke(ConstantRefs.MHR_DYNAMICCONSTANTREF_WITHARGS, CR_DynamicConstantRef, args));
-        }
-        catch (NoSuchElementException e) {
-            return Optional.empty();
-        }
+        ConstantRef<?>[] args = new ConstantRef<?>[bootstrapArgs.length + 5];
+        args[0] = bootstrapMethod.owner().descriptorString();
+        args[1] = bootstrapMethod.methodName();
+        args[2] = bootstrapMethod.methodType().descriptorString();
+        args[3] = name;
+        args[4] = type.descriptorString();
+        System.arraycopy(bootstrapArgs, 0, args, 5, bootstrapArgs.length);
+        return Optional.of(DynamicConstantRef.of(RefBootstraps.BSM_DYNAMICCONSTANTREF, "_", CR_DynamicConstantRef, args));
     }
 
     /**
@@ -388,13 +386,16 @@
 
     @Override
     public String toString() {
-        // @@@ Too verbose.  Prefer something like DynamicRef[Foo::bootstrap(name/static args)type]
-        return String.format("DynamicConstantRef[%s(%s), NameAndType[%s:%s]]",
-                             bootstrapMethod, Arrays.toString(bootstrapArgs), name, type.simpleName());
+        return String.format("DynamicConstantRef[%s::%s(%s%s)%s]",
+                             bootstrapMethod.owner().simpleName(),
+                             bootstrapMethod.methodName(),
+                             name.equals("_") ? "" : name + "/",
+                             Stream.of(bootstrapArgs).map(Object::toString).collect(joining(",")),
+                             type.simpleName());
     }
 
     private static final class DynamicConstantRefImpl<T> extends DynamicConstantRef<T> {
-        public DynamicConstantRefImpl(MethodHandleRef bootstrapMethod, String name, ClassRef type, ConstantRef<?>... bootstrapArgs) {
+        DynamicConstantRefImpl(MethodHandleRef bootstrapMethod, String name, ClassRef type, ConstantRef<?>... bootstrapArgs) {
             super(bootstrapMethod, name, type, bootstrapArgs);
         }
     }
--- a/src/java.base/share/classes/java/lang/sym/EnumRef.java	Mon Mar 05 17:41:29 2018 -0500
+++ b/src/java.base/share/classes/java/lang/sym/EnumRef.java	Mon Mar 05 18:02:36 2018 -0500
@@ -73,8 +73,7 @@
 
     @Override
     public Optional<? extends ConstantRef<? super ConstantRef<E>>> toConstantRef(MethodHandles.Lookup lookup) {
-        return DynamicConstantRef.symbolizeHelper(lookup, ConstantRefs.MHR_ENUMREF_FACTORY, CR_EnumRef,
-                                                  constantType(), constantName());
+        return Optional.of(DynamicConstantRef.of(RefBootstraps.BSM_ENUMREF, CR_EnumRef).withArgs(constantType().descriptorString(), constantName()));
     }
 
     @Override
--- a/src/java.base/share/classes/java/lang/sym/MethodHandleRef.java	Mon Mar 05 17:41:29 2018 -0500
+++ b/src/java.base/share/classes/java/lang/sym/MethodHandleRef.java	Mon Mar 05 18:02:36 2018 -0500
@@ -93,7 +93,7 @@
      * @throws NullPointerException if any of the non-ignored arguments are null
      */
     @Foldable
-    static MethodHandleRef of(Kind kind, ClassRef clazz, String name, MethodTypeRef type) {
+    static ConstantMethodHandleRef of(Kind kind, ClassRef clazz, String name, MethodTypeRef type) {
         return new ConstantMethodHandleRef(kind, clazz, name, type);
     }
 
@@ -109,7 +109,7 @@
      * @throws NullPointerException if any of the non-ignored arguments are null
      */
     @Foldable
-    static MethodHandleRef of(Kind kind, ClassRef clazz, String name, String descriptorString) {
+    static ConstantMethodHandleRef of(Kind kind, ClassRef clazz, String name, String descriptorString) {
         return of(kind, clazz, name, MethodTypeRef.ofDescriptor(descriptorString));
     }
 
@@ -126,7 +126,7 @@
      * @throws NullPointerException if any of the non-ignored arguments are null
      */
     @Foldable
-    static MethodHandleRef of(Kind kind, ClassRef clazz, String name, ClassRef returnType, ClassRef... paramTypes) {
+    static ConstantMethodHandleRef of(Kind kind, ClassRef clazz, String name, ClassRef returnType, ClassRef... paramTypes) {
         return of(kind, clazz, name, MethodTypeRef.of(returnType, paramTypes));
     }
 
@@ -143,7 +143,7 @@
      * @throws NullPointerException if any of the arguments are null
      */
     @Foldable
-    static MethodHandleRef ofDynamicCallsite(ClassRef clazz, String name, ClassRef returnType, ClassRef... paramTypes) {
+    static ConstantMethodHandleRef ofDynamicCallsite(ClassRef clazz, String name, ClassRef returnType, ClassRef... paramTypes) {
         return of(STATIC, clazz, name, MethodTypeRef.of(returnType, paramTypes).insertParameterTypes(0, ConstantRefs.INDY_BOOTSTRAP_ARGS));
     }
 
@@ -160,7 +160,7 @@
      * @throws NullPointerException if any of the arguments are null
      */
     @Foldable
-    static MethodHandleRef ofDynamicConstant(ClassRef clazz, String name, ClassRef returnType, ClassRef... paramTypes) {
+    static ConstantMethodHandleRef ofDynamicConstant(ClassRef clazz, String name, ClassRef returnType, ClassRef... paramTypes) {
         return of(STATIC, clazz, name, MethodTypeRef.of(returnType, paramTypes).insertParameterTypes(0, ConstantRefs.CONDY_BOOTSTRAP_ARGS));
     }
 
@@ -175,7 +175,7 @@
      * @throws NullPointerException if any of the arguments are null
      */
     @Foldable
-    static MethodHandleRef ofField(Kind kind, ClassRef clazz, String name, ClassRef type) {
+    static ConstantMethodHandleRef ofField(Kind kind, ClassRef clazz, String name, ClassRef type) {
         MethodTypeRef mtr;
         switch (kind) {
             case GETTER: mtr = MethodTypeRef.of(type, clazz); break;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/sym/RefBootstraps.java	Mon Mar 05 18:02:36 2018 -0500
@@ -0,0 +1,159 @@
+/*
+ * 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 static java.lang.sym.ConstantRefs.CR_ClassRef;
+import static java.lang.sym.ConstantRefs.CR_ConstantRef;
+import static java.lang.sym.ConstantRefs.CR_DynamicConstantRef;
+import static java.lang.sym.ConstantRefs.CR_EnumRef;
+import static java.lang.sym.ConstantRefs.CR_MethodHandleRef;
+import static java.lang.sym.ConstantRefs.CR_MethodTypeRef;
+import static java.lang.sym.ConstantRefs.CR_String;
+
+/**
+ * RefBoostraps
+ *
+ * @author Brian Goetz
+ */
+public final class RefBootstraps {
+    private RefBootstraps() { }
+
+    @Foldable
+    private static final ClassRef THIS_CLASS = ClassRef.of("java.lang.sym.RefBootstraps");
+
+    /** Bootstrap for ClassRef */
+    @Foldable
+    public static final MethodHandleRef BSM_CLASSREF = MethodHandleRef.ofDynamicConstant(THIS_CLASS, "classRef", CR_ClassRef,
+                                                                                         CR_String);
+
+    /** Bootstrap for MethodTypeRef */
+    @Foldable
+    public static final MethodHandleRef BSM_METHODTYPEREF = MethodHandleRef.ofDynamicConstant(THIS_CLASS, "methodTypeRef", CR_MethodTypeRef,
+                                                                                              CR_String);
+
+    /** Bootstrap for MethodHandleRef */
+    @Foldable
+    public static final MethodHandleRef BSM_METHODHANDLEREF = MethodHandleRef.ofDynamicConstant(THIS_CLASS, "methodHandleRef", CR_MethodHandleRef,
+                                                                                                CR_String, CR_String, CR_String, CR_String);
+
+    /** Bootstrap for DynamicConstantRef */
+    @Foldable
+    public static final MethodHandleRef BSM_DYNAMICCONSTANTREF = MethodHandleRef.ofDynamicConstant(THIS_CLASS, "dynamicConstantRef", CR_DynamicConstantRef,
+                                                                                                   CR_String, CR_String, CR_String, CR_String, CR_String,
+
+                                                                                                   CR_ConstantRef.array());
+
+    /** Bootstrap for ClassRef */
+    @Foldable
+    public static final MethodHandleRef BSM_ENUMREF = MethodHandleRef.ofDynamicConstant(THIS_CLASS, "enumRef", CR_EnumRef,
+                                                                                        CR_String, CR_String);
+    /**
+     * Bootstrap for ClassRef
+     *
+     * @param lookup ignored
+     * @param name ignored
+     * @param clazz ignored
+     * @param descriptor descriptor for class
+     * @return the ClassRef
+     */
+    public static ClassRef classRef(MethodHandles.Lookup lookup, String name, Class<ClassRef> clazz,
+                                    String descriptor) {
+        // @@@ Can fold descriptor into name channel, with encoding from BytecodeName
+        return ClassRef.ofDescriptor(descriptor);
+    }
+
+    /**
+     * Bootstrap for MethodTypeRef
+     *
+     * @param lookup ignored
+     * @param name ignored
+     * @param clazz ignored
+     * @param descriptor descriptor for method
+     * @return the MethodTypeRef
+     */
+    public static MethodTypeRef methodTypeRef(MethodHandles.Lookup lookup, String name, Class<ClassRef> clazz,
+                                              String descriptor) {
+        // @@@ Can fold descriptor into name channel, with encoding from BytecodeName
+        return MethodTypeRef.ofDescriptor(descriptor);
+    }
+
+    /**
+     * Bootstrap for MethodHandleRef
+     *
+     * @param lookup ignored
+     * @param name ignored
+     * @param clazz ignored
+     * @param bsmKindName kind
+     * @param bsmOwner owner
+     * @param bsmName name
+     * @param bsmDesc desc
+     * @return the MethodHandleRef
+     */
+    public static MethodHandleRef methodHandleRef(MethodHandles.Lookup lookup, String name, Class<ClassRef> clazz,
+                                                  String bsmKindName, String bsmOwner, String bsmName, String bsmDesc) {
+        return MethodHandleRef.of(MethodHandleRef.Kind.valueOf(bsmKindName), ClassRef.ofDescriptor(bsmOwner), bsmName, MethodTypeRef.ofDescriptor(bsmDesc));
+    }
+
+    /**
+     * Bootstrap for DynamicConstantRef
+     *
+     * @param lookup ignored
+     * @param name ignored
+     * @param clazz ignored
+     * @param bsmOwner owner
+     * @param bsmName name
+     * @param bsmDesc desc
+     * @param invName invName
+     * @param invType invType
+     * @param args bsm args
+     * @return the DynamicConstantRef
+     */
+    public static DynamicConstantRef<?> dynamicConstantRef(MethodHandles.Lookup lookup, String name, Class<ClassRef> clazz,
+                                                           String bsmOwner, String bsmName, String bsmDesc,
+                                                           String invName, String invType,
+                                                           ConstantRef<?>... args) {
+        return DynamicConstantRef.of(MethodHandleRef.of(MethodHandleRef.Kind.STATIC, ClassRef.ofDescriptor(bsmOwner), bsmName, MethodTypeRef.ofDescriptor(bsmDesc)),
+                                     invName, ClassRef.ofDescriptor(invType), args);
+
+    }
+
+    /**
+     * Bootstrap for EnumRef
+     *
+     * @param lookup ignored
+     * @param name ignored
+     * @param clazz ignored
+     * @param classDescriptor enum class
+     * @param constantName enum constant
+     * @return the EnumRef
+     */
+    public static EnumRef<?> enumRef(MethodHandles.Lookup lookup, String name, Class<ClassRef> clazz,
+                                     String classDescriptor, String constantName) {
+        return EnumRef.of(ClassRef.ofDescriptor(classDescriptor), constantName);
+    }
+}
--- a/src/java.base/share/classes/java/lang/sym/package-info.java	Mon Mar 05 17:41:29 2018 -0500
+++ b/src/java.base/share/classes/java/lang/sym/package-info.java	Mon Mar 05 18:02:36 2018 -0500
@@ -54,7 +54,7 @@
  *
  * <p>The subtypes of of {@link java.lang.sym.ConstantRef} describe various kinds
  * of constant values.  For each type of constant pool entry defined in JVMS 4.4,
- * there is a corresponding subtype of {@link java.lang.sym.ConstantRef:
+ * there is a corresponding subtype of {@link java.lang.sym.ConstantRef}:
  * {@code ConstantClassRef}, {@code ConstantMethodTypeRef},
  * {@code ConstantMethodHandleRef}, {@code String}, {@code Integer}, {@code Long},
  * {@code Float}, {@code Double}, and {@code DynamicConstantRef}.  These classes