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;
|