Skip to content

Commit 4de310f

Browse files
committed
Fix caller frame lookup in SuperInitNode
1 parent 6d897ae commit 4de310f

File tree

5 files changed

+68
-22
lines changed

5 files changed

+68
-22
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/FrameBuiltins.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import com.oracle.graal.python.nodes.PRootNode;
4646
import com.oracle.graal.python.nodes.frame.MaterializeFrameNode;
4747
import com.oracle.graal.python.nodes.frame.ReadCallerFrameNode;
48+
import com.oracle.graal.python.nodes.frame.ReadCallerFrameNode.FrameSelector;
4849
import com.oracle.graal.python.nodes.frame.ReadLocalsNode;
4950
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
5051
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
@@ -233,7 +234,7 @@ Object getBackref(VirtualFrame frame, PFrame self,
233234
// a) self is still on the stack and the caller isn't filled in
234235
// b) this frame has returned, but not (yet) to a Python caller
235236
// c) this frame has no caller (it is/was a top frame)
236-
PFrame callerFrame = readCallerFrame.executeWith(frame, cur.getRef(), false, 0);
237+
PFrame callerFrame = readCallerFrame.executeWith(frame, cur.getRef(), FrameSelector.ALL_PYTHON_FRAMES, 0);
237238

238239
// We don't need to mark the caller frame as 'escaped' because if 'self' is
239240
// escaped, the caller frame will be escaped when leaving the current function.

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/superobject/SuperBuiltins.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
import com.oracle.graal.python.nodes.call.special.LookupAndCallBinaryNode;
7878
import com.oracle.graal.python.nodes.classes.IsSubtypeNode;
7979
import com.oracle.graal.python.nodes.frame.ReadCallerFrameNode;
80+
import com.oracle.graal.python.nodes.frame.ReadCallerFrameNode.FrameSelector;
8081
import com.oracle.graal.python.nodes.frame.ReadLocalVariableNode;
8182
import com.oracle.graal.python.nodes.function.BuiltinFunctionRootNode;
8283
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
@@ -254,7 +255,7 @@ PNone initInPlace(VirtualFrame frame, SuperObject self, @SuppressWarnings("unuse
254255
PNone init(VirtualFrame frame, SuperObject self, @SuppressWarnings("unused") PNone clsArg, @SuppressWarnings("unused") PNone objArg,
255256
@Cached ReadCallerFrameNode readCaller,
256257
@CachedLibrary(limit = "1") HashingStorageLibrary hlib) {
257-
PFrame target = readCaller.executeWith(frame, 0);
258+
PFrame target = readCaller.executeWith(frame, FrameSelector.SKIP_PYTHON_BUILTIN, 0);
258259
if (target == null) {
259260
throw raise(PythonErrorType.RuntimeError, ErrorMessages.NO_CURRENT_FRAME, "super()");
260261
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PRootNode.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
package com.oracle.graal.python.nodes;
4242

4343
import com.oracle.graal.python.builtins.objects.function.Signature;
44+
import com.oracle.graal.python.nodes.function.BuiltinFunctionRootNode;
4445
import com.oracle.truffle.api.Assumption;
4546
import com.oracle.truffle.api.CompilerAsserts;
4647
import com.oracle.truffle.api.CompilerDirectives;
@@ -143,6 +144,10 @@ public static boolean isPythonInternal(RootNode rootNode) {
143144
return rootNode instanceof PRootNode && isPythonInternal((PRootNode) rootNode);
144145
}
145146

147+
public static boolean isPythonBuiltin(RootNode rootNode) {
148+
return rootNode instanceof BuiltinFunctionRootNode;
149+
}
150+
146151
private static Assumption createCallerFrameAssumption() {
147152
return Truffle.getRuntime().createAssumption("does not need caller frame");
148153
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/ReadCallerFrameNode.java

Lines changed: 57 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,40 @@
6262

6363
@NodeInfo(shortName = "read_caller_fame")
6464
public final class ReadCallerFrameNode extends Node {
65+
public enum FrameSelector {
66+
ALL_PYTHON_FRAMES {
67+
@Override
68+
public boolean skip(RootNode rootNode) {
69+
return false;
70+
}
71+
},
72+
/**
73+
* Skips any internal code frames including internal Python level frames.
74+
*/
75+
SKIP_PYTHON_INTERNAL {
76+
@Override
77+
public boolean skip(RootNode rootNode) {
78+
return PRootNode.isPythonInternal(rootNode);
79+
}
80+
},
81+
/**
82+
* Skips only builtins frames, not internal Python level frames.
83+
*/
84+
SKIP_PYTHON_BUILTIN {
85+
@Override
86+
public boolean skip(RootNode rootNode) {
87+
return PRootNode.isPythonBuiltin(rootNode);
88+
}
89+
};
90+
91+
public abstract boolean skip(RootNode rootNode);
92+
93+
public final boolean skip(PFrame.Reference ref) {
94+
Node callNode = ref.getCallNode();
95+
return callNode == null || skip(callNode.getRootNode());
96+
}
97+
}
98+
6599
@CompilationFinal private ConditionProfile cachedCallerFrameProfile;
66100
@Child private MaterializeFrameNode materializeNode;
67101

@@ -73,26 +107,30 @@ public static ReadCallerFrameNode create() {
73107
}
74108

75109
public final PFrame executeWith(VirtualFrame frame, int level) {
76-
return executeWith(frame, PArguments.getCurrentFrameInfo(frame), true, level);
110+
return executeWith(frame, PArguments.getCurrentFrameInfo(frame), FrameSelector.SKIP_PYTHON_INTERNAL, level);
111+
}
112+
113+
public final PFrame executeWith(VirtualFrame frame, FrameSelector selector, int level) {
114+
return executeWith(frame, PArguments.getCurrentFrameInfo(frame), selector, level);
77115
}
78116

79117
public final PFrame executeWith(VirtualFrame frame, Frame startFrame, int level) {
80-
return executeWith(frame, PArguments.getCurrentFrameInfo(startFrame), true, level);
118+
return executeWith(frame, PArguments.getCurrentFrameInfo(startFrame), FrameSelector.SKIP_PYTHON_INTERNAL, level);
81119
}
82120

83121
public PFrame executeWith(VirtualFrame frame, PFrame.Reference startFrameInfo, int level) {
84-
return executeWith(frame, startFrameInfo, true, level);
122+
return executeWith(frame, startFrameInfo, FrameSelector.SKIP_PYTHON_INTERNAL, level);
85123
}
86124

87125
public PFrame executeWith(VirtualFrame frame, PFrame.Reference startFrameInfo, FrameInstance.FrameAccess frameAccess, int level) {
88-
return executeWith(frame, startFrameInfo, frameAccess, true, level);
126+
return executeWith(frame, startFrameInfo, frameAccess, FrameSelector.SKIP_PYTHON_INTERNAL, level);
89127
}
90128

91-
public PFrame executeWith(VirtualFrame frame, PFrame.Reference startFrameInfo, boolean skipInternal, int level) {
92-
return executeWith(frame, startFrameInfo, FrameInstance.FrameAccess.READ_ONLY, skipInternal, level);
129+
public PFrame executeWith(VirtualFrame frame, PFrame.Reference startFrameInfo, FrameSelector selector, int level) {
130+
return executeWith(frame, startFrameInfo, FrameInstance.FrameAccess.READ_ONLY, selector, level);
93131
}
94132

95-
public PFrame executeWith(VirtualFrame frame, PFrame.Reference startFrameInfo, FrameInstance.FrameAccess frameAccess, boolean skipInternal, int level) {
133+
public PFrame executeWith(VirtualFrame frame, PFrame.Reference startFrameInfo, FrameInstance.FrameAccess frameAccess, FrameSelector selector, int level) {
96134
PFrame.Reference curFrameInfo = startFrameInfo;
97135
if (cachedCallerFrameProfile == null) {
98136
CompilerDirectives.transferToInterpreterAndInvalidate();
@@ -101,28 +139,28 @@ public PFrame executeWith(VirtualFrame frame, PFrame.Reference startFrameInfo, F
101139
for (int i = 0; i <= level;) {
102140
PFrame.Reference callerInfo = curFrameInfo.getCallerInfo();
103141
if (callerInfo == null) {
104-
Frame callerFrame = getCallerFrame(startFrameInfo, frameAccess, skipInternal, level);
142+
Frame callerFrame = getCallerFrame(startFrameInfo, frameAccess, selector, level);
105143
if (callerFrame != null) {
106144
return ensureMaterializeNode().execute(frame, false, true, callerFrame);
107145
}
108146
return null;
109-
} else if (!(skipInternal && (callerInfo.getCallNode() == null || PRootNode.isPythonInternal(callerInfo.getCallNode().getRootNode())))) {
147+
} else if (!selector.skip(callerInfo)) {
110148
i++;
111149
}
112150
curFrameInfo = callerInfo;
113151
}
114152
} else {
115-
curFrameInfo = walkLevels(frame, curFrameInfo, frameAccess, skipInternal, level);
153+
curFrameInfo = walkLevels(frame, curFrameInfo, frameAccess, selector, level);
116154
}
117155
return curFrameInfo.getPyFrame();
118156
}
119157

120-
private PFrame.Reference walkLevels(VirtualFrame frame, PFrame.Reference startFrameInfo, FrameInstance.FrameAccess frameAccess, boolean skipInternal, int level) {
158+
private PFrame.Reference walkLevels(VirtualFrame frame, PFrame.Reference startFrameInfo, FrameInstance.FrameAccess frameAccess, FrameSelector selector, int level) {
121159
PFrame.Reference currentFrame = startFrameInfo;
122160
for (int i = 0; i <= level;) {
123161
PFrame.Reference callerInfo = currentFrame.getCallerInfo();
124162
if (cachedCallerFrameProfile.profile(callerInfo == null)) {
125-
Frame callerFrame = getCallerFrame(startFrameInfo, frameAccess, skipInternal, level);
163+
Frame callerFrame = getCallerFrame(startFrameInfo, frameAccess, selector, level);
126164
if (callerFrame != null) {
127165
// At this point, we must 'materialize' the frame. Actually, the Truffle frame
128166
// is never materialized but we ensure that a corresponding PFrame is created
@@ -131,7 +169,7 @@ private PFrame.Reference walkLevels(VirtualFrame frame, PFrame.Reference startFr
131169
return PArguments.getCurrentFrameInfo(callerFrame);
132170
}
133171
return PFrame.Reference.EMPTY;
134-
} else if (!(skipInternal && (callerInfo.getCallNode() == null || PRootNode.isPythonInternal(callerInfo.getCallNode().getRootNode())))) {
172+
} else if (!selector.skip(callerInfo)) {
135173
i++;
136174
}
137175
currentFrame = callerInfo;
@@ -202,7 +240,7 @@ private PFrame.Reference walkLevels(VirtualFrame frame, PFrame.Reference startFr
202240
*/
203241
public static Frame getCurrentFrame(Node requestingNode, FrameInstance.FrameAccess frameAccess) {
204242
CompilerDirectives.transferToInterpreterAndInvalidate();
205-
return getFrame(Objects.requireNonNull(requestingNode), null, frameAccess, false, 0);
243+
return getFrame(Objects.requireNonNull(requestingNode), null, frameAccess, FrameSelector.ALL_PYTHON_FRAMES, 0);
206244
}
207245

208246
/**
@@ -213,15 +251,15 @@ public static Frame getCurrentFrame(Node requestingNode, FrameInstance.FrameAcce
213251
*
214252
* @param startFrame - the frame to start counting from (must not be {@code null})
215253
* @param frameAccess - the desired {@link FrameInstance} access kind
216-
* @param skipInternal - declares if Python internal frames should be skipped or counted
254+
* @param selector - declares which frames should be skipped or counted
217255
* @param level - the stack depth to go to. Ignored if {@code startFrame} is {@code null}
218256
*/
219-
public static Frame getCallerFrame(PFrame.Reference startFrame, FrameInstance.FrameAccess frameAccess, boolean skipInternal, int level) {
257+
public static Frame getCallerFrame(PFrame.Reference startFrame, FrameInstance.FrameAccess frameAccess, FrameSelector selector, int level) {
220258
CompilerDirectives.transferToInterpreterAndInvalidate();
221-
return getFrame(null, Objects.requireNonNull(startFrame), frameAccess, skipInternal, level);
259+
return getFrame(null, Objects.requireNonNull(startFrame), frameAccess, selector, level);
222260
}
223261

224-
private static Frame getFrame(Node requestingNode, PFrame.Reference startFrame, FrameInstance.FrameAccess frameAccess, boolean skipInternal, int level) {
262+
private static Frame getFrame(Node requestingNode, PFrame.Reference startFrame, FrameInstance.FrameAccess frameAccess, FrameSelector selector, int level) {
225263
assert CompilerDirectives.inInterpreter();
226264
final Frame[] outputFrame = new Frame[1];
227265
Truffle.getRuntime().iterateFrames(new FrameInstanceVisitor<Frame>() {
@@ -272,7 +310,7 @@ public Frame visitFrame(FrameInstance frameInstance) {
272310
} else {
273311
// Skip frames of builtin functions (if requested) because these do not have
274312
// a Python frame in CPython.
275-
if (!(skipInternal && pRootNode.isPythonInternal())) {
313+
if (!selector.skip(pRootNode)) {
276314
if (i == level || startFrame == null) {
277315
Frame frame = frameInstance.getFrame(frameAccess);
278316
assert PArguments.isPythonFrame(frame);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/ExecutionContext.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
import com.oracle.graal.python.nodes.frame.MaterializeFrameNode;
5151
import com.oracle.graal.python.nodes.frame.MaterializeFrameNodeGen;
5252
import com.oracle.graal.python.nodes.frame.ReadCallerFrameNode;
53+
import com.oracle.graal.python.nodes.frame.ReadCallerFrameNode.FrameSelector;
5354
import com.oracle.graal.python.nodes.util.ExceptionStateNodes.GetCaughtExceptionNode;
5455
import com.oracle.graal.python.runtime.exception.PException;
5556
import com.oracle.truffle.api.CompilerAsserts;
@@ -249,7 +250,7 @@ public void exit(VirtualFrame frame, PRootNode node) {
249250
// n.b. We need to use 'ReadCallerFrameNode.getCallerFrame' instead of
250251
// 'Truffle.getRuntime().getCallerFrame()' because we still need to skip
251252
// non-Python frames, even if we do not skip frames of builtin functions.
252-
Frame callerFrame = ReadCallerFrameNode.getCallerFrame(info, FrameInstance.FrameAccess.READ_ONLY, false, 0);
253+
Frame callerFrame = ReadCallerFrameNode.getCallerFrame(info, FrameInstance.FrameAccess.READ_ONLY, FrameSelector.ALL_PYTHON_FRAMES, 0);
253254
if (PArguments.isPythonFrame(callerFrame)) {
254255
callerInfo = PArguments.getCurrentFrameInfo(callerFrame);
255256
} else {

0 commit comments

Comments
 (0)