runtimeContextArgCount == 0 ? new LinkRequestImpl(callSiteDescriptor, callSiteUnstable, arguments)
: new RuntimeContextLinkRequestImpl(callSiteDescriptor, callSiteUnstable, arguments,
runtimeContextArgCount);
// Find a suitable method handle with a guard
GuardedInvocation guardedInvocation = linkerServices.getGuardedInvocation(linkRequest);
// None found - throw an exception
if(guardedInvocation == null) {
throw new NoSuchDynamicMethodException(callSiteDescriptor.toString());
}
// If our call sites have a runtime context, and the linker produced a context-stripped invocation, adapt the
// produced invocation into contextual invocation (by dropping the context...)
if(runtimeContextArgCount > 0) {
final MethodType origType = callSiteDescriptor.getMethodType();
final MethodHandle invocation = guardedInvocation.getInvocation();
if(invocation.type().parameterCount() == origType.parameterCount() - runtimeContextArgCount) {
final List<Class<?>> prefix = origType.parameterList().subList(1, runtimeContextArgCount + 1);
final MethodHandle guard = guardedInvocation.getGuard();
guardedInvocation = guardedInvocation.dropArguments(1, prefix);
}
}
int newRelinkCount = relinkCount;
// Note that the short-circuited "&&" evaluation below ensures we'll increment the relinkCount until
// threshold + 1 but not beyond that. Threshold + 1 is treated as a special value to signal that resetAndRelink
// has already executed once for the unstable call site; we only want the call site to throw away its current
// linkage once, when it transitions to unstable.
if(unstableDetectionEnabled && newRelinkCount <= unstableRelinkThreshold && newRelinkCount++ == unstableRelinkThreshold) {
callSite.resetAndRelink(guardedInvocation, createRelinkAndInvokeMethod(callSite, newRelinkCount));
} else {
callSite.relink(guardedInvocation, createRelinkAndInvokeMethod(callSite, newRelinkCount));
}
if(syncOnRelink) {
MutableCallSite.syncAll(new MutableCallSite[] { (MutableCallSite)callSite });
}
return guardedInvocation.getInvocation();
}