blob: 6b75126a90fa493a2976cf9f43f383b8a7d4d573 [file]
/*
* Copyright (c) 2022, 2025, 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.classfile.constantpool;
import java.lang.classfile.BootstrapMethodEntry;
import java.lang.classfile.ClassFile;
import java.lang.classfile.ClassFileBuilder;
import java.lang.classfile.ClassModel;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.attribute.ConstantValueAttribute;
import java.lang.classfile.instruction.ConstantInstruction;
import java.lang.constant.*;
import java.lang.invoke.MethodHandleInfo;
import java.util.List;
import java.util.function.Consumer;
import jdk.internal.classfile.impl.AbstractPoolEntry;
import jdk.internal.classfile.impl.AbstractPoolEntry.ClassEntryImpl;
import jdk.internal.classfile.impl.ClassReaderImpl;
import jdk.internal.classfile.impl.SplitConstantPool;
import jdk.internal.classfile.impl.TemporaryConstantPool;
import jdk.internal.classfile.impl.Util;
import static java.util.Objects.requireNonNull;
/**
* Builder for the constant pool of a {@code class} file. Provides read and
* write access to the constant pool that is {@linkplain ClassFileBuilder#constantPool()
* being built}. Writing is append-only (the index of new entries monotonically
* increase) and idempotent (entry-bearing methods will return an existing entry
* if there is a suitable one).
* <p>
* For {@code class} file building, an overload of {@link ClassFile#build(
* ClassEntry, ConstantPoolBuilder, Consumer) ClassFile::build} takes a
* {@code ConstantPoolBuilder}. For {@code class} file transformations via
* {@link ClassFile#transformClass ClassFile::transformClass}, the {@link
* ClassFile.ConstantPoolSharingOption} controls how the constant pool builder
* of the resulting {@code class} is created.
*
* <h2 id="alien">Alien Constant Pool Entries</h2>
* In {@code class} file building and constant pool building, some constant pool
* entries supplied may be {@linkplain #canWriteDirect(ConstantPool) alien}
* to this constant pool builder of the active class file builder. For example,
* {@link #classEntry(Utf8Entry) classEntry(Utf8Entry)} may be called with an
* alien UTF8 entry. Alien entries will be converted to a pool entry in
* this constant pool builder, reusing equivalent entries or adding new entries
* if there is none. As a result, all pool entries returned by entry-bearing
* methods in this constant pool builder belong to this constant pool.
* <p>
* Some {@link ClassFileBuilder} methods may have their outputs adjusted if they
* receive pool entries alien to {@linkplain ClassFileBuilder#constantPool
* their constant pools}. For example, if an {@link ConstantInstruction#ofLoad
* ldc_w} instruction with an alien entry is written to a {@link CodeBuilder},
* the {@code CodeBuilder} may emit a functionally equivalent {@code ldc}
* instruction instead, if the converted entry can be encoded in such an
* instruction.
* <p>
* To avoid the conversion of alien constant pool entries, such as for the
* accuracy of the generated {@code class} file, users can always supply
* constant pool entries obtained by calling the constant pool builder
* entry-bearing methods of the constant pools associated with the {@code
* ClassFileBuilder}. Otherwise, the conversions have no impact on the
* behaviors of the generated {@code class} files.
*
* @see ClassFileBuilder#constantPool()
* @since 24
*/
public sealed interface ConstantPoolBuilder
extends ConstantPool
permits SplitConstantPool, TemporaryConstantPool {
/**
* {@return a new constant pool builder} The new constant pool builder will
* be pre-populated with the contents of the constant pool {@linkplain
* ClassModel#constantPool() associated with} the given class model. The
* index of new entries will start from the {@link ConstantPool#size()
* size()} of the source pool.
*
* @param classModel the class to copy from
* @see ClassFile#build(ClassEntry, ConstantPoolBuilder, Consumer)
* @see ClassFile.ConstantPoolSharingOption#SHARED_POOL
*/
static ConstantPoolBuilder of(ClassModel classModel) {
return new SplitConstantPool((ClassReaderImpl) classModel.constantPool());
}
/**
* {@return a new constant pool builder} The new constant pool builder
* will be empty. The index of new entries will start from {@code 1}.
*
* @see ClassFile.ConstantPoolSharingOption#NEW_POOL
*/
static ConstantPoolBuilder of() {
return new SplitConstantPool();
}
/**
* {@return {@code true} if the index of any entry in the given constant
* pool refers to the same entry in this builder} This may be because they
* are the same builder, or because this builder was {@linkplain
* #of(ClassModel) pre-populated} from the given constant pool.
* <p>
* If the constant pool of an entry is not directly writable to this pool,
* it is alien to this pool, and a {@link ClassFileBuilder} associated
* with this constant pool will convert that alien constant pool entry.
*
* @param constantPool the given constant pool
* @see ClassFileBuilder#constantPool() ClassFileBuilder::constantPool
* @see ##alien Alien Constant Pool Entries
*/
boolean canWriteDirect(ConstantPool constantPool);
/**
* {@return a {@link Utf8Entry} describing the provided {@link String}}
*
* @param s the string
* @see Utf8Entry#stringValue() Utf8Entry::stringValue
*/
Utf8Entry utf8Entry(String s);
/**
* {@return a {@link Utf8Entry} describing the {@linkplain
* ClassDesc#descriptorString() field descriptor string} of the provided
* {@link ClassDesc}}
*
* @apiNote
* The resulting {@code Utf8Entry} is usually not {@linkplain
* #classEntry(Utf8Entry) referable by} a {@link ClassEntry}, which uses
* internal form of binary names.
*
* @param desc the symbolic descriptor for the class
*/
default Utf8Entry utf8Entry(ClassDesc desc) {
return utf8Entry(desc.descriptorString());
}
/**
* {@return a {@link Utf8Entry} describing the {@linkplain
* MethodTypeDesc#descriptorString() method descriptor string} of the
* provided {@link MethodTypeDesc}}
*
* @param desc the symbolic descriptor for the method type
*/
default Utf8Entry utf8Entry(MethodTypeDesc desc) {
return utf8Entry(desc.descriptorString());
}
/**
* {@return a {@link ClassEntry} referring to the provided {@link
* Utf8Entry}} The {@code Utf8Entry} describes the internal form
* of the binary name of a class or interface or the field descriptor
* string of an array type.
*
* @param ne the {@code Utf8Entry}
* @see ClassEntry#name() ClassEntry::name
*/
ClassEntry classEntry(Utf8Entry ne);
/**
* {@return a {@link ClassEntry} describing the same reference type
* as the provided {@link ClassDesc}}
*
* @param classDesc the symbolic descriptor for the reference type
* @throws IllegalArgumentException if {@code classDesc} represents a
* primitive type
* @see ClassEntry#asSymbol() ClassEntry::asSymbol
*/
default ClassEntry classEntry(ClassDesc classDesc) {
if (requireNonNull(classDesc).isPrimitive()) {
throw new IllegalArgumentException("Cannot be encoded as ClassEntry: " + classDesc.displayName());
}
ClassEntryImpl ret = (ClassEntryImpl)classEntry(utf8Entry(classDesc.isArray() ? classDesc.descriptorString() : Util.toInternalName(classDesc)));
ret.sym = classDesc;
return ret;
}
/**
* {@return a {@link PackageEntry} referring to the provided {@link
* Utf8Entry}} The {@code Utf8Entry} describes the internal form
* of the name of a package.
*
* @param nameEntry the {@code Utf8Entry}
* @see PackageEntry#name() PackageEntry::name
*/
PackageEntry packageEntry(Utf8Entry nameEntry);
/**
* {@return a {@link PackageEntry} describing the same package as the
* provided {@link PackageDesc}}
*
* @param packageDesc the symbolic descriptor for the package
* @see PackageEntry#asSymbol() PackageEntry::asSymbol
*/
default PackageEntry packageEntry(PackageDesc packageDesc) {
return packageEntry(utf8Entry(packageDesc.internalName()));
}
/**
* {@return a {@link ModuleEntry} referring to the provided {@link
* Utf8Entry}} The {@code Utf8Entry} describes the module name.
*
* @param moduleName the constant pool entry describing the module name
* @see ModuleEntry#name() ModuleEntry::name
*/
ModuleEntry moduleEntry(Utf8Entry moduleName);
/**
* {@return a {@link ModuleEntry} describing the same module as the provided
* {@link ModuleDesc}}
*
* @param moduleDesc the symbolic descriptor for the module
* @see ModuleEntry#asSymbol() ModuleEntry::asSymbol
*/
default ModuleEntry moduleEntry(ModuleDesc moduleDesc) {
return moduleEntry(utf8Entry(moduleDesc.name()));
}
/**
* {@return a {@link NameAndTypeEntry} referring to the provided name and
* type {@link Utf8Entry}} The name {@code Utf8Entry} describes an
* unqualified name or the special name {@value ConstantDescs#INIT_NAME},
* and the type {@code Utf8Entry} describes a field or method descriptor
* string.
*
* @param nameEntry the name {@code Utf8Entry}
* @param typeEntry the type {@code Utf8Entry}
* @see NameAndTypeEntry#name() NameAndTypeEntry::name
* @see NameAndTypeEntry#type() NameAndTypeEntry::type
*/
NameAndTypeEntry nameAndTypeEntry(Utf8Entry nameEntry, Utf8Entry typeEntry);
/**
* {@return a {@link NameAndTypeEntry} describing the provided unqualified
* name and field descriptor}
*
* @param name the unqualified name
* @param type the field descriptor
*/
default NameAndTypeEntry nameAndTypeEntry(String name, ClassDesc type) {
return nameAndTypeEntry(utf8Entry(name), utf8Entry(type));
}
/**
* {@return a {@link NameAndTypeEntry} describing the provided name and
* method descriptor} The name can be an unqualified name or the
* special name {@value ConstantDescs#INIT_NAME}.
*
* @param name the unqualified name, or {@value ConstantDescs#INIT_NAME}
* @param type the method descriptor
*/
default NameAndTypeEntry nameAndTypeEntry(String name, MethodTypeDesc type) {
return nameAndTypeEntry(utf8Entry(name), utf8Entry(type));
}
/**
* {@return a {@link FieldRefEntry} referring to a {@link ClassEntry} and a
* {@link NameAndTypeEntry}} The {@code ClassEntry} describes a class or
* interface that has this field as a member, and the {@code
* NameAndTypeEntry} describes the unqualified name and the field descriptor
* for this field.
*
* @param owner the {@code ClassEntry}
* @param nameAndType the {@code NameAndTypeEntry}
* @see FieldRefEntry#owner() FieldRefEntry::owner
* @see FieldRefEntry#nameAndType() FieldRefEntry::nameAndType
*/
FieldRefEntry fieldRefEntry(ClassEntry owner, NameAndTypeEntry nameAndType);
/**
* {@return a {@link FieldRefEntry} describing a field of a class}
*
* @param owner the class or interface the field is a member of
* @param name the unqualified name of the field
* @param type the field descriptor
* @throws IllegalArgumentException if {@code owner} represents a primitive type
* @see FieldRefEntry#typeSymbol() FieldRefEntry::typeSymbol
*/
default FieldRefEntry fieldRefEntry(ClassDesc owner, String name, ClassDesc type) {
return fieldRefEntry(classEntry(owner), nameAndTypeEntry(name, type));
}
/**
* {@return a {@link MethodRefEntry} referring to a {@link ClassEntry} and a
* {@link NameAndTypeEntry}} The {@code ClassEntry} describes a class that
* has this method as a member, and the {@code NameAndTypeEntry} describes
* the unqualified name or the special name {@value ConstantDescs#INIT_NAME}
* and the method descriptor for this method.
*
* @param owner the {@code ClassEntry}
* @param nameAndType the {@code NameAndTypeEntry}
* @see MethodRefEntry#owner() MethodRefEntry::owner
* @see MethodRefEntry#nameAndType() MethodRefEntry::nameAndType
*/
MethodRefEntry methodRefEntry(ClassEntry owner, NameAndTypeEntry nameAndType);
/**
* {@return a {@link MethodRefEntry} describing a method of a class}
*
* @param owner the class the method is a member of
* @param name the unqualified name, or special name {@value
* ConstantDescs#INIT_NAME}, of the method
* @param type the method descriptor
* @throws IllegalArgumentException if {@code owner} represents a primitive type
* @see MethodRefEntry#typeSymbol() MethodRefEntry::typeSymbol
*/
default MethodRefEntry methodRefEntry(ClassDesc owner, String name, MethodTypeDesc type) {
return methodRefEntry(classEntry(owner), nameAndTypeEntry(name, type));
}
/**
* {@return an {@link InterfaceMethodRefEntry} referring to a {@link
* ClassEntry} and a {@link NameAndTypeEntry}} The {@code ClassEntry}
* describes an interface that has this method as a member, and the {@code
* NameAndTypeEntry} describes the unqualified name and the method
* descriptor for this method.
*
* @param owner the {@code ClassEntry}
* @param nameAndType the {@code NameAndTypeEntry}
* @see InterfaceMethodRefEntry#owner() InterfaceMethodRefEntry::owner
* @see InterfaceMethodRefEntry#nameAndType()
* InterfaceMethodRefEntry::nameAndType
*/
InterfaceMethodRefEntry interfaceMethodRefEntry(ClassEntry owner, NameAndTypeEntry nameAndType);
/**
* {@return an {@link InterfaceMethodRefEntry} describing a method of an
* interface}
*
* @param owner the interface the method is a member of
* @param name the unqualified name of the method
* @param type the method descriptor
* @throws IllegalArgumentException if {@code owner} represents a primitive type
* @see InterfaceMethodRefEntry#typeSymbol() InterfaceMethodRefEntry::typeSymbol
*/
default InterfaceMethodRefEntry interfaceMethodRefEntry(ClassDesc owner, String name, MethodTypeDesc type) {
return interfaceMethodRefEntry(classEntry(owner), nameAndTypeEntry(name, type));
}
/**
* {@return a {@link MethodTypeEntry} describing the same method type as
* the provided {@link MethodTypeDesc}}
*
* @param descriptor the symbolic descriptor of the method type
* @see MethodTypeEntry#asSymbol() MethodTypeEntry::asSymbol
*/
MethodTypeEntry methodTypeEntry(MethodTypeDesc descriptor);
/**
* {@return a {@link MethodTypeEntry} referring to a {@link Utf8Entry}}
* The {@code Utf8Entry} represents a method descriptor string.
*
* @param descriptor the {@code Utf8Entry}
* @see MethodTypeEntry#descriptor() MethodTypeEntry::descriptor
*/
MethodTypeEntry methodTypeEntry(Utf8Entry descriptor);
/**
* {@return a {@link MethodHandleEntry} describing the same method handle as
* the given {@link DirectMethodHandleDesc}}
*
* @param descriptor the symbolic descriptor of the method handle
* @see MethodHandleEntry#asSymbol() MethodHandleEntry::asSymbol
*/
default MethodHandleEntry methodHandleEntry(DirectMethodHandleDesc descriptor) {
var owner = classEntry(descriptor.owner());
var nat = nameAndTypeEntry(utf8Entry(descriptor.methodName()), utf8Entry(descriptor.lookupDescriptor()));
var ret = methodHandleEntry(descriptor.refKind(), switch (descriptor.kind()) {
case GETTER, SETTER, STATIC_GETTER, STATIC_SETTER -> fieldRefEntry(owner, nat);
case INTERFACE_STATIC, INTERFACE_VIRTUAL, INTERFACE_SPECIAL -> interfaceMethodRefEntry(owner, nat);
case STATIC, VIRTUAL, SPECIAL, CONSTRUCTOR -> methodRefEntry(owner, nat);
});
((AbstractPoolEntry.MethodHandleEntryImpl) ret).sym = descriptor;
return ret;
}
/**
* {@return a {@link MethodHandleEntry} encoding a reference kind and
* referring to a {@link MemberRefEntry}} The reference kind must be
* in {@code [1, 9]}, and the {@code MemberRefEntry} is subject to
* various restrictions based on the reference kind (JVMS {@jvms 4.4.8}).
*
* @param refKind the reference kind of the method handle
* @param reference the {@code MemberRefEntry}
* @see MethodHandleInfo##refkinds Reference kinds
* @see MethodHandleEntry#kind() MethodHandleEntry::kind
* @see MethodHandleEntry#reference() MethodHandleEntry::reference
*/
MethodHandleEntry methodHandleEntry(int refKind, MemberRefEntry reference);
/**
* {@return an {@link InvokeDynamicEntry} describing the same dynamic call
* site as the provided {@link DynamicCallSiteDesc}}
*
* @param dcsd the symbolic descriptor of the dynamic call site
* @see InvokeDynamicEntry#asSymbol() InvokeDynamicEntry::asSymbol
*/
default InvokeDynamicEntry invokeDynamicEntry(DynamicCallSiteDesc dcsd) {
var ret = invokeDynamicEntry(bsmEntry((DirectMethodHandleDesc)dcsd.bootstrapMethod(), List.of(dcsd.bootstrapArgs())), nameAndTypeEntry(dcsd.invocationName(), dcsd.invocationType()));
((AbstractPoolEntry.InvokeDynamicEntryImpl) ret).sym = dcsd;
return ret;
}
/**
* {@return an {@link InvokeDynamicEntry} referring to a {@link
* BootstrapMethodEntry} and a {@link NameAndTypeEntry}}
* The {@code BootstrapMethodEntry} describes the bootstrap method
* and its invocation arguments in addition to the name and type,
* and the {@code NameAndTypeEntry} a name and a method descriptor.
*
* @param bootstrapMethodEntry the {@code BootstrapMethodEntry}
* @param nameAndType the {@code NameAndTypeEntry}
* @see InvokeDynamicEntry#bootstrap() InvokeDynamicEntry::bootstrap
* @see InvokeDynamicEntry#nameAndType() InvokeDynamicEntry::nameAndType
*/
InvokeDynamicEntry invokeDynamicEntry(BootstrapMethodEntry bootstrapMethodEntry,
NameAndTypeEntry nameAndType);
/**
* {@return a {@link ConstantDynamicEntry} describing the dynamic constant
* as the provided {@link DynamicConstantDesc}}
*
* @param dcd the symbolic descriptor of the constant
* @see ConstantDynamicEntry#asSymbol() ConstantDynamicEntry::asSymbol
*/
default ConstantDynamicEntry constantDynamicEntry(DynamicConstantDesc<?> dcd) {
var ret = constantDynamicEntry(bsmEntry(dcd.bootstrapMethod(), List.of(dcd.bootstrapArgs())), nameAndTypeEntry(dcd.constantName(), dcd.constantType()));
((AbstractPoolEntry.ConstantDynamicEntryImpl) ret).sym = dcd;
return ret;
}
/**
* {@return a {@link ConstantDynamicEntry} referring to a {@link
* BootstrapMethodEntry} and a {@link NameAndTypeEntry}}
* The {@code BootstrapMethodEntry} describes the bootstrap method
* and its invocation arguments in addition to the name and type,
* and the {@code NameAndTypeEntry} a name and a field descriptor.
*
* @param bootstrapMethodEntry the {@code BootstrapMethodEntry}
* @param nameAndType the {@code NameAndTypeEntry}
* @see ConstantDynamicEntry#bootstrap() ConstantDynamicEntry::bootstrap
* @see ConstantDynamicEntry#nameAndType() ConstantDynamicEntry::nameAndType
*/
ConstantDynamicEntry constantDynamicEntry(BootstrapMethodEntry bootstrapMethodEntry, NameAndTypeEntry nameAndType);
/**
* {@return an {@link IntegerEntry} describing the provided value}
*
* @param value the value
* @see IntegerEntry#intValue() IntegerEntry::intValue
*/
IntegerEntry intEntry(int value);
/**
* {@return a {@link FloatEntry} describing the provided value}
* <p>
* All NaN values of the {@code float} may or may not be collapsed into a
* single {@linkplain Float#NaN "canonical" NaN value}.
*
* @param value the value
* @see FloatEntry#floatValue() FloatEntry::floatValue
*/
FloatEntry floatEntry(float value);
/**
* {@return a {@link LongEntry} describing the provided value}
*
* @param value the value
* @see LongEntry#longValue() LongEntry::longValue
*/
LongEntry longEntry(long value);
/**
* {@return a {@link DoubleEntry} describing the provided value}
* <p>
* All NaN values of the {@code double} may or may not be collapsed into a
* single {@linkplain Double#NaN "canonical" NaN value}.
*
* @param value the value
* @see DoubleEntry#doubleValue() DoubleEntry::doubleValue
*/
DoubleEntry doubleEntry(double value);
/**
* {@return a {@link StringEntry} referring to a {@link Utf8Entry}}
* The {@code Utf8Entry} describes the string value.
*
* @param utf8 the {@code Utf8Entry}
* @see StringEntry#utf8() StringEntry::utf8
*/
StringEntry stringEntry(Utf8Entry utf8);
/**
* {@return a {@link StringEntry} describing the provided value}
*
* @param value the value
* @see StringEntry#stringValue() StringEntry::stringValue
*/
default StringEntry stringEntry(String value) {
return stringEntry(utf8Entry(value));
}
/**
* {@return a {@link ConstantValueEntry} describing the provided constant
* {@link Integer}, {@link Long}, {@link Float}, {@link Double}, or {@link
* String} value}
*
* @param c the provided constant value
* @throws IllegalArgumentException if the value is not one of {@code
* Integer}, {@code Long}, {@code Float}, {@code Double}, or {@code
* String}
* @see ConstantValueEntry#constantValue() ConstantValueEntry::constantValue
* @see ConstantValueAttribute#of(ConstantDesc)
* ConstantValueAttribute::of(ConstantDesc)
*/
default ConstantValueEntry constantValueEntry(ConstantDesc c) {
if (c instanceof Integer i) return intEntry(i);
if (c instanceof String s) return stringEntry(s);
if (c instanceof Long l) return longEntry(l);
if (c instanceof Float f) return floatEntry(f);
if (c instanceof Double d) return doubleEntry(d);
throw new IllegalArgumentException("Illegal type: " + (c == null ? null : c.getClass()));
}
/**
* {@return a {@link LoadableConstantEntry} describing the provided constant
* value}
*
* @param c the nominal descriptor for the constant
*/
default LoadableConstantEntry loadableConstantEntry(ConstantDesc c) {
if (c instanceof Integer i) return intEntry(i);
if (c instanceof String s) return stringEntry(s);
if (c instanceof Long l) return longEntry(l);
if (c instanceof Float f) return floatEntry(f);
if (c instanceof Double d) return doubleEntry(d);
if (c instanceof ClassDesc cd && !cd.isPrimitive()) return classEntry(cd);
if (c instanceof MethodTypeDesc mtd) return methodTypeEntry(mtd);
if (c instanceof DirectMethodHandleDesc dmhd) return methodHandleEntry(dmhd);
if (c instanceof DynamicConstantDesc<?> dcd) return constantDynamicEntry(dcd);
throw new IllegalArgumentException("Illegal type: " + (c == null ? null : c.getClass()));
}
/**
* {@return a {@link BootstrapMethodEntry} describing the provided
* bootstrap method and arguments}
*
* @param methodReference the bootstrap method
* @param arguments the arguments
*/
default BootstrapMethodEntry bsmEntry(DirectMethodHandleDesc methodReference,
List<ConstantDesc> arguments) {
return bsmEntry(methodHandleEntry(methodReference),
arguments.stream().map(this::loadableConstantEntry).toList());
}
/**
* {@return a {@link BootstrapMethodEntry} referring to a {@link
* MethodHandleEntry} and a list of {@link LoadableConstantEntry}}
* The {@code MethodHandleEntry} is the bootstrap method, and the
* list of {@code LoadableConstantEntry} is the arguments.
*
* @param methodReference the {@code MethodHandleEntry}
* @param arguments the list of {@code LoadableConstantEntry}
* @see BootstrapMethodEntry#bootstrapMethod()
* BootstrapMethodEntry::bootstrapMethod
* @see BootstrapMethodEntry#arguments() BootstrapMethodEntry::arguments
*/
BootstrapMethodEntry bsmEntry(MethodHandleEntry methodReference,
List<LoadableConstantEntry> arguments);
}