< prev index next >

src/java.base/share/classes/java/lang/constant/DynamicConstantDesc.java

Print this page
rev 52749 : Bootstrap method consolidation
* clean up and simplify JDK support code for BSM invocation
* simplify JVM bootstrap handshake: use BootstrapCallInfo only
* remove unused JVM paths and data fields
* move bootstrap argument processing from MethodHandleNatives to ConstantPool
* remove ConstantGroup; merge argument access into BootstrapCallInfo
* adjust BSM argument access: remove copyArguments, add argumentRef API
* add metadata-free BSM modes, including symbolic arguments from CP


   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package java.lang.constant;
  26 


  27 import java.lang.Enum.EnumDesc;
  28 import java.lang.invoke.MethodHandle;
  29 import java.lang.invoke.MethodHandles;

  30 import java.lang.invoke.VarHandle;
  31 import java.lang.invoke.VarHandle.VarHandleDesc;



  32 import java.util.Arrays;
  33 import java.util.List;
  34 import java.util.Map;
  35 import java.util.Objects;
  36 import java.util.Optional;
  37 import java.util.function.Function;
  38 import java.util.stream.Stream;
  39 
  40 import static java.lang.constant.ConstantDescs.BSM_DYNAMICCONSTANTDESC;
  41 import static java.lang.constant.ConstantDescs.BSM_INVOKE;
  42 import static java.lang.constant.ConstantDescs.CR_Class;
  43 import static java.lang.constant.ConstantDescs.CR_VarHandle;
  44 import static java.lang.constant.ConstantDescs.DEFAULT_NAME;
  45 import static java.lang.constant.ConstantDescs.MHR_DYNAMICCONSTANTDESC_FACTORY;
  46 import static java.lang.constant.ConstantDescs.MHR_DYNAMICCONSTANTDESC_NAMED_FACTORY;
  47 import static java.lang.constant.ConstantUtils.EMPTY_CONSTANTDESC;
  48 import static java.lang.constant.ConstantUtils.validateMemberName;
  49 import static java.util.Objects.requireNonNull;
  50 import static java.util.stream.Collectors.joining;
  51 
  52 /**
  53  * A <a href="package-summary.html#nominal">nominal descriptor</a> for a
  54  * dynamic constant (one described in the constant pool with
  55  * {@code Constant_Dynamic_info}.)
  56  *
  57  * <p>Concrete subtypes of {@linkplain DynamicConstantDesc} must be
  58  * <a href="../doc-files/ValueBased.html">value-based</a>.
  59  *
  60  * @param <T> the type of the dynamic constant
  61  */
  62 public abstract class DynamicConstantDesc<T>
  63         implements ConstantDesc<T>, Constable<ConstantDesc<T>> {
  64 
  65     private final DirectMethodHandleDesc bootstrapMethod;
  66     private final ConstantDesc<?>[] bootstrapArgs;
  67     private final String constantName;
  68     private final ClassDesc constantType;


  82      * @param bootstrapMethod a {@link DirectMethodHandleDescImpl} describing the
  83      *                        bootstrap method for the constant
  84      * @param constantName The name that would appear in the {@code NameAndType}
  85      *                     operand of the {@code LDC} for this constant, as per
  86      *                     JVMS 4.2.2
  87      * @param constantType a {@link DirectMethodHandleDescImpl} describing the type
  88      *                     that would appear in the {@code NameAndType} operand
  89      *                     of the {@code LDC} for this constant
  90      * @param bootstrapArgs {@link ConstantDesc}s describing the static arguments
  91      *                      to the bootstrap, that would appear in the
  92      *                      {@code BootstrapMethods} attribute
  93      * @throws NullPointerException if any argument is null
  94      * @throws IllegalArgumentException if the {@code name} has the incorrect
  95      * format
  96      * @jvms 4.2.2 Unqualified Names
  97      */
  98     protected DynamicConstantDesc(DirectMethodHandleDesc bootstrapMethod,
  99                                   String constantName,
 100                                   ClassDesc constantType,
 101                                   ConstantDesc<?>... bootstrapArgs) {
 102         this.bootstrapMethod = requireNonNull(bootstrapMethod);
 103         this.constantName = validateMemberName(requireNonNull(constantName));
 104         this.constantType = requireNonNull(constantType);
 105         this.bootstrapArgs = requireNonNull(bootstrapArgs).clone();
 106 
 107         if (constantName.length() == 0)
 108             throw new IllegalArgumentException("Illegal invocation name: " + constantName);
 109     }
 110 
 111     /**
 112      * Return a nominal descriptor for a dynamic constant, transforming it into
 113      * a more specific type if the constant bootstrap is a well-known one and a
 114      * more specific nominal descriptor type (e.g., ClassDesc) is available.
 115      *
 116      * <p>Classes whose {@link Constable#describeConstable()} method produces
 117      * a {@linkplain DynamicConstantDesc} with a well-known bootstrap including
 118      * {@link Class} (for instances describing primitive types), {@link Enum},
 119      * and {@link VarHandle}.
 120      *
 121      * <p>Bytecode-reading APIs that process the constant pool and wish to expose
 122      * entries as {@link ConstantDesc} to their callers should generally use this


 137      *                      to the bootstrap, that would appear in the
 138      *                      {@code BootstrapMethods} attribute
 139      * @return the nominal descriptor
 140      * @throws NullPointerException if any argument is null
 141      * @throws IllegalArgumentException if the {@code name} has the incorrect
 142      * format
 143      * @jvms 4.2.2 Unqualified Names
 144      */
 145     public static<T> ConstantDesc<T> ofCanonical(DirectMethodHandleDesc bootstrapMethod,
 146                                                  String constantName,
 147                                                  ClassDesc constantType,
 148                                                  ConstantDesc<?>[] bootstrapArgs) {
 149         return DynamicConstantDesc.<T>ofNamed(bootstrapMethod, constantName, constantType, bootstrapArgs)
 150                 .tryCanonicalize();
 151     }
 152 
 153     /**
 154      * Return a nominal descriptor for a dynamic constant.
 155      *
 156      * @param <T> the type of the dynamic constant
 157      * @param bootstrapMethod a {@link DirectMethodHandleDescImpl} describing the
 158      *                        bootstrap method for the constant
 159      * @param constantName The name that would appear in the {@code NameAndType}
 160      *                     operand of the {@code LDC} for this constant, as per
 161      *                     JVMS 4.2.2
 162      * @param constantType a {@link ClassDesc} describing the type
 163      *                     that would appear in the {@code NameAndType} operand
 164      *                     of the {@code LDC} for this constant
 165      * @param bootstrapArgs {@link ConstantDesc}s describing the static arguments
 166      *                      to the bootstrap, that would appear in the
 167      *                      {@code BootstrapMethods} attribute
 168      * @return the nominal descriptor
 169      * @throws NullPointerException if any argument is null
 170      * @throws IllegalArgumentException if the {@code name} has the incorrect
 171      * format
 172      * @jvms 4.2.2 Unqualified Names
 173      */
 174 
 175     public static<T> DynamicConstantDesc<T> ofNamed(DirectMethodHandleDesc bootstrapMethod,
 176                                                     String constantName,
 177                                                     ClassDesc constantType,


 214      * the same as the bootstrap method return type.
 215      *
 216      * @param <T> the type of the dynamic constant
 217      * @param bootstrapMethod a {@link DirectMethodHandleDescImpl} describing the
 218      *                        bootstrap method for the constant
 219      * @param bootstrapArgs {@link ConstantDesc}s describing the static arguments
 220      *                      to the bootstrap, that would appear in the
 221      *                      {@code BootstrapMethods} attribute
 222      * @return the nominal descriptor
 223      * @throws NullPointerException if any argument is null
 224      * @throws IllegalArgumentException if the {@code name} has the incorrect
 225      * format
 226      * @jvms 4.2.2 Unqualified Names
 227      */
 228     public static<T> DynamicConstantDesc<T> of(DirectMethodHandleDesc bootstrapMethod,
 229                                                ConstantDesc<?>... bootstrapArgs) {
 230         return ofNamed(bootstrapMethod, DEFAULT_NAME, bootstrapMethod.methodType().returnType(), bootstrapArgs);
 231     }
 232 
 233     /**










































































 234      * Return a nominal descriptor for a dynamic constant whose bootstrap has
 235      * no static arguments, whose name parameter is {@link ConstantDescs#DEFAULT_NAME},
 236      * and whose type parameter is always the same as the bootstrap method return type.
 237      *
 238      * @param <T> the type of the dynamic constant
 239      * @param bootstrapMethod a {@link DirectMethodHandleDescImpl} describing the
 240      *                        bootstrap method for the constant
 241      * @return the nominal descriptor
 242      * @throws NullPointerException if any argument is null
 243      * @throws IllegalArgumentException if the {@code name} has the incorrect
 244      * format
 245      */
 246     public static<T> DynamicConstantDesc<T> of(DirectMethodHandleDesc bootstrapMethod) {
 247         return of(bootstrapMethod, EMPTY_CONSTANTDESC);
 248     }
 249 
 250     /**
 251      * Returns The name that would appear in the {@code NameAndType} operand
 252      *             of the {@code LDC} for this constant
 253      *


 277         return bootstrapMethod;
 278     }
 279 
 280     /**
 281      * Returns the bootstrap arguments for this constant
 282      * @return the bootstrap arguments
 283      */
 284     public ConstantDesc<?>[] bootstrapArgs() {
 285         return bootstrapArgs.clone();
 286     }
 287 
 288     /**
 289      * Returns the bootstrap arguments for this constant as a {@link List}
 290      *
 291      * @return a {@link List} of the bootstrap arguments, described as {@link ConstantDesc}
 292      */
 293     public List<ConstantDesc<?>> bootstrapArgsList() {
 294         return List.of(bootstrapArgs);
 295     }
 296 



 297     @SuppressWarnings("unchecked")
 298     public T resolveConstantDesc(MethodHandles.Lookup lookup) throws ReflectiveOperationException {
 299         // TODO replace with public supported method















 300         try {
 301             MethodHandle bsm = bootstrapMethod.resolveConstantDesc(lookup);
 302             if (bsm.type().parameterCount() < 2 ||
 303                 !MethodHandles.Lookup.class.isAssignableFrom(bsm.type().parameterType(0))) {
 304                 throw new BootstrapMethodError(
 305                         "Invalid bootstrap method declared for resolving a dynamic constant: " + bootstrapMethod);
 306             }
 307             Object[] bsmArgs = new Object[3 + bootstrapArgs.length];
 308             bsmArgs[0] = lookup;
 309             bsmArgs[1] = constantName;
 310             bsmArgs[2] = constantType.resolveConstantDesc(lookup);
 311             for (int i = 0; i < bootstrapArgs.length; i++)
 312                 bsmArgs[3 + i] = bootstrapArgs[i].resolveConstantDesc(lookup);
 313 
 314             return (T) bsm.invokeWithArguments(bsmArgs);
 315         } catch (Error e) {
 316             throw e;
 317         } catch (Throwable t) {
 318             throw new BootstrapMethodError(t);
 319         }


 320     }
 321 
 322     @Override
 323     public Optional<? extends ConstantDesc<ConstantDesc<T>>> describeConstable() {
 324         ConstantDesc<?>[] args;
 325         if (constantName.equals(DEFAULT_NAME) && constantType.equals(bootstrapMethod.methodType().returnType())) {
 326             args = new ConstantDesc<?>[bootstrapArgs.length + 2];
 327             args[0] = MHR_DYNAMICCONSTANTDESC_FACTORY;
 328             args[1] = bootstrapMethod.describeConstable().orElseThrow();
 329             for (int i = 0; i < bootstrapArgs.length; i++)
 330                 args[i + 2] = (ConstantDesc<?>) ((Constable) bootstrapArgs[i]).describeConstable().orElseThrow();
 331         }
 332         else {
 333             args = new ConstantDesc<?>[bootstrapArgs.length + 4];
 334             args[0] = MHR_DYNAMICCONSTANTDESC_NAMED_FACTORY;
 335             args[1] = bootstrapMethod.describeConstable().orElseThrow();
 336             args[2] = constantName;
 337             args[3] = constantType().descriptorString();
 338             for (int i = 0; i < bootstrapArgs.length; i++)
 339                 args[i + 4] = (ConstantDesc<?>) ((Constable) bootstrapArgs[i]).describeConstable().orElseThrow();
 340         }
 341         return Optional.of(DynamicConstantDesc.of(BSM_INVOKE, args));
 342     }
 343 
 344     private ConstantDesc<T> tryCanonicalize() {
 345         Function<DynamicConstantDesc<?>, ConstantDesc<?>> f = canonicalMap.get(bootstrapMethod);
 346         if (f != null) {
 347             try {
 348                 @SuppressWarnings("unchecked")
 349                 ConstantDesc<T> converted = (ConstantDesc<T>) f.apply(this);
 350                 return converted;
 351             }
 352             catch (Throwable t) {
 353                 return this;
 354             }
 355         }
 356         return this;
 357     }
 358 
 359     private static ConstantDesc<?> canonicalizeNull(DynamicConstantDesc<?> desc) {
 360         if (desc.bootstrapArgs.length != 0)
 361             return desc;




   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package java.lang.constant;
  26 
  27 import jdk.internal.vm.annotation.Stable;
  28 
  29 import java.lang.Enum.EnumDesc;
  30 import java.lang.invoke.MethodHandle;
  31 import java.lang.invoke.MethodHandles;
  32 import java.lang.invoke.MethodHandles.Lookup;
  33 import java.lang.invoke.VarHandle;
  34 import java.lang.invoke.VarHandle.VarHandleDesc;
  35 import java.lang.reflect.InvocationTargetException;
  36 import java.security.AccessController;
  37 import java.security.PrivilegedAction;
  38 import java.util.Arrays;
  39 import java.util.List;
  40 import java.util.Map;
  41 import java.util.Objects;
  42 import java.util.Optional;
  43 import java.util.function.Function;
  44 import java.util.stream.Stream;
  45 


  46 import static java.lang.constant.ConstantDescs.CR_Class;
  47 import static java.lang.constant.ConstantDescs.CR_VarHandle;
  48 import static java.lang.constant.ConstantDescs.DEFAULT_NAME;
  49 import static java.lang.constant.ConstantUtils.*;
  50 import static java.lang.invoke.MethodHandles.lookup;


  51 import static java.util.Objects.requireNonNull;
  52 import static java.util.stream.Collectors.joining;
  53 
  54 /**
  55  * A <a href="package-summary.html#nominal">nominal descriptor</a> for a
  56  * dynamic constant (one described in the constant pool with
  57  * {@code Constant_Dynamic_info}.)
  58  *
  59  * <p>Concrete subtypes of {@linkplain DynamicConstantDesc} must be
  60  * <a href="../doc-files/ValueBased.html">value-based</a>.
  61  *
  62  * @param <T> the type of the dynamic constant
  63  */
  64 public abstract class DynamicConstantDesc<T>
  65         implements ConstantDesc<T>, Constable<ConstantDesc<T>> {
  66 
  67     private final DirectMethodHandleDesc bootstrapMethod;
  68     private final ConstantDesc<?>[] bootstrapArgs;
  69     private final String constantName;
  70     private final ClassDesc constantType;


  84      * @param bootstrapMethod a {@link DirectMethodHandleDescImpl} describing the
  85      *                        bootstrap method for the constant
  86      * @param constantName The name that would appear in the {@code NameAndType}
  87      *                     operand of the {@code LDC} for this constant, as per
  88      *                     JVMS 4.2.2
  89      * @param constantType a {@link DirectMethodHandleDescImpl} describing the type
  90      *                     that would appear in the {@code NameAndType} operand
  91      *                     of the {@code LDC} for this constant
  92      * @param bootstrapArgs {@link ConstantDesc}s describing the static arguments
  93      *                      to the bootstrap, that would appear in the
  94      *                      {@code BootstrapMethods} attribute
  95      * @throws NullPointerException if any argument is null
  96      * @throws IllegalArgumentException if the {@code name} has the incorrect
  97      * format
  98      * @jvms 4.2.2 Unqualified Names
  99      */
 100     protected DynamicConstantDesc(DirectMethodHandleDesc bootstrapMethod,
 101                                   String constantName,
 102                                   ClassDesc constantType,
 103                                   ConstantDesc<?>... bootstrapArgs) {
 104         this.bootstrapMethod = validateBootstrapMethod(requireNonNull(bootstrapMethod), constantName);
 105         this.constantName = validateMemberName(requireNonNull(constantName));
 106         this.constantType = requireNonNull(constantType);
 107         this.bootstrapArgs = requireNonNull(bootstrapArgs).clone();
 108 
 109         if (constantName.length() == 0)
 110             throw new IllegalArgumentException("Illegal invocation name: " + constantName);
 111     }
 112 
 113     /**
 114      * Return a nominal descriptor for a dynamic constant, transforming it into
 115      * a more specific type if the constant bootstrap is a well-known one and a
 116      * more specific nominal descriptor type (e.g., ClassDesc) is available.
 117      *
 118      * <p>Classes whose {@link Constable#describeConstable()} method produces
 119      * a {@linkplain DynamicConstantDesc} with a well-known bootstrap including
 120      * {@link Class} (for instances describing primitive types), {@link Enum},
 121      * and {@link VarHandle}.
 122      *
 123      * <p>Bytecode-reading APIs that process the constant pool and wish to expose
 124      * entries as {@link ConstantDesc} to their callers should generally use this


 139      *                      to the bootstrap, that would appear in the
 140      *                      {@code BootstrapMethods} attribute
 141      * @return the nominal descriptor
 142      * @throws NullPointerException if any argument is null
 143      * @throws IllegalArgumentException if the {@code name} has the incorrect
 144      * format
 145      * @jvms 4.2.2 Unqualified Names
 146      */
 147     public static<T> ConstantDesc<T> ofCanonical(DirectMethodHandleDesc bootstrapMethod,
 148                                                  String constantName,
 149                                                  ClassDesc constantType,
 150                                                  ConstantDesc<?>[] bootstrapArgs) {
 151         return DynamicConstantDesc.<T>ofNamed(bootstrapMethod, constantName, constantType, bootstrapArgs)
 152                 .tryCanonicalize();
 153     }
 154 
 155     /**
 156      * Return a nominal descriptor for a dynamic constant.
 157      *
 158      * @param <T> the type of the dynamic constant
 159      * @param bootstrapMethod a {@link DirectMethodHandleDesc} describing the
 160      *                        bootstrap method for the constant
 161      * @param constantName The name that would appear in the {@code NameAndType}
 162      *                     operand of the {@code LDC} for this constant, as per
 163      *                     JVMS 4.2.2
 164      * @param constantType a {@link ClassDesc} describing the type
 165      *                     that would appear in the {@code NameAndType} operand
 166      *                     of the {@code LDC} for this constant
 167      * @param bootstrapArgs {@link ConstantDesc}s describing the static arguments
 168      *                      to the bootstrap, that would appear in the
 169      *                      {@code BootstrapMethods} attribute
 170      * @return the nominal descriptor
 171      * @throws NullPointerException if any argument is null
 172      * @throws IllegalArgumentException if the {@code name} has the incorrect
 173      * format
 174      * @jvms 4.2.2 Unqualified Names
 175      */
 176 
 177     public static<T> DynamicConstantDesc<T> ofNamed(DirectMethodHandleDesc bootstrapMethod,
 178                                                     String constantName,
 179                                                     ClassDesc constantType,


 216      * the same as the bootstrap method return type.
 217      *
 218      * @param <T> the type of the dynamic constant
 219      * @param bootstrapMethod a {@link DirectMethodHandleDescImpl} describing the
 220      *                        bootstrap method for the constant
 221      * @param bootstrapArgs {@link ConstantDesc}s describing the static arguments
 222      *                      to the bootstrap, that would appear in the
 223      *                      {@code BootstrapMethods} attribute
 224      * @return the nominal descriptor
 225      * @throws NullPointerException if any argument is null
 226      * @throws IllegalArgumentException if the {@code name} has the incorrect
 227      * format
 228      * @jvms 4.2.2 Unqualified Names
 229      */
 230     public static<T> DynamicConstantDesc<T> of(DirectMethodHandleDesc bootstrapMethod,
 231                                                ConstantDesc<?>... bootstrapArgs) {
 232         return ofNamed(bootstrapMethod, DEFAULT_NAME, bootstrapMethod.methodType().returnType(), bootstrapArgs);
 233     }
 234 
 235     /**
 236      * Return a nominal descriptor for a dynamic constant whose name parameter
 237      * is {@link ConstantDescs#INVOKE_NAME}, and whose type parameter is always
 238      * the same as the bootstrap method return type.
 239      *
 240      * @param <T> the type of the dynamic constant
 241      * @param bootstrapMethod a {@link DirectMethodHandleDescImpl} describing the
 242      *                        bootstrap method for the constant
 243      * @param bootstrapArgs {@link ConstantDesc}s describing the static arguments
 244      *                      to the bootstrap, that would appear in the
 245      *                      {@code BootstrapMethods} attribute
 246      * @return the nominal descriptor
 247      * @throws NullPointerException if any argument is null
 248      * @throws IllegalArgumentException if the {@code name} has the incorrect
 249      * format
 250      * @jvms 4.2.2 Unqualified Names
 251      */
 252     public static<T> DynamicConstantDesc<T> ofInvoke(DirectMethodHandleDesc bootstrapMethod,
 253                                                      ConstantDesc<?>... bootstrapArgs) {
 254         String constantName = ConstantDescs.INVOKE_NAME;
 255         validateExpressionModeBootstrapMethod(bootstrapMethod, constantName);
 256         return ofNamed(bootstrapMethod, constantName, bootstrapMethod.methodType().returnType(), bootstrapArgs);
 257     }
 258 
 259     /**
 260      * Return a nominal descriptor for a dynamic constant whose name parameter
 261      * is {@link ConstantDescs#SYMBOLIC_NAME}, and whose type parameter is always
 262      * the same as the bootstrap method return type.  The effect of resolving
 263      * this dynamic constant will be to invoke the bootstrap method, without
 264      * metadata, and without resolving any static argument whose corresponding
 265      * bootstrap method parameter type is either {@code Object}, {@code ConstantDesc},
 266      * or a subtype of {@code ConstantDesc}.  Other bootstrap method parameter
 267      * types, such as {@code String} or {@code MethodHandle}, receive resolved
 268      * static arguments, as usual.
 269      *
 270      * @param <T> the type of the dynamic constant
 271      * @param bootstrapMethod a {@link DirectMethodHandleDescImpl} describing the
 272      *                        bootstrap method which will produce for the constant
 273      * @param bootstrapArgs {@link ConstantDesc}s describing the static arguments
 274      *                      to the bootstrap, that would appear in the
 275      *                      {@code BootstrapMethods} attribute
 276      * @return the nominal descriptor
 277      * @throws NullPointerException if any argument is null
 278      * @throws IllegalArgumentException if the {@code name} has the incorrect
 279      * format
 280      * @jvms 4.2.2 Unqualified Names
 281      */
 282     public static<T> DynamicConstantDesc<T> ofSymbolicExpression(DirectMethodHandleDesc bootstrapMethod,
 283                                                                  ConstantDesc<?>... bootstrapArgs) {
 284         String constantName = ConstantDescs.SYMBOLIC_NAME;
 285         validateExpressionModeBootstrapMethod(bootstrapMethod, constantName);
 286         return ofNamed(bootstrapMethod, constantName, bootstrapMethod.methodType().returnType(), bootstrapArgs);
 287     }
 288 
 289     /**
 290      * Return a nominal descriptor for a dynamic constant whose name parameter
 291      * is {@link ConstantDescs#SYMBOLIC_NAME}, whose type parameter is
 292      * {@code ConstantDesc}, and whose bootstrap method is
 293      * {@link ConstantBootstraps#constantDesc}.  The effect of resolving
 294      * this dynamic constant will be to return a {@code ConstantDesc}
 295      * that represents the sole static argument, without resolving it.
 296      *
 297      * @param <T> the type of the constant to be described
 298      * @param constantDesc the constant to be described
 299      * @return the nominal descriptor, which when resolved produces the constant, as a {@code ConstantDesc}
 300      * @throws NullPointerException if any argument is null
 301      * @throws IllegalArgumentException if the {@code name} has the incorrect
 302      * format
 303      * @jvms 4.2.2 Unqualified Names
 304      */
 305     public static<T extends ConstantDesc<?>> DynamicConstantDesc<T> ofSymbolic(T constantDesc) {
 306         return ofSymbolicExpression(ConstantDescs.MHR_CONSTANTDESC_IDENTITY, constantDesc);
 307     }
 308     
 309     /**
 310      * Return a nominal descriptor for a dynamic constant whose bootstrap has
 311      * no static arguments, whose name parameter is {@link ConstantDescs#DEFAULT_NAME},
 312      * and whose type parameter is always the same as the bootstrap method return type.
 313      *
 314      * @param <T> the type of the dynamic constant
 315      * @param bootstrapMethod a {@link DirectMethodHandleDescImpl} describing the
 316      *                        bootstrap method for the constant
 317      * @return the nominal descriptor
 318      * @throws NullPointerException if any argument is null
 319      * @throws IllegalArgumentException if the {@code name} has the incorrect
 320      * format
 321      */
 322     public static<T> DynamicConstantDesc<T> of(DirectMethodHandleDesc bootstrapMethod) {
 323         return of(bootstrapMethod, EMPTY_CONSTANTDESC);
 324     }
 325 
 326     /**
 327      * Returns The name that would appear in the {@code NameAndType} operand
 328      *             of the {@code LDC} for this constant
 329      *


 353         return bootstrapMethod;
 354     }
 355 
 356     /**
 357      * Returns the bootstrap arguments for this constant
 358      * @return the bootstrap arguments
 359      */
 360     public ConstantDesc<?>[] bootstrapArgs() {
 361         return bootstrapArgs.clone();
 362     }
 363 
 364     /**
 365      * Returns the bootstrap arguments for this constant as a {@link List}
 366      *
 367      * @return a {@link List} of the bootstrap arguments, described as {@link ConstantDesc}
 368      */
 369     public List<ConstantDesc<?>> bootstrapArgsList() {
 370         return List.of(bootstrapArgs);
 371     }
 372 
 373     public T resolveConstantDesc(Lookup lookup) throws ReflectiveOperationException {
 374         try {
 375             Object rawResult = MH_resolveDynamicConstant().invokeExact(this, lookup);
 376             @SuppressWarnings("unchecked")
 377             T result = (T) rawResult;
 378             return result;
 379         } catch (ReflectiveOperationException|RuntimeException ex) {
 380             throw ex;
 381         } catch (Throwable ex) {
 382             throw new InvocationTargetException(ex);
 383         }
 384     }
 385 
 386     private static @Stable MethodHandle MH_resolveDynamicConstant;
 387     private static MethodHandle MH_resolveDynamicConstant() {
 388         MethodHandle mh = MH_resolveDynamicConstant;
 389         if (mh != null)  return mh;
 390         // tunnel through access controls to get to BSCI::ofConstantDesc
 391         mh = AccessController.doPrivileged(new PrivilegedAction<MethodHandle>() {
 392             @Override
 393             public MethodHandle run() {
 394                 try {
 395                     var bsci = Class.forName("java.lang.invoke.BootstrapMethodInvoker");
 396                     var meth = bsci.getDeclaredMethod("resolveDynamicConstant",
 397                             DynamicConstantDesc.class, Lookup.class);
 398                     meth.setAccessible(true);
 399                     return lookup().unreflect(meth);
 400                 } catch (ReflectiveOperationException ex) {
 401                     throw new InternalError(ex);
 402                 }










 403             }
 404         });
 405         return mh;
 406     }
 407 
 408     @Override
 409     public Optional<? extends ConstantDesc<ConstantDesc<T>>> describeConstable() {
 410         return Optional.of(DynamicConstantDesc.ofSymbolic(this));

















 411     }
 412 
 413     private ConstantDesc<T> tryCanonicalize() {
 414         Function<DynamicConstantDesc<?>, ConstantDesc<?>> f = canonicalMap.get(bootstrapMethod);
 415         if (f != null) {
 416             try {
 417                 @SuppressWarnings("unchecked")
 418                 ConstantDesc<T> converted = (ConstantDesc<T>) f.apply(this);
 419                 return converted;
 420             }
 421             catch (Throwable t) {
 422                 return this;
 423             }
 424         }
 425         return this;
 426     }
 427 
 428     private static ConstantDesc<?> canonicalizeNull(DynamicConstantDesc<?> desc) {
 429         if (desc.bootstrapArgs.length != 0)
 430             return desc;


< prev index next >