|
38 | 38 | import org.truffleruby.language.arguments.RubyArguments;
|
39 | 39 | import org.truffleruby.language.control.RaiseException;
|
40 | 40 | import org.truffleruby.language.methods.CallBoundMethodNode;
|
| 41 | +import org.truffleruby.language.methods.CallInternalMethodNode; |
41 | 42 | import org.truffleruby.language.methods.InternalMethod;
|
42 | 43 | import org.truffleruby.language.objects.AllocationTracing;
|
43 | 44 | import org.truffleruby.language.objects.MetaClassNode;
|
|
51 | 52 | import com.oracle.truffle.api.dsl.Specialization;
|
52 | 53 | import com.oracle.truffle.api.frame.MaterializedFrame;
|
53 | 54 | import com.oracle.truffle.api.frame.VirtualFrame;
|
54 |
| -import com.oracle.truffle.api.nodes.DirectCallNode; |
55 | 55 | import com.oracle.truffle.api.nodes.RootNode;
|
56 | 56 | import com.oracle.truffle.api.source.SourceSection;
|
57 | 57 |
|
@@ -132,8 +132,7 @@ public abstract static class CallNode extends CoreMethodArrayArgumentsNode {
|
132 | 132 |
|
133 | 133 | @Specialization
|
134 | 134 | protected Object call(VirtualFrame frame, RubyMethod method, Object[] arguments, Object maybeBlock) {
|
135 |
| - return callBoundMethodNode |
136 |
| - .execute(frame, method, arguments, maybeBlock); |
| 135 | + return callBoundMethodNode.execute(frame, method, arguments, maybeBlock); |
137 | 136 | }
|
138 | 137 |
|
139 | 138 | }
|
@@ -320,20 +319,21 @@ private RubyProc createProc(RootCallTarget callTarget, InternalMethod method, Ob
|
320 | 319 | protected RootCallTarget methodCallTarget(InternalMethod method) {
|
321 | 320 | // translate to something like:
|
322 | 321 | // lambda { |same args list| method.call(args) }
|
323 |
| - // We need to preserve the method receiver and we want to have the same argument list |
| 322 | + // We need to preserve the method receiver and we want to have the same argument list. |
| 323 | + // We create a new CallTarget for the Proc that calls the method CallTarget and passes the correct receiver. |
324 | 324 |
|
325 | 325 | final SourceSection sourceSection = method.getSharedMethodInfo().getSourceSection();
|
326 |
| - final RubyRootNode oldRootNode = RubyRootNode.of(method.getCallTarget()); |
| 326 | + final RubyRootNode methodRootNode = RubyRootNode.of(method.getCallTarget()); |
327 | 327 |
|
328 |
| - final SetReceiverNode setReceiverNode = new SetReceiverNode(method.getCallTarget()); |
329 |
| - final RootNode newRootNode = new RubyRootNode( |
| 328 | + final SetReceiverNode setReceiverNode = new SetReceiverNode(method); |
| 329 | + final RootNode wrapRootNode = new RubyRootNode( |
330 | 330 | getLanguage(),
|
331 | 331 | sourceSection,
|
332 |
| - oldRootNode.getFrameDescriptor(), |
| 332 | + methodRootNode.getFrameDescriptor(), |
333 | 333 | method.getSharedMethodInfo(),
|
334 | 334 | setReceiverNode,
|
335 |
| - oldRootNode.getSplit()); |
336 |
| - return Truffle.getRuntime().createCallTarget(newRootNode); |
| 335 | + methodRootNode.getSplit()); |
| 336 | + return Truffle.getRuntime().createCallTarget(wrapRootNode); |
337 | 337 | }
|
338 | 338 |
|
339 | 339 | protected int getCacheLimit() {
|
@@ -378,23 +378,24 @@ protected boolean unbound(RubyUnboundMethod rubyMethod) {
|
378 | 378 | }
|
379 | 379 |
|
380 | 380 | private static class SetReceiverNode extends RubyContextSourceNode {
|
| 381 | + private final InternalMethod method; |
| 382 | + @Child private CallInternalMethodNode callInternalMethodNode = CallInternalMethodNode.create(); |
381 | 383 |
|
382 |
| - @Child private DirectCallNode methodCallNode; |
383 |
| - |
384 |
| - public SetReceiverNode(RootCallTarget methodCallTarget) { |
385 |
| - this.methodCallNode = DirectCallNode.create(methodCallTarget); |
| 384 | + public SetReceiverNode(InternalMethod method) { |
| 385 | + this.method = method; |
386 | 386 | }
|
387 | 387 |
|
388 | 388 | @Override
|
389 | 389 | public Object execute(VirtualFrame frame) {
|
390 |
| - Object receiver = RubyArguments.getSelf(RubyArguments.getDeclarationFrame(frame)); |
391 |
| - RubyArguments.setSelf(frame, receiver); |
392 |
| - /* Remove the declaration frame from the arguments so that the method will not see the special variables |
393 |
| - * associated with the proc. This matches the behaviour in MRI. */ |
394 |
| - RubyArguments.setDeclarationFrame(frame, null); |
395 |
| - return methodCallNode.call(frame.getArguments()); |
| 390 | + final Object originalBoundMethodReceiver = RubyArguments.getSelf(RubyArguments.getDeclarationFrame(frame)); |
| 391 | + return callInternalMethodNode.execute( |
| 392 | + frame, |
| 393 | + null, |
| 394 | + method, |
| 395 | + originalBoundMethodReceiver, |
| 396 | + RubyArguments.getBlock(frame), |
| 397 | + RubyArguments.getArguments(frame)); |
396 | 398 | }
|
397 |
| - |
398 | 399 | }
|
399 | 400 |
|
400 | 401 | @CoreMethod(names = { "__allocate__", "__layout_allocate__" }, constructor = true, visibility = Visibility.PRIVATE)
|
|
0 commit comments