Skip to content

Commit 015f6f5

Browse files
ZeaveeDoug Simon
authored and
Doug Simon
committedSep 21, 2023
8315771: [JVMCI] Resolution of bootstrap methods with int[] static arguments
Reviewed-by: dnsimon, psandoz
1 parent 83b01cf commit 015f6f5

File tree

5 files changed

+194
-18
lines changed

5 files changed

+194
-18
lines changed
 

‎src/hotspot/share/jvmci/jvmciCompilerToVM.cpp

+11-3
Original file line numberDiff line numberDiff line change
@@ -771,9 +771,11 @@ C2V_VMENTRY_NULL(jobjectArray, resolveBootstrapMethod, (JNIEnv* env, jobject, AR
771771
}
772772
// Get the indy entry based on CP index
773773
int indy_index = -1;
774-
for (int i = 0; i < cp->resolved_indy_entries_length(); i++) {
775-
if (cp->resolved_indy_entry_at(i)->constant_pool_index() == index) {
776-
indy_index = i;
774+
if (is_indy) {
775+
for (int i = 0; i < cp->resolved_indy_entries_length(); i++) {
776+
if (cp->resolved_indy_entry_at(i)->constant_pool_index() == index) {
777+
indy_index = i;
778+
}
777779
}
778780
}
779781
// Resolve the bootstrap specifier, its name, type, and static arguments
@@ -839,6 +841,11 @@ C2V_VMENTRY_NULL(jobjectArray, resolveBootstrapMethod, (JNIEnv* env, jobject, AR
839841
return JVMCIENV->get_jobjectArray(bsmi);
840842
C2V_END
841843

844+
C2V_VMENTRY_0(jint, bootstrapArgumentIndexAt, (JNIEnv* env, jobject, ARGUMENT_PAIR(cp), jint cpi, jint index))
845+
constantPoolHandle cp(THREAD, UNPACK_PAIR(ConstantPool, cp));
846+
return cp->bootstrap_argument_index_at(cpi, index);
847+
C2V_END
848+
842849
C2V_VMENTRY_0(jint, lookupNameAndTypeRefIndexInPool, (JNIEnv* env, jobject, ARGUMENT_PAIR(cp), jint index, jint opcode))
843850
constantPoolHandle cp(THREAD, UNPACK_PAIR(ConstantPool, cp));
844851
return cp->name_and_type_ref_index_at(index, (Bytecodes::Code)opcode);
@@ -3177,6 +3184,7 @@ JNINativeMethod CompilerToVM::methods[] = {
31773184
{CC "lookupConstantInPool", CC "(" HS_CONSTANT_POOL2 "IZ)" JAVACONSTANT, FN_PTR(lookupConstantInPool)},
31783185
{CC "constantPoolRemapInstructionOperandFromCache", CC "(" HS_CONSTANT_POOL2 "I)I", FN_PTR(constantPoolRemapInstructionOperandFromCache)},
31793186
{CC "resolveBootstrapMethod", CC "(" HS_CONSTANT_POOL2 "I)[" OBJECT, FN_PTR(resolveBootstrapMethod)},
3187+
{CC "bootstrapArgumentIndexAt", CC "(" HS_CONSTANT_POOL2 "II)I", FN_PTR(bootstrapArgumentIndexAt)},
31803188
{CC "getUncachedStringInPool", CC "(" HS_CONSTANT_POOL2 "I)" JAVACONSTANT, FN_PTR(getUncachedStringInPool)},
31813189
{CC "resolveTypeInPool", CC "(" HS_CONSTANT_POOL2 "I)" HS_KLASS, FN_PTR(resolveTypeInPool)},
31823190
{CC "resolveFieldInPool", CC "(" HS_CONSTANT_POOL2 "I" HS_METHOD2 "B[I)" HS_KLASS, FN_PTR(resolveFieldInPool)},

‎src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java

+22
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,28 @@ Object[] resolveBootstrapMethod(HotSpotConstantPool constantPool, int cpi) {
483483

484484
private native Object[] resolveBootstrapMethod(HotSpotConstantPool constantPool, long constantPoolPointer, int cpi);
485485

486+
/**
487+
* Gets the constant pool index of a static argument of a {@code CONSTANT_Dynamic_info} or
488+
* @{code CONSTANT_InvokeDynamic_info} entry. Used when the list of static arguments in the
489+
* {@link BootstrapMethodInvocation} is a {@code List<PrimitiveConstant>} of the form
490+
* {{@code arg_count}, {@code pool_index}}, meaning the arguments are not already resolved and that
491+
* the JDK has to lookup the arguments when they are needed. The {@code cpi} corresponds to
492+
* {@code pool_index} and the {@code index} has to be smaller than {@code arg_count}.
493+
*
494+
* The behavior of this method is undefined if {@code cpi} does not denote an entry representing
495+
* a {@code CONSTANT_Dynamic_info} or a @{code CONSTANT_InvokeDynamic_info}, or if the index
496+
* is out of bounds.
497+
*
498+
* @param cpi the index of a {@code CONSTANT_Dynamic_info} or @{code CONSTANT_InvokeDynamic_info} entry
499+
* @param index the index of the static argument in the list of static arguments
500+
* @return the constant pool index associated with the static argument
501+
*/
502+
int bootstrapArgumentIndexAt(HotSpotConstantPool constantPool, int cpi, int index) {
503+
return bootstrapArgumentIndexAt(constantPool, constantPool.getConstantPoolPointer(), cpi, index);
504+
}
505+
506+
private native int bootstrapArgumentIndexAt(HotSpotConstantPool constantPool, long constantPoolPointer, int cpi, int index);
507+
486508
/**
487509
* If {@code cpi} denotes an entry representing a signature polymorphic method ({@jvms 2.9}),
488510
* this method ensures that the type referenced by the entry is loaded and initialized. It

‎src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotConstantPool.java

+60-2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import static jdk.vm.ci.hotspot.HotSpotVMConfig.config;
2828
import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
2929

30+
import java.util.AbstractList;
31+
import java.util.ArrayList;
3032
import java.util.Arrays;
3133
import java.util.List;
3234
import java.util.stream.Collectors;
@@ -38,6 +40,7 @@
3840
import jdk.vm.ci.meta.JavaField;
3941
import jdk.vm.ci.meta.JavaMethod;
4042
import jdk.vm.ci.meta.JavaType;
43+
import jdk.vm.ci.meta.PrimitiveConstant;
4144
import jdk.vm.ci.meta.ResolvedJavaMethod;
4245
import jdk.vm.ci.meta.ResolvedJavaType;
4346
import jdk.vm.ci.meta.Signature;
@@ -504,6 +507,60 @@ private int flags() {
504507
return UNSAFE.getInt(getConstantPoolPointer() + config().constantPoolFlagsOffset);
505508
}
506509

510+
/**
511+
* Represents a list of static arguments from a {@link BootstrapMethodInvocation} of the form
512+
* {{@code arg_count}, {@code pool_index}}, meaning the arguments are not already resolved
513+
* and that the JDK has to lookup the arguments when they are needed. The {@code bssIndex}
514+
* corresponds to {@code pool_index} and the {@code size} corresponds to {@code arg_count}.
515+
*/
516+
static class CachedBSMArgs extends AbstractList<JavaConstant> {
517+
private final JavaConstant[] cache;
518+
private final HotSpotConstantPool cp;
519+
private final int bssIndex;
520+
521+
CachedBSMArgs(HotSpotConstantPool cp, int bssIndex, int size) {
522+
this.cp = cp;
523+
this.bssIndex = bssIndex;
524+
this.cache = new JavaConstant[size];
525+
}
526+
527+
/**
528+
* Lazily resolves and caches the argument at the given index and returns it. The method
529+
* {@link CompilerToVM#bootstrapArgumentIndexAt} is used to obtain the constant pool
530+
* index of the entry and the method {@link ConstantPool#lookupConstant} is used to
531+
* resolve it. If the resolution failed, the index is returned as a
532+
* {@link PrimitiveConstant}.
533+
*
534+
* @param index index of the element to return
535+
* @return A {@link JavaConstant} corresponding to the static argument requested. A return
536+
* value of type {@link PrimitiveConstant} represents an unresolved constant pool entry
537+
*/
538+
@Override
539+
public JavaConstant get(int index) {
540+
JavaConstant res = cache[index];
541+
if (res == null) {
542+
int argCpi = compilerToVM().bootstrapArgumentIndexAt(cp, bssIndex, index);
543+
Object object = cp.lookupConstant(argCpi, false);
544+
if (object instanceof PrimitiveConstant primitiveConstant) {
545+
res = runtime().getReflection().boxPrimitive(primitiveConstant);
546+
} else if (object instanceof JavaConstant javaConstant) {
547+
res = javaConstant;
548+
} else if (object instanceof JavaType type) {
549+
res = runtime().getReflection().forObject(type);
550+
} else {
551+
res = JavaConstant.forInt(argCpi);
552+
}
553+
cache[index] = res;
554+
}
555+
return res;
556+
}
557+
558+
@Override
559+
public int size() {
560+
return cache.length;
561+
}
562+
}
563+
507564
static class BootstrapMethodInvocationImpl implements BootstrapMethodInvocation {
508565
private final boolean indy;
509566
private final ResolvedJavaMethod method;
@@ -582,8 +639,9 @@ public BootstrapMethodInvocation lookupBootstrapMethodInvocation(int index, int
582639
staticArgumentsList = List.of((JavaConstant[]) staticArguments);
583640
} else {
584641
int[] bsciArgs = (int[]) staticArguments;
585-
String message = String.format("Resolving bootstrap static arguments for %s using BootstrapCallInfo %s not supported", method.format("%H.%n(%p)"), Arrays.toString(bsciArgs));
586-
throw new IllegalArgumentException(message);
642+
int argCount = bsciArgs[0];
643+
int bss_index = bsciArgs[1];
644+
staticArgumentsList = new CachedBSMArgs(this, bss_index, argCount);
587645
}
588646
return new BootstrapMethodInvocationImpl(tag.name.equals("InvokeDynamic"), method, name, type, staticArgumentsList);
589647
default:

‎src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ConstantPool.java

+24-3
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ default JavaMethod lookupMethod(int cpi, int opcode) {
131131

132132
/**
133133
* The details for invoking a bootstrap method associated with a {@code CONSTANT_Dynamic_info}
134-
* or {@code CONSTANT_InvokeDynamic_info} pool entry .
134+
* or {@code CONSTANT_InvokeDynamic_info} pool entry.
135135
*
136136
* @jvms 4.4.10 The {@code CONSTANT_Dynamic_info} and {@code CONSTANT_InvokeDynamic_info}
137137
* Structures
@@ -165,6 +165,29 @@ interface BootstrapMethodInvocation {
165165
/**
166166
* Gets the static arguments with which the bootstrap method will be invoked.
167167
*
168+
* The {@linkplain JavaConstant#getJavaKind kind} of each argument will be
169+
* {@link JavaKind#Object} or {@link JavaKind#Int}. The latter represents an
170+
* unresolved {@code CONSTANT_Dynamic_info} entry. To resolve this entry, the
171+
* corresponding bootstrap method has to be called first:
172+
*
173+
* <pre>
174+
* List<JavaConstant> args = bmi.getStaticArguments();
175+
* List<JavaConstant> resolvedArgs = new ArrayList<>(args.size());
176+
* for (JavaConstant c : args) {
177+
* JavaConstant r = c;
178+
* if (c.getJavaKind() == JavaKind.Int) {
179+
* // If needed, access corresponding BootstrapMethodInvocation using
180+
* // cp.lookupBootstrapMethodInvocation(pc.asInt(), -1)
181+
* r = cp.lookupConstant(c.asInt(), true);
182+
* } else {
183+
* assert c.getJavaKind() == JavaKind.Object;
184+
* }
185+
* resolvedArgs.append(r);
186+
* }
187+
* </pre>
188+
*
189+
* The other types of entries are already resolved an can be used directly.
190+
*
168191
* @jvms 5.4.3.6
169192
*/
170193
List<JavaConstant> getStaticArguments();
@@ -182,8 +205,6 @@ interface BootstrapMethodInvocation {
182205
* {@code index} was not decoded from a bytecode stream
183206
* @return the bootstrap method invocation details or {@code null} if the entry specified by {@code index}
184207
* is not a {@code CONSTANT_Dynamic_info} or @{code CONSTANT_InvokeDynamic_info}
185-
* @throws IllegalArgumentException if the bootstrap method invocation makes use of
186-
* {@code java.lang.invoke.BootstrapCallInfo}
187208
* @jvms 4.7.23 The {@code BootstrapMethods} Attribute
188209
*/
189210
default BootstrapMethodInvocation lookupBootstrapMethodInvocation(int index, int opcode) {

0 commit comments

Comments
 (0)
Please sign in to comment.