Skip to content

Commit

Permalink
Move call info setup closer to handle build
Browse files Browse the repository at this point in the history
Different types of methods will have different mechanisms for
passing the kwargs callInfo along.
* "Generic" handles just using DynamicMethod.call can use the forms
  that take int callInfo. All existing implementations of that set
  the thread-local anyway, but we have at least pushed the flags
  up to this point.
* Jitted Ruby methods do not yet accept callInfo as a paramter so
  all such calls should be wrapped by callInfo thread-local.
* Native core methods do not yet accept callInfo as a parameter so
  all such calls should be wrapped by callInfo thread-local.
* Construction with new/initialize does not yet accept callInfo as
  a parameter so all such calls should be wrapped by callInfo
  thread-local.

I do not believe any other cases being built for indy dispatch
right now end up in core that cares about keywords, so the flags
do not need to be set.
  • Loading branch information
headius committed Nov 9, 2023
1 parent 1e6829d commit 4b7eb42
Showing 1 changed file with 23 additions and 16 deletions.
39 changes: 23 additions & 16 deletions core/src/main/java/org/jruby/ir/targets/indy/InvokeSite.java
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ MethodHandle buildGenericHandle(CacheEntry entry) {
if (signature.argOffset("block") != -1) {
binder = binder.permute("method", "context", "self", "rubyClass", "name", "callInfo", "block", "args");
}
} else {
binder = setThreadLocalCallInfo(binder);
}

if (Options.INVOKEDYNAMIC_LOG_BINDING.load()) {
Expand All @@ -193,6 +195,18 @@ MethodHandle buildGenericHandle(CacheEntry entry) {
return binder.invokeVirtualQuiet(LOOKUP, "call").handle();
}

private SmartBinder setThreadLocalCallInfo(SmartBinder binder) {
SmartHandle callInfoWrapper;
SmartBinder baseBinder = SmartBinder.from(binder.signature().changeReturn(void.class)).permute("context");
if (flags == 0) {
callInfoWrapper = baseBinder.invokeVirtualQuiet(LOOKUP, "clearCallInfo");
} else {
callInfoWrapper = baseBinder.append("flags", flags).invokeStaticQuiet(LOOKUP, IRRuntimeHelpers.class, "setCallInfo");
}
binder = binder.foldVoid(callInfoWrapper);
return binder;
}

private static SmartBinder permuteForGenericCall(SmartBinder binder, DynamicMethod method, String... basePermutes) {
if (methodWantsBlock(method)) {
binder = binder.permute(arrayOf(basePermutes, "block", String[]::new));
Expand Down Expand Up @@ -393,6 +407,9 @@ MethodHandle buildJittedHandle(CacheEntry entry, boolean blockGiven) {
binder = SmartBinder.from(signature)
.permute("context", "self", "arg.*", "block");

// no jitted forms accept callInfo yet so we always set in thread local
binder = setThreadLocalCallInfo(binder);

if (arity == -1) {
// already [], nothing to do
mh = (MethodHandle)compiledIRMethod.getHandle();
Expand Down Expand Up @@ -477,6 +494,9 @@ MethodHandle buildNativeHandle(CacheEntry entry, boolean blockGiven) {

if (binder != null) {

// no native methods accept callInfo directly, so we always set thread local
binder = setThreadLocalCallInfo(binder);

// clean up non-arguments, ordering, types
if (!nc.hasContext()) {
binder = binder.drop("context");
Expand Down Expand Up @@ -660,8 +680,7 @@ public IRubyObject invoke(ThreadContext context, IRubyObject caller, IRubyObject
mh = getHandle(self, entry);
}

boolean needsCallInfo = arity > -1 && arity < 4;
finishBinding(entry, mh, self, selfClass, switchPoint, needsCallInfo);
finishBinding(entry, mh, self, selfClass, switchPoint);

return performIndirectCall(context, self, args, block, methodName, passSymbol, entry);
}
Expand All @@ -684,8 +703,7 @@ public IRubyObject invoke(ThreadContext context, IRubyObject self, IRubyObject[]
mh = getHandle(self, entry);
}

boolean needsCallInfo = arity > -1 && arity < 4;
finishBinding(entry, mh, self, selfClass, switchPoint, needsCallInfo);
finishBinding(entry, mh, self, selfClass, switchPoint);

return performIndirectCall(context, self, args, block, methodName, passSymbol, entry);
}
Expand All @@ -702,24 +720,13 @@ private CacheEntry methodMissingEntry(ThreadContext context, RubyClass selfClass
return Helpers.createMethodMissingEntry(context, selfClass, callType, visibility, entry.token, methodName);
}

private void finishBinding(CacheEntry entry, MethodHandle mh, IRubyObject self, RubyClass selfClass, SwitchPoint switchPoint, boolean needsCallInfo) {
private void finishBinding(CacheEntry entry, MethodHandle mh, IRubyObject self, RubyClass selfClass, SwitchPoint switchPoint) {
if (literalClosure) {
mh = Binder.from(mh.type())
.tryFinally(getBlockEscape(signature))
.invoke(mh);
}

if (needsCallInfo) {
SmartHandle callInfoWrapper;
SmartBinder baseBinder = SmartBinder.from(signature.changeReturn(void.class)).permute("context");
if (flags == 0) {
callInfoWrapper = baseBinder.invokeVirtualQuiet(LOOKUP, "clearCallInfo");
} else {
callInfoWrapper = baseBinder.append("flags", flags).invokeStaticQuiet(LOOKUP, IRRuntimeHelpers.class, "setCallInfo");
}
mh = foldArguments(mh, callInfoWrapper.handle());
}

updateInvocationTarget(mh, self, selfClass, entry.method, switchPoint);
}

Expand Down

0 comments on commit 4b7eb42

Please sign in to comment.