Skip to content

Commit 41ec137

Browse files
committed
DispatchNode converted to DSL + new special variable search logic
fix: new special variable seachup logic trying to store assuption as cached parameter
1 parent 06cb0ff commit 41ec137

File tree

12 files changed

+156
-208
lines changed

12 files changed

+156
-208
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public Object execute(VirtualFrame frame) {
5353
final Object[] rubyArgs = RubyArguments.repack(frame.getArguments(), receiver, 0, 1);
5454
RubyArguments.setArgument(rubyArgs, 0, methodSymbol);
5555

56-
return toEnumNode.dispatch(null, receiver, "to_enum", rubyArgs, PRIVATE, null);
56+
return toEnumNode.execute(null, receiver, "to_enum", rubyArgs, PRIVATE, null);
5757
} else {
5858
return method.execute(frame);
5959
}

src/main/java/org/truffleruby/core/basicobject/BasicObjectNodes.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,7 @@ protected Object send(Frame callerFrame, Object self, Object[] rubyArgs, RootCal
560560
@Cached DispatchNode dispatchNode,
561561
@Cached NameToJavaStringNode nameToJavaString) {
562562
Object name = RubyArguments.getArgument(rubyArgs, 0);
563-
return dispatchNode.dispatch(callerFrame, self, nameToJavaString.execute(this, name),
563+
return dispatchNode.execute(callerFrame, self, nameToJavaString.execute(this, name),
564564
RubyArguments.repack(rubyArgs, self, 1), PRIVATE, null);
565565
}
566566
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1395,7 +1395,7 @@ protected Object send(Frame callerFrame, Object self, Object[] rubyArgs, RootCal
13951395
@Cached NameToJavaStringNode nameToJavaString) {
13961396
Object name = RubyArguments.getArgument(rubyArgs, 0);
13971397
Object[] newArgs = RubyArguments.repack(rubyArgs, self, 1);
1398-
return dispatchNode.dispatch(callerFrame, self, nameToJavaString.execute(this, name), newArgs, PUBLIC,
1398+
return dispatchNode.execute(callerFrame, self, nameToJavaString.execute(this, name), newArgs, PUBLIC,
13991399
null);
14001400
}
14011401

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.io.IOException;
1313

1414
import com.oracle.truffle.api.RootCallTarget;
15+
import com.oracle.truffle.api.dsl.GenerateUncached;
1516
import com.oracle.truffle.api.dsl.NeverDefault;
1617
import com.oracle.truffle.api.frame.Frame;
1718
import com.oracle.truffle.api.profiles.InlinedConditionProfile;
@@ -213,6 +214,7 @@ public static int declarationDepth(Frame topFrame) {
213214
}
214215

215216
@ImportStatic(TruffleKernelNodes.class)
217+
@GenerateUncached
216218
public abstract static class GetSpecialVariableStorage extends RubyBaseNode {
217219

218220
@NeverDefault

src/main/java/org/truffleruby/core/thread/TruffleThreadNodes.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
2727
import com.oracle.truffle.api.library.CachedLibrary;
2828
import com.oracle.truffle.api.nodes.Node;
29-
import org.truffleruby.language.arguments.ReadCallerVariablesNode;
3029

3130
@CoreModule("Truffle::ThreadOperations")
3231
public abstract class TruffleThreadNodes {
@@ -62,7 +61,7 @@ protected Object findRubyCaller(RubyArray modules,
6261
if (data == null) {
6362
return nil;
6463
} else {
65-
ReadCallerVariablesNode.notifyCallerToSendSpecialVariables(data.callNode);
64+
//ReadCallerVariablesNode.notifyCallerToSendSpecialVariables(data.callNode);
6665
Object variables = storageNode.execute(data.frame.materialize());
6766
getLanguage().getCurrentFiber().extensionCallStack.setSpecialVariables(variables);
6867
return variables;

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

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,15 @@
99
*/
1010
package org.truffleruby.language;
1111

12+
import com.oracle.truffle.api.Assumption;
13+
import com.oracle.truffle.api.dsl.NeverDefault;
1214
import com.oracle.truffle.api.frame.Frame;
1315
import org.truffleruby.annotations.SuppressFBWarnings;
1416
import org.truffleruby.core.kernel.TruffleKernelNodes.GetSpecialVariableStorage;
1517
import org.truffleruby.language.arguments.ReadCallerVariablesNode;
1618

1719
import org.truffleruby.language.threadlocal.SpecialVariableStorage;
20+
import org.truffleruby.parser.ParentFrameDescriptor;
1821

1922
/** Some Ruby methods need access to the caller special variables: see usages of {@link ReadCallerVariablesNode}. This
2023
* is used for methods which need to access the last regexp MatchData or the last IO line.
@@ -30,34 +33,32 @@
3033
* stack.
3134
*
3235
* <p>
33-
* This class works in tandem with {@link GetSpecialVariableStorage} for this purpose. At first, we don't send down the
34-
* {@link SpecialVariableStorage}. If the callee needs it, it will de-optimize and walk the stack to retrieve it (slow).
35-
* It will also call {@link #startSendingOwnVariables()}, so that the next time the method is called, the special
36-
* variables will be passed down and the method does not need further de-optimizations.
37-
*
38-
* <p>
39-
* {@link ReadCallerVariablesNode} is used by child nodes that require access to this storage and this mechanism ensures
40-
* they receive an object that will not require CallTarget splitting to be accessed efficiently (i.e., part of the
41-
* calling convention and not having to find the value in the caller frame). */
36+
* This class works in tandem with {@link GetSpecialVariableStorage} and {@link ReadCallerVariablesNode}. When those two
37+
* classes don't have {@link SpecialVariableStorage} in the frame they will invalidate the exception, so that the next
38+
* time the method is called, the special variables will be passed down. */
4239
@SuppressFBWarnings("IS")
4340
public abstract class SpecialVariablesSendingNode extends RubyBaseNode {
4441

45-
@Child protected GetSpecialVariableStorage readingNode;
42+
@NeverDefault
43+
protected Assumption getSpecialVariableAssumption(Frame frame) {
44+
if (frame == null) {
45+
return getValidAssumption();
46+
}
47+
var currentFrameDescriptor = frame.getFrameDescriptor();
4648

47-
public void startSendingOwnVariables() {
48-
synchronized (this) {
49-
if (readingNode == null) {
50-
readingNode = insert(GetSpecialVariableStorage.create());
49+
while (true) {
50+
if (currentFrameDescriptor.getInfo() == null) {
51+
return getValidAssumption();
52+
}
53+
if (currentFrameDescriptor.getInfo() instanceof ParentFrameDescriptor nextDescriptor) {
54+
currentFrameDescriptor = nextDescriptor.getDescriptor();
55+
} else {
56+
return (Assumption) currentFrameDescriptor.getInfo();
5157
}
5258
}
5359
}
5460

55-
public SpecialVariableStorage getSpecialVariablesIfRequired(Frame frame) {
56-
if (readingNode == null) {
57-
return null;
58-
} else {
59-
return readingNode.execute(frame);
60-
}
61+
protected Assumption getValidAssumption() {
62+
return Assumption.ALWAYS_VALID;
6163
}
62-
6364
}

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

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,14 @@
99
*/
1010
package org.truffleruby.language.arguments;
1111

12-
import com.oracle.truffle.api.CompilerDirectives;
1312
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
1413
import com.oracle.truffle.api.Truffle;
1514
import com.oracle.truffle.api.frame.Frame;
1615
import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
17-
import com.oracle.truffle.api.nodes.DirectCallNode;
18-
import com.oracle.truffle.api.nodes.IndirectCallNode;
19-
import com.oracle.truffle.api.nodes.Node;
2016
import com.oracle.truffle.api.profiles.ConditionProfile;
2117
import org.truffleruby.core.kernel.TruffleKernelNodes.GetSpecialVariableStorage;
2218
import org.truffleruby.language.CallStackManager;
23-
import org.truffleruby.language.NotOptimizedWarningNode;
2419
import org.truffleruby.language.RubyBaseNode;
25-
import org.truffleruby.language.RubyNode;
2620
import org.truffleruby.language.SpecialVariablesSendingNode;
2721
import org.truffleruby.language.control.RaiseException;
2822
import org.truffleruby.language.threadlocal.SpecialVariableStorage;
@@ -33,7 +27,6 @@
3327
public class ReadCallerVariablesNode extends RubyBaseNode {
3428

3529
private final ConditionProfile inArgumentsProfile = ConditionProfile.create();
36-
@Child private NotOptimizedWarningNode notOptimizedNode = null;
3730

3831
public static ReadCallerVariablesNode create() {
3932
return new ReadCallerVariablesNode();
@@ -50,13 +43,6 @@ public SpecialVariableStorage execute(Frame frame) {
5043

5144
@TruffleBoundary
5245
protected SpecialVariableStorage getCallerSpecialVariables() {
53-
final Node callerNode = getContext().getCallStack().getCallerNode(1, false);
54-
if (!notifyCallerToSendSpecialVariables(callerNode)) {
55-
// If we fail to notify the call node (e.g., because it is a UncachedDispatchNode which is not handled yet),
56-
// we don't want to deoptimize this CallTarget on every call.
57-
getNotOptimizedNode().warn("Unoptimized reading of caller special variables.");
58-
}
59-
6046
final MaterializedFrame callerFrame = Truffle.getRuntime()
6147
.iterateFrames(f -> f.getFrame(FrameAccess.MATERIALIZE).materialize(), 1);
6248
if (!CallStackManager.isRubyFrame(callerFrame)) {
@@ -69,31 +55,4 @@ protected SpecialVariableStorage getCallerSpecialVariables() {
6955

7056
return GetSpecialVariableStorage.getSlow(callerFrame);
7157
}
72-
73-
public static boolean notifyCallerToSendSpecialVariables(Node callerNode) {
74-
if (callerNode instanceof DirectCallNode || callerNode instanceof IndirectCallNode) {
75-
Node parent = callerNode.getParent();
76-
while (parent != null) {
77-
if (parent instanceof SpecialVariablesSendingNode) {
78-
((SpecialVariablesSendingNode) parent).startSendingOwnVariables();
79-
return true;
80-
}
81-
if (parent instanceof RubyNode) {
82-
// A node with source info representing Ruby code, we could not find the FrameAndVariablesSendingNode
83-
return false;
84-
}
85-
parent = parent.getParent();
86-
}
87-
}
88-
89-
return false;
90-
}
91-
92-
private NotOptimizedWarningNode getNotOptimizedNode() {
93-
if (notOptimizedNode == null) {
94-
CompilerDirectives.transferToInterpreterAndInvalidate();
95-
notOptimizedNode = insert(NotOptimizedWarningNode.create());
96-
}
97-
return notOptimizedNode;
98-
}
9958
}

0 commit comments

Comments
 (0)