Skip to content

Commit 66d3f13

Browse files
committed
Simplify sending and reading the caller frame and variables storage
* Now that #__send__/#send no longer need to forward through the caller data. * Makes the separation between reading nodes and sending nodes clearer.
1 parent 68f5a5f commit 66d3f13

10 files changed

+27
-141
lines changed

src/main/java/org/truffleruby/core/kernel/TruffleKernelNodes.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -319,15 +319,14 @@ public static GetSpecialVariableStorage create() {
319319
return GetSpecialVariableStorageNodeGen.create();
320320
}
321321

322-
public void startSending(Reads variables, Reads frame) {
323-
if (variables == Reads.CALLER || frame == Reads.CALLER) {
324-
throw CompilerDirectives.shouldNotReachHere();
325-
}
326-
if (frame == Reads.SELF) {
322+
@Override
323+
public void startSending(boolean variables, boolean frame) {
324+
if (frame) {
327325
replace(new ReadOwnFrameAndVariablesNode(), "Starting to read own frame and variables");
328326
}
329327
}
330328

329+
@Override
331330
public boolean sendingFrame() {
332331
return false;
333332
}

src/main/java/org/truffleruby/language/CallStackManager.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,6 @@ public InternalMethod getCallingMethod() {
9898
return tryGetMethod(getCallerFrame(FrameAccess.READ_ONLY));
9999
}
100100

101-
public boolean callerIsSend() {
102-
return false; // TODO (eregon, 2 Feb 2021): simplify callers
103-
}
104-
105101
// SourceSection
106102

107103
@TruffleBoundary

src/main/java/org/truffleruby/language/FrameAndVariablesSendingNode.java

Lines changed: 12 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,19 @@
1616
import org.truffleruby.language.arguments.ReadCallerFrameNode;
1717
import org.truffleruby.language.arguments.ReadCallerVariablesNode;
1818

19-
import org.truffleruby.language.FrameOrVariablesReadingNode.Reads;
2019
import org.truffleruby.language.methods.DeclarationContext;
2120
import org.truffleruby.language.threadlocal.SpecialVariableStorage;
2221

2322
/** Some Ruby methods need access to the caller frame (the frame active when the method call was made) or to the storage
2423
* of special variables within that frame: see usages of {@link ReadCallerFrameNode} and {@link ReadCallerVariablesNode}
2524
* . This is notably used to get hold of instances of {@link DeclarationContext} and {@link RubyBinding} and methods
26-
* which need to access the last regexp match or the last io line.
25+
* which need to access the last regexp MatchData or the last IO line.
2726
*
2827
* <p>
2928
* This means that when making a method call, we might need to pass down its {@link Frame} or
3029
* {@link SpecialVariableStorage} active when the method call was made.
3130
*
3231
* <p>
33-
* When retrieving the frame or special variable storage in a method called through the Ruby {@code #send} method, we
34-
* must not retrieve the frame of the actual call (made by {@code #send}) but the frame of the {@code #send} call
35-
* itself.
36-
*
37-
* <p>
3832
* Materializing a frame is expensive, and the point of this parent node is to only materialize the frame when we know
3933
* for sure it has been requested by the callee. It is also possible to walk the stack to retrieve the frame to
4034
* materialize - but this is even slower and causes a deoptimization in the callee every time we walk the stack.
@@ -43,10 +37,12 @@
4337
* This class works in tandem with {@link FrameOrVariablesReadingNode} for this purpose. At first, we don't send down
4438
* the frame. If the callee needs it, it will de-optimize and walk the stack to retrieve it (slow). It will also call
4539
* {@link #startSendingOwnFrame()}}, so that the next time the method is called, the frame will be passed down and the
46-
* method does not need further de-optimizations. (Note in the case of {@code #send} calls, we need to recursively call
47-
* {@link ReadCallerFrameNode} to get the parent frame!) {@link ReadCallerVariablesNode} is used similarly to access
48-
* special variable storage, but for child nodes that only require access to this storage ensures they receive an object
49-
* that will not require node splitting to be accessed efficiently. */
40+
* method does not need further de-optimizations.
41+
*
42+
* <p>
43+
* {@link ReadCallerVariablesNode} is used similarly to access special variable storage, but for child nodes that only
44+
* require access to this storage ensures they receive an object that will not require node splitting to be accessed
45+
* efficiently. */
5046
@SuppressFBWarnings("IS")
5147
public abstract class FrameAndVariablesSendingNode extends RubyContextNode {
5248

@@ -60,37 +56,23 @@ public boolean sendingFrames() {
6056
}
6157
}
6258

63-
private synchronized void startSending(Reads variables, Reads frame) {
59+
private synchronized void startSending(boolean variables, boolean frame) {
6460
if (readingNode != null) {
6561
readingNode.startSending(variables, frame);
66-
} else if (variables == Reads.SELF && frame == Reads.NOTHING) {
62+
} else if (variables && !frame) {
6763
readingNode = insert(GetSpecialVariableStorage.create());
68-
} else if (variables == Reads.NOTHING && frame == Reads.SELF) {
64+
} else if (!variables && frame) {
6965
readingNode = insert(new ReadOwnFrameNode());
70-
} else if (variables == Reads.CALLER && frame == Reads.NOTHING) {
71-
readingNode = insert(new ReadCallerFrameNode());
72-
} else if (variables == Reads.NOTHING && frame == Reads.CALLER) {
73-
readingNode = insert(new ReadCallerVariablesNode());
7466
}
7567
}
7668

7769
/** Whether we are sending down the frame (because the called method reads it). */
7870
public void startSendingOwnFrame() {
79-
RubyRootNode root = (RubyRootNode) getRootNode();
80-
if (getContext().getCoreLibrary().isSend(root.getSharedMethodInfo())) {
81-
startSending(Reads.NOTHING, Reads.CALLER);
82-
} else {
83-
startSending(Reads.NOTHING, Reads.SELF);
84-
}
71+
startSending(false, true);
8572
}
8673

8774
public void startSendingOwnVariables() {
88-
RubyRootNode root = (RubyRootNode) getRootNode();
89-
if (getContext().getCoreLibrary().isSend(root.getSharedMethodInfo())) {
90-
startSending(Reads.CALLER, Reads.NOTHING);
91-
} else {
92-
startSending(Reads.SELF, Reads.NOTHING);
93-
}
75+
startSending(true, false);
9476
}
9577

9678
public Object getFrameOrStorageIfRequired(Frame frame) {

src/main/java/org/truffleruby/language/FrameOrVariablesReadingNode.java

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,13 @@
1212
import com.oracle.truffle.api.frame.Frame;
1313
import com.oracle.truffle.api.nodes.NodeInterface;
1414

15+
/** See {@link FrameAndVariablesSendingNode}. Nodes implementing this interface are used to read the data from the
16+
* current frame, before a call. */
1517
public interface FrameOrVariablesReadingNode extends NodeInterface {
1618

17-
public static enum Reads {
18-
NOTHING, // callees don't need to read the frame
19-
SELF, // for most calls
20-
CALLER; // for `send` calls
21-
}
22-
2319
public Object execute(Frame frame);
2420

25-
public void startSending(Reads variables, Reads frame);
21+
public void startSending(boolean variables, boolean frame);
2622

2723
public boolean sendingFrame();
2824
}

src/main/java/org/truffleruby/language/ReadOwnFrameAndVariablesNode.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
*/
1010
package org.truffleruby.language;
1111

12-
import com.oracle.truffle.api.CompilerDirectives;
1312
import com.oracle.truffle.api.frame.Frame;
1413
import org.truffleruby.core.kernel.TruffleKernelNodes.GetSpecialVariableStorage;
1514

@@ -21,12 +20,11 @@ public Object execute(Frame frame) {
2120
return new FrameAndVariables(readVariablesNode.execute(frame), frame.materialize());
2221
}
2322

24-
public void startSending(Reads variables, Reads frame) {
25-
if (variables == Reads.CALLER || frame == Reads.CALLER) {
26-
throw CompilerDirectives.shouldNotReachHere();
27-
}
23+
@Override
24+
public void startSending(boolean variables, boolean frame) {
2825
}
2926

27+
@Override
3028
public boolean sendingFrame() {
3129
return true;
3230
}

src/main/java/org/truffleruby/language/ReadOwnFrameNode.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
*/
1010
package org.truffleruby.language;
1111

12-
import com.oracle.truffle.api.CompilerDirectives;
1312
import com.oracle.truffle.api.frame.Frame;
1413

1514
public class ReadOwnFrameNode extends RubyBaseNode implements FrameOrVariablesReadingNode {
@@ -18,15 +17,14 @@ public Object execute(Frame frame) {
1817
return frame.materialize();
1918
}
2019

21-
public void startSending(Reads variables, Reads frame) {
22-
if (variables == Reads.CALLER || frame == Reads.CALLER) {
23-
throw CompilerDirectives.shouldNotReachHere();
24-
}
25-
if (variables == Reads.SELF) {
20+
@Override
21+
public void startSending(boolean variables, boolean frame) {
22+
if (variables) {
2623
replace(new ReadOwnFrameAndVariablesNode(), "Starting to read own frame and variables");
2724
}
2825
}
2926

27+
@Override
3028
public boolean sendingFrame() {
3129
return true;
3230
}

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,11 @@
1919
import com.oracle.truffle.api.nodes.Node;
2020
import com.oracle.truffle.api.profiles.ConditionProfile;
2121

22-
import org.truffleruby.language.FrameOrVariablesReadingNode;
2322
import org.truffleruby.language.FrameAndVariablesSendingNode;
2423
import org.truffleruby.language.NotOptimizedWarningNode;
2524
import org.truffleruby.language.RubyContextNode;
2625

27-
public abstract class ReadCallerDataNode extends RubyContextNode implements FrameOrVariablesReadingNode {
26+
public abstract class ReadCallerDataNode extends RubyContextNode {
2827

2928
private final ConditionProfile callerDataProfile = ConditionProfile.create();
3029
@Child private NotOptimizedWarningNode notOptimizedNode = null;

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

Lines changed: 0 additions & 55 deletions
This file was deleted.

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

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
import com.oracle.truffle.api.frame.Frame;
1313
import org.truffleruby.language.FrameAndVariablesSendingNode;
1414

15-
import com.oracle.truffle.api.CompilerDirectives;
1615
import com.oracle.truffle.api.frame.MaterializedFrame;
1716

1817
public class ReadCallerFrameNode extends ReadCallerDataNode {
@@ -41,17 +40,4 @@ protected Object getDataFromFrame(MaterializedFrame frame) {
4140
return frame;
4241
}
4342

44-
public void startSending(Reads variables, Reads frame) {
45-
if (variables == Reads.SELF || frame == Reads.SELF) {
46-
throw CompilerDirectives.shouldNotReachHere();
47-
}
48-
if (variables == Reads.CALLER) {
49-
replace(new ReadCallerFrameAndVariablesNode(), "Starting to read caller frame and variables");
50-
}
51-
}
52-
53-
54-
public boolean sendingFrame() {
55-
return true;
56-
}
5743
}

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

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import org.truffleruby.core.kernel.TruffleKernelNodes;
1515
import org.truffleruby.language.FrameAndVariablesSendingNode;
1616

17-
import com.oracle.truffle.api.CompilerDirectives;
1817
import com.oracle.truffle.api.frame.MaterializedFrame;
1918

2019
public class ReadCallerVariablesNode extends ReadCallerDataNode {
@@ -43,16 +42,4 @@ protected Object getDataFromFrame(MaterializedFrame frame) {
4342
return TruffleKernelNodes.GetSpecialVariableStorage.getSlow(frame);
4443
}
4544

46-
public void startSending(Reads variables, Reads frame) {
47-
if (variables == Reads.SELF || frame == Reads.SELF) {
48-
throw CompilerDirectives.shouldNotReachHere();
49-
}
50-
if (frame == Reads.CALLER) {
51-
replace(new ReadCallerFrameAndVariablesNode(), "Starting to read caller frame and variables");
52-
}
53-
}
54-
55-
public boolean sendingFrame() {
56-
return false;
57-
}
5845
}

0 commit comments

Comments
 (0)