45
45
import org .truffleruby .language .control .RaiseException ;
46
46
import org .truffleruby .language .methods .CallInternalMethodNode ;
47
47
import org .truffleruby .language .methods .InternalMethod ;
48
+ import org .truffleruby .language .methods .SharedMethodInfo ;
48
49
import org .truffleruby .language .objects .AllocationTracing ;
49
50
import org .truffleruby .language .objects .MetaClassNode ;
50
51
import org .truffleruby .language .threadlocal .SpecialVariableStorage ;
@@ -279,28 +280,29 @@ protected RubyUnboundMethod unbind(RubyMethod method) {
279
280
@ CoreMethod (names = "to_proc" )
280
281
public abstract static class ToProcNode extends CoreMethodArrayArgumentsNode {
281
282
282
- @ Specialization (guards = "methodObject == cachedMethodObject" , limit = "getCacheLimit()" )
283
- protected RubyProc toProcCached (RubyMethod methodObject ,
283
+ @ Specialization (guards = { "isSingleContext()" , "methodObject == cachedMethodObject" },
284
+ limit = "getCacheLimit()" )
285
+ protected RubyProc toProcCachedSingleContext (RubyMethod methodObject ,
284
286
@ Cached ("methodObject" ) RubyMethod cachedMethodObject ,
285
287
@ Cached ("toProcUncached(cachedMethodObject)" ) RubyProc proc ) {
286
288
return proc ;
287
289
}
288
290
289
291
@ Specialization (
290
- guards = "cachedMethod == methodObject.method " ,
292
+ guards = "methodObject.method.getCallTarget() == methodCallTarget " ,
291
293
limit = "getCacheLimit()" ,
292
- replaces = "toProcCached " )
294
+ replaces = "toProcCachedSingleContext " )
293
295
protected RubyProc toProcCachedTarget (RubyMethod methodObject ,
294
- @ Cached ("methodObject.method" ) InternalMethod cachedMethod ,
295
- @ Cached ("methodCallTarget(cachedMethod )" ) RootCallTarget callTarget ) {
296
- return createProc (callTarget , cachedMethod , methodObject .receiver );
296
+ @ Cached ("methodObject.method.getCallTarget() " ) RootCallTarget methodCallTarget ,
297
+ @ Cached ("procCallTargetToCallRubyMethod(methodCallTarget )" ) RootCallTarget procCallTarget ) {
298
+ return createProc (procCallTarget , methodObject . method , methodObject .receiver );
297
299
}
298
300
299
- @ Specialization
301
+ @ Specialization ( replaces = { "toProcCachedSingleContext" , "toProcCachedTarget" })
300
302
protected RubyProc toProcUncached (RubyMethod methodObject ) {
301
303
final InternalMethod method = methodObject .method ;
302
- final RootCallTarget callTarget = methodCallTarget (method );
303
304
final Object receiver = methodObject .receiver ;
305
+ final RootCallTarget callTarget = procCallTargetToCallRubyMethod (method .getCallTarget ());
304
306
return createProc (callTarget , method , receiver );
305
307
}
306
308
@@ -324,26 +326,26 @@ private RubyProc createProc(RootCallTarget callTarget, InternalMethod method, Ob
324
326
}
325
327
326
328
@ TruffleBoundary
327
- protected RootCallTarget methodCallTarget ( InternalMethod method ) {
329
+ protected RootCallTarget procCallTargetToCallRubyMethod ( RootCallTarget callTarget ) {
328
330
// translate to something like:
329
331
// lambda { |same args list| method.call(args) }
330
332
// We need to preserve the method receiver and we want to have the same argument list.
331
333
// We create a new CallTarget for the Proc that calls the method CallTarget and passes the correct receiver.
332
334
333
- final SourceSection sourceSection = method . getSharedMethodInfo (). getSourceSection ( );
334
- final RubyRootNode methodRootNode = RubyRootNode . of ( method . getCallTarget () );
335
+ final RubyRootNode methodRootNode = RubyRootNode . of ( callTarget );
336
+ final SharedMethodInfo sharedMethodInfo = methodRootNode . getSharedMethodInfo ( );
335
337
336
- var callWithRubyMethodReceiverNode = new CallWithRubyMethodReceiverNode (method );
338
+ var callWithRubyMethodReceiverNode = new CallWithRubyMethodReceiverNode ();
337
339
final RubyLambdaRootNode wrapRootNode = new RubyLambdaRootNode (
338
340
getLanguage (),
339
- sourceSection ,
341
+ sharedMethodInfo . getSourceSection () ,
340
342
methodRootNode .getFrameDescriptor (),
341
- method . getSharedMethodInfo () ,
343
+ sharedMethodInfo ,
342
344
callWithRubyMethodReceiverNode ,
343
345
methodRootNode .getSplit (),
344
346
methodRootNode .returnID ,
345
347
BreakID .INVALID ,
346
- method . getSharedMethodInfo () .getArity ());
348
+ sharedMethodInfo .getArity ());
347
349
return wrapRootNode .getCallTarget ();
348
350
}
349
351
@@ -352,16 +354,13 @@ protected int getCacheLimit() {
352
354
}
353
355
354
356
private static class CallWithRubyMethodReceiverNode extends RubyContextSourceNode {
355
- private final InternalMethod method ;
356
357
@ Child private CallInternalMethodNode callInternalMethodNode = CallInternalMethodNode .create ();
357
358
358
- public CallWithRubyMethodReceiverNode (InternalMethod method ) {
359
- this .method = method ;
360
- }
361
-
362
359
@ Override
363
360
public Object execute (VirtualFrame frame ) {
364
- final Object receiver = RubyArguments .getSelf (RubyArguments .getDeclarationFrame (frame ));
361
+ final MaterializedFrame declarationFrame = RubyArguments .getDeclarationFrame (frame );
362
+ final Object receiver = RubyArguments .getSelf (declarationFrame );
363
+ final InternalMethod method = RubyArguments .getMethod (declarationFrame );
365
364
return CallNode .callBoundMethod (frame , method , receiver , frame .getArguments (), callInternalMethodNode );
366
365
}
367
366
}
0 commit comments