Skip to content

Commit 1bbf062

Browse files
committed
Cache Method#to_proc result's call target in global cache
1 parent b4fe248 commit 1bbf062

File tree

2 files changed

+14
-27
lines changed

2 files changed

+14
-27
lines changed

src/main/java/org/truffleruby/core/method/MethodNodes.java

Lines changed: 11 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -285,30 +285,18 @@ RubyUnboundMethod unbind(RubyMethod method,
285285
@CoreMethod(names = "to_proc")
286286
public abstract static class ToProcNode extends CoreMethodArrayArgumentsNode {
287287

288-
@Specialization(guards = { "isSingleContext()", "methodObject == cachedMethodObject" },
289-
limit = "getCacheLimit()")
290-
RubyProc toProcCachedSingleContext(RubyMethod methodObject,
291-
@Cached("methodObject") RubyMethod cachedMethodObject,
292-
@Cached("toProcUncached(cachedMethodObject)") RubyProc proc) {
293-
return proc;
294-
}
295-
296-
@Specialization(
297-
guards = "methodObject.method.getCallTarget() == methodCallTarget",
298-
limit = "getCacheLimit()",
299-
replaces = "toProcCachedSingleContext")
300-
RubyProc toProcCachedTarget(RubyMethod methodObject,
301-
@Cached("methodObject.method.getCallTarget()") RootCallTarget methodCallTarget,
302-
@Cached("procCallTargetToCallRubyMethod(methodCallTarget)") RootCallTarget procCallTarget) {
303-
return createProc(procCallTarget, methodObject.method, methodObject.receiver);
304-
}
305-
306-
@Specialization(replaces = { "toProcCachedSingleContext", "toProcCachedTarget" })
307-
RubyProc toProcUncached(RubyMethod methodObject) {
288+
@Specialization
289+
RubyProc toProc(RubyMethod methodObject) {
308290
final InternalMethod method = methodObject.method;
309291
final Object receiver = methodObject.receiver;
310-
final RootCallTarget callTarget = procCallTargetToCallRubyMethod(method.getCallTarget());
311-
return createProc(callTarget, method, receiver);
292+
RootCallTarget toProcCallTarget = method.toProcCallTarget;
293+
294+
if (toProcCallTarget == null) {
295+
toProcCallTarget = createToProcCallTarget(method.getCallTarget());
296+
method.toProcCallTarget = toProcCallTarget;
297+
}
298+
299+
return createProc(toProcCallTarget, method, receiver);
312300
}
313301

314302
private RubyProc createProc(RootCallTarget callTarget, InternalMethod method, Object receiver) {
@@ -331,7 +319,7 @@ private RubyProc createProc(RootCallTarget callTarget, InternalMethod method, Ob
331319
}
332320

333321
@TruffleBoundary
334-
protected RootCallTarget procCallTargetToCallRubyMethod(RootCallTarget callTarget) {
322+
protected RootCallTarget createToProcCallTarget(RootCallTarget callTarget) {
335323
// translate to something like:
336324
// lambda { |same args list| method.call(args) }
337325
// We need to preserve the method receiver and we want to have the same argument list.
@@ -354,10 +342,6 @@ protected RootCallTarget procCallTargetToCallRubyMethod(RootCallTarget callTarge
354342
return wrapRootNode.getCallTarget();
355343
}
356344

357-
protected int getCacheLimit() {
358-
return getLanguage().options.METHOD_TO_PROC_CACHE;
359-
}
360-
361345
private static final class CallWithRubyMethodReceiverNode extends RubyContextSourceNode {
362346
@Child private CallInternalMethodNode callInternalMethodNode = CallInternalMethodNode.create();
363347

src/main/java/org/truffleruby/language/methods/InternalMethod.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ public final class InternalMethod implements ObjectGraphNode {
5757
private final CachedLazyCallTargetSupplier callTargetSupplier;
5858
@CompilationFinal private RootCallTarget callTarget;
5959

60+
/** call target of a Proc created from a method and cached for consequent Method#to_proc calls */
61+
public RootCallTarget toProcCallTarget;
62+
6063
public static InternalMethod fromProc(
6164
RubyContext context,
6265
SharedMethodInfo sharedMethodInfo,

0 commit comments

Comments
 (0)