Skip to content

Commit e71b4ee

Browse files
committed
Use CallInternalMethodNode instead of DirectCallNode for the CallTarget of Method#to_proc
1 parent 152be9f commit e71b4ee

File tree

4 files changed

+35
-31
lines changed

4 files changed

+35
-31
lines changed

spec/truffle/always_inlined_spec.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,4 +113,12 @@
113113
obj = Class.new { attr_reader(*names) }.new
114114
names.each { |name| obj.send(name).should == nil }
115115
end
116+
117+
it "work with each(&method(:always_inlined_method))" do
118+
obj = Class.new do
119+
[:foo].each(&method(:attr_accessor))
120+
end.new
121+
obj.foo = 42
122+
obj.foo.should == 42
123+
end
116124
end

src/main/java/org/truffleruby/builtins/ReRaiseInlinedExceptionNode.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import com.oracle.truffle.api.CompilerDirectives;
2020
import com.oracle.truffle.api.frame.VirtualFrame;
2121

22+
import java.util.Arrays;
23+
2224
public class ReRaiseInlinedExceptionNode extends RubyContextSourceNode {
2325

2426
public final NodeFactory<? extends RubyBaseNode> nodeFactory;
@@ -31,8 +33,10 @@ public ReRaiseInlinedExceptionNode(NodeFactory<? extends RubyBaseNode> nodeFacto
3133
public Object execute(VirtualFrame frame) {
3234
final Object[] arguments = frame.getArguments();
3335
if (arguments.length != 1 || !(arguments[0] instanceof RaiseException)) {
36+
CompilerDirectives.transferToInterpreterAndInvalidate();
3437
throw CompilerDirectives.shouldNotReachHere(
35-
"CallTarget of always-inlined builtin should be called with a single RaiseException argument");
38+
"CallTarget of always-inlined builtin should be called with a single RaiseException argument" +
39+
", but was called with: " + Arrays.toString(arguments));
3640
}
3741

3842
final RaiseException raiseException = (RaiseException) arguments[0];

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

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import org.truffleruby.language.arguments.RubyArguments;
3939
import org.truffleruby.language.control.RaiseException;
4040
import org.truffleruby.language.methods.CallBoundMethodNode;
41+
import org.truffleruby.language.methods.CallInternalMethodNode;
4142
import org.truffleruby.language.methods.InternalMethod;
4243
import org.truffleruby.language.objects.AllocationTracing;
4344
import org.truffleruby.language.objects.MetaClassNode;
@@ -51,7 +52,6 @@
5152
import com.oracle.truffle.api.dsl.Specialization;
5253
import com.oracle.truffle.api.frame.MaterializedFrame;
5354
import com.oracle.truffle.api.frame.VirtualFrame;
54-
import com.oracle.truffle.api.nodes.DirectCallNode;
5555
import com.oracle.truffle.api.nodes.RootNode;
5656
import com.oracle.truffle.api.source.SourceSection;
5757

@@ -132,8 +132,7 @@ public abstract static class CallNode extends CoreMethodArrayArgumentsNode {
132132

133133
@Specialization
134134
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);
137136
}
138137

139138
}
@@ -320,20 +319,21 @@ private RubyProc createProc(RootCallTarget callTarget, InternalMethod method, Ob
320319
protected RootCallTarget methodCallTarget(InternalMethod method) {
321320
// translate to something like:
322321
// 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.
324324

325325
final SourceSection sourceSection = method.getSharedMethodInfo().getSourceSection();
326-
final RubyRootNode oldRootNode = RubyRootNode.of(method.getCallTarget());
326+
final RubyRootNode methodRootNode = RubyRootNode.of(method.getCallTarget());
327327

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(
330330
getLanguage(),
331331
sourceSection,
332-
oldRootNode.getFrameDescriptor(),
332+
methodRootNode.getFrameDescriptor(),
333333
method.getSharedMethodInfo(),
334334
setReceiverNode,
335-
oldRootNode.getSplit());
336-
return Truffle.getRuntime().createCallTarget(newRootNode);
335+
methodRootNode.getSplit());
336+
return Truffle.getRuntime().createCallTarget(wrapRootNode);
337337
}
338338

339339
protected int getCacheLimit() {
@@ -378,23 +378,24 @@ protected boolean unbound(RubyUnboundMethod rubyMethod) {
378378
}
379379

380380
private static class SetReceiverNode extends RubyContextSourceNode {
381+
private final InternalMethod method;
382+
@Child private CallInternalMethodNode callInternalMethodNode = CallInternalMethodNode.create();
381383

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;
386386
}
387387

388388
@Override
389389
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));
396398
}
397-
398399
}
399400

400401
@CoreMethod(names = { "__allocate__", "__layout_allocate__" }, constructor = true, visibility = Visibility.PRIVATE)

src/main/java/org/truffleruby/language/arguments/RubyArguments.java

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -142,15 +142,6 @@ public static SpecialVariableStorage getCallerStorage(Frame frame) {
142142
}
143143
}
144144

145-
public static FrameAndVariables getCallerFrameAndVariables(Frame frame) {
146-
Object frameOrVariables = frame.getArguments()[ArgumentIndicies.CALLER_FRAME_OR_VARIABLES.ordinal()];
147-
if (frameOrVariables instanceof FrameAndVariables) {
148-
return (FrameAndVariables) frameOrVariables;
149-
} else {
150-
return null;
151-
}
152-
}
153-
154145
public static InternalMethod getMethod(Frame frame) {
155146
return (InternalMethod) frame.getArguments()[ArgumentIndicies.METHOD.ordinal()];
156147
}

0 commit comments

Comments
 (0)