下面列出了java.lang.invoke.MutableCallSite#syncAll ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* Relinks a call site conforming to the invocation arguments.
*
* @param callSite the call site itself
* @param arguments arguments to the invocation
*
* @return return the method handle for the invocation
*
* @throws Exception rethrows any exception thrown by the linkers
*/
@SuppressWarnings("unused")
private MethodHandle relink(final RelinkableCallSite callSite, final int relinkCount, final Object... arguments) throws Exception {
final CallSiteDescriptor callSiteDescriptor = callSite.getDescriptor();
final boolean unstableDetectionEnabled = unstableRelinkThreshold > 0;
final boolean callSiteUnstable = unstableDetectionEnabled && relinkCount >= unstableRelinkThreshold;
final LinkRequest linkRequest = new SimpleLinkRequest(callSiteDescriptor, callSiteUnstable, arguments);
GuardedInvocation guardedInvocation = linkerServices.getGuardedInvocation(linkRequest);
// None found - throw an exception
if(guardedInvocation == null) {
throw new NoSuchDynamicMethodException(callSiteDescriptor.toString());
}
// Make sure we transform the invocation before linking it into the call site. This is typically used to match the
// return type of the invocation to the call site.
guardedInvocation = prelinkTransformer.filter(guardedInvocation, linkRequest, linkerServices);
Objects.requireNonNull(guardedInvocation);
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();
}
private void updateCallSite(boolean desired_state, MethodHandle tester, MutableCallSite c, MethodHandle mh, MutableCallSite[] cs) {
try {
if (((boolean)tester.invokeExact()) != desired_state) {
c.setTarget(mh);
MutableCallSite.syncAll(cs);
}
} catch (Throwable e) {
Misc.internalError(e);
}
}
@Override
public void setGeneration(long generation) {
currentGeneration.setTarget(MethodHandles.constant(long.class, generation));
MutableCallSite.syncAll(currentGenerations);
}
/**
* Relinks a call site conforming to the invocation arguments.
*
* @param callSite the call site itself
* @param arguments arguments to the invocation
*
* @return return the method handle for the invocation
*
* @throws Exception rethrows any exception thrown by the linkers
*/
@SuppressWarnings("unused")
private MethodHandle relink(final RelinkableCallSite callSite, final int relinkCount, final Object... arguments) throws Exception {
final CallSiteDescriptor callSiteDescriptor = callSite.getDescriptor();
final boolean unstableDetectionEnabled = unstableRelinkThreshold > 0;
final boolean callSiteUnstable = unstableDetectionEnabled && relinkCount >= unstableRelinkThreshold;
final LinkRequest linkRequest =
runtimeContextArgCount == 0 ?
new LinkRequestImpl(callSiteDescriptor, callSite, relinkCount, callSiteUnstable, arguments) :
new RuntimeContextLinkRequestImpl(callSiteDescriptor, callSite, relinkCount, callSiteUnstable, arguments, runtimeContextArgCount);
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);
}
}
// Make sure we filter the invocation before linking it into the call site. This is typically used to match the
// return type of the invocation to the call site.
guardedInvocation = prelinkFilter.filter(guardedInvocation, linkRequest, linkerServices);
Objects.requireNonNull(guardedInvocation);
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();
}
/**
* Relinks a call site conforming to the invocation arguments.
*
* @param callSite the call site itself
* @param arguments arguments to the invocation
*
* @return return the method handle for the invocation
*
* @throws Exception rethrows any exception thrown by the linkers
*/
@SuppressWarnings("unused")
private MethodHandle relink(final RelinkableCallSite callSite, final int relinkCount, final Object... arguments) throws Exception {
final CallSiteDescriptor callSiteDescriptor = callSite.getDescriptor();
final boolean unstableDetectionEnabled = unstableRelinkThreshold > 0;
final boolean callSiteUnstable = unstableDetectionEnabled && relinkCount >= unstableRelinkThreshold;
final LinkRequest linkRequest =
runtimeContextArgCount == 0 ?
new LinkRequestImpl(callSiteDescriptor, callSite, relinkCount, callSiteUnstable, arguments) :
new RuntimeContextLinkRequestImpl(callSiteDescriptor, callSite, relinkCount, callSiteUnstable, arguments, runtimeContextArgCount);
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);
}
}
// Make sure we filter the invocation before linking it into the call site. This is typically used to match the
// return type of the invocation to the call site.
guardedInvocation = prelinkFilter.filter(guardedInvocation, linkRequest, linkerServices);
Objects.requireNonNull(guardedInvocation);
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();
}
/**
* Relinks a call site conforming to the invocation arguments.
*
* @param callSite the call site itself
* @param arguments arguments to the invocation
*
* @return return the method handle for the invocation
*
* @throws Exception rethrows any exception thrown by the linkers
*/
@SuppressWarnings("unused")
private MethodHandle relink(final RelinkableCallSite callSite, final int relinkCount, final Object... arguments) throws Exception {
final CallSiteDescriptor callSiteDescriptor = callSite.getDescriptor();
final boolean unstableDetectionEnabled = unstableRelinkThreshold > 0;
final boolean callSiteUnstable = unstableDetectionEnabled && relinkCount >= unstableRelinkThreshold;
final LinkRequest linkRequest =
runtimeContextArgCount == 0 ?
new LinkRequestImpl(callSiteDescriptor, callSite, relinkCount, callSiteUnstable, arguments) :
new RuntimeContextLinkRequestImpl(callSiteDescriptor, callSite, relinkCount, callSiteUnstable, arguments, runtimeContextArgCount);
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);
}
}
// Make sure we filter the invocation before linking it into the call site. This is typically used to match the
// return type of the invocation to the call site.
guardedInvocation = prelinkFilter.filter(guardedInvocation, linkRequest, linkerServices);
Objects.requireNonNull(guardedInvocation);
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();
}
/**
* Relinks a call site conforming to the invocation arguments.
*
* @param callSite the call site itself
* @param arguments arguments to the invocation
*
* @return return the method handle for the invocation
*
* @throws Exception rethrows any exception thrown by the linkers
*/
@SuppressWarnings("unused")
private MethodHandle relink(final RelinkableCallSite callSite, final int relinkCount, final Object... arguments) throws Exception {
final CallSiteDescriptor callSiteDescriptor = callSite.getDescriptor();
final boolean unstableDetectionEnabled = unstableRelinkThreshold > 0;
final boolean callSiteUnstable = unstableDetectionEnabled && relinkCount >= unstableRelinkThreshold;
final LinkRequest linkRequest =
runtimeContextArgCount == 0 ?
new LinkRequestImpl(callSiteDescriptor, callSite, relinkCount, callSiteUnstable, arguments) :
new RuntimeContextLinkRequestImpl(callSiteDescriptor, callSite, relinkCount, callSiteUnstable, arguments, runtimeContextArgCount);
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);
}
}
// Make sure we filter the invocation before linking it into the call site. This is typically used to match the
// return type of the invocation to the call site.
guardedInvocation = prelinkFilter.filter(guardedInvocation, linkRequest, linkerServices);
Objects.requireNonNull(guardedInvocation);
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();
}
/**
* Relinks a call site conforming to the invocation arguments.
*
* @param callSite the call site itself
* @param arguments arguments to the invocation
*
* @return return the method handle for the invocation
*
* @throws Exception rethrows any exception thrown by the linkers
*/
@SuppressWarnings("unused")
private MethodHandle relink(final RelinkableCallSite callSite, final int relinkCount, final Object... arguments) throws Exception {
final CallSiteDescriptor callSiteDescriptor = callSite.getDescriptor();
final boolean unstableDetectionEnabled = unstableRelinkThreshold > 0;
final boolean callSiteUnstable = unstableDetectionEnabled && relinkCount >= unstableRelinkThreshold;
final LinkRequest linkRequest =
runtimeContextArgCount == 0 ?
new LinkRequestImpl(callSiteDescriptor, callSite, relinkCount, callSiteUnstable, arguments) :
new RuntimeContextLinkRequestImpl(callSiteDescriptor, callSite, relinkCount, callSiteUnstable, arguments, runtimeContextArgCount);
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);
}
}
// Make sure we filter the invocation before linking it into the call site. This is typically used to match the
// return type of the invocation to the call site.
guardedInvocation = prelinkFilter.filter(guardedInvocation, linkRequest, linkerServices);
Objects.requireNonNull(guardedInvocation);
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();
}
/**
* Relinks a call site conforming to the invocation arguments.
*
* @param callSite the call site itself
* @param arguments arguments to the invocation
* @return return the method handle for the invocation
* @throws Exception rethrows any exception thrown by the linkers
*/
@SuppressWarnings("unused")
private MethodHandle relink(RelinkableCallSite callSite, int relinkCount, Object... arguments) throws Exception {
final CallSiteDescriptor callSiteDescriptor = callSite.getDescriptor();
final boolean unstableDetectionEnabled = unstableRelinkThreshold > 0;
final boolean callSiteUnstable = unstableDetectionEnabled && relinkCount >= unstableRelinkThreshold;
final LinkRequest linkRequest =
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();
}
/**
* Relinks a call site conforming to the invocation arguments.
*
* @param callSite the call site itself
* @param arguments arguments to the invocation
* @return return the method handle for the invocation
* @throws Exception rethrows any exception thrown by the linkers
*/
@SuppressWarnings("unused")
private MethodHandle relink(RelinkableCallSite callSite, int relinkCount, Object... arguments) throws Exception {
final CallSiteDescriptor callSiteDescriptor = callSite.getDescriptor();
final boolean unstableDetectionEnabled = unstableRelinkThreshold > 0;
final boolean callSiteUnstable = unstableDetectionEnabled && relinkCount >= unstableRelinkThreshold;
final LinkRequest linkRequest =
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();
}
/**
* Relinks a call site conforming to the invocation arguments.
*
* @param callSite the call site itself
* @param arguments arguments to the invocation
*
* @return return the method handle for the invocation
*
* @throws Exception rethrows any exception thrown by the linkers
*/
@SuppressWarnings("unused")
private MethodHandle relink(final RelinkableCallSite callSite, final int relinkCount, final Object... arguments) throws Exception {
final CallSiteDescriptor callSiteDescriptor = callSite.getDescriptor();
final boolean unstableDetectionEnabled = unstableRelinkThreshold > 0;
final boolean callSiteUnstable = unstableDetectionEnabled && relinkCount >= unstableRelinkThreshold;
final LinkRequest linkRequest =
runtimeContextArgCount == 0 ?
new LinkRequestImpl(callSiteDescriptor, callSite, relinkCount, callSiteUnstable, arguments) :
new RuntimeContextLinkRequestImpl(callSiteDescriptor, callSite, relinkCount, callSiteUnstable, arguments, runtimeContextArgCount);
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);
}
}
// Make sure we filter the invocation before linking it into the call site. This is typically used to match the
// return type of the invocation to the call site.
guardedInvocation = prelinkFilter.filter(guardedInvocation, linkRequest, linkerServices);
Objects.requireNonNull(guardedInvocation);
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();
}
/**
* Relinks a call site conforming to the invocation arguments.
*
* @param callSite the call site itself
* @param arguments arguments to the invocation
* @return return the method handle for the invocation
* @throws Exception rethrows any exception thrown by the linkers
*/
@SuppressWarnings("unused")
private MethodHandle relink(RelinkableCallSite callSite, int relinkCount, Object... arguments) throws Exception {
final CallSiteDescriptor callSiteDescriptor = callSite.getDescriptor();
final boolean unstableDetectionEnabled = unstableRelinkThreshold > 0;
final boolean callSiteUnstable = unstableDetectionEnabled && relinkCount >= unstableRelinkThreshold;
final LinkRequest linkRequest =
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();
}
public synchronized static void resetAll() {
for (BaseCallSite callsite : callsites) {
callsite.reset();
}
MutableCallSite.syncAll(callsites.toArray(new MutableCallSite[callsites.size()]));
}
/**
* Load JCas types for some combination of class loader and type system
* Some of these classes may have already been loaded for this type system
* Some of these classes may have already been loaded (perhaps for another type system)
* @param ts the type system
* @param isDoUserJCasLoading always true, left in for experimentation in the future with dynamic generation of JCas classes
* @param cl the class loader. For Pears, is the pear class loader
*/
private static synchronized void loadJCasForTSandClassLoader(
TypeSystemImpl ts,
boolean isDoUserJCasLoading,
ClassLoader cl,
Map<String, JCasClassInfo> type2jcci) {
// boolean alreadyPartiallyLoaded = false; // true if any JCas types for this class loader have previously been loaded
// synchronized (cl2t2j) {
// type2jcci = cl2t2j.get(cl);
//
// if (null == type2jcci) {
// type2jcci = new HashMap<>();
// cl2t2j.put(cl, type2jcci);
// } else {
// alreadyPartiallyLoaded = true;
// }
// }
/**
* copy in built-ins
* update t2jcci (if not already loaded) with load info for type
* update type system's map from unique JCasID to the type in this type system
*/
/* ============================== */
/* BUILT-INS */
/* ============================== */
for (int typecode = 1; typecode < jcasClassesInfoForBuiltins.length; typecode++) {
JCasClassInfo jcci = jcasClassesInfoForBuiltins[typecode];
if (jcci != null) {
Class<? extends TOP> jcasClass = jcci.jcasClass;
type2jcci.putIfAbsent(jcasClass.getCanonicalName(), jcci);
setTypeFromJCasIDforBuiltIns(jcci, ts, typecode);
// update call sites not called, was called when
// jcci was created.
// updateAllCallSitesForJCasClass(jcasClass, ts.getTypeForCode(typecode));
}
}
/* ========================================================= */
/* Add all user-defined JCas Types, in subsumption order */
/* ========================================================= */
if (isDoUserJCasLoading) {
/**
* Two passes are needed loading is needed.
* - The first one loads the JCas Cover Classes initializes everything
* -- some of the classes might already be loaded (including the builtins which are loaded once per class loader)
* - The second pass performs the conformance checks between the loaded JCas cover classes, and the current type system.
* This depends on having the TypeImpl's javaClass field be accurate (reflect any loaded JCas types)
*/
// this is this here rather than in a static initializer, because
// we want to use the "cl" parameter to get a version of the
// getMethodHandlesLookup that will have the right (maybe more local) permissions checking.
// This is done by having the UIMA Class loader notice that the class being loaded is
// MHLC, and then dynamically loading in that class loader a copy of the byte code
// for that class.
Lookup lookup = getLookup(cl);
ArrayList<MutableCallSite> callSites_toSync = new ArrayList<>();
maybeLoadJCasAndSubtypes(ts, ts.topType, type2jcci.get(TOP.class.getCanonicalName()), cl, type2jcci, callSites_toSync, lookup);
MutableCallSite[] sync = callSites_toSync.toArray(new MutableCallSite[callSites_toSync.size()]);
MutableCallSite.syncAll(sync);
checkConformance(ts, ts.topType, type2jcci);
}
reportErrors();
}