Skip to content

Commit d7e6c86

Browse files
committed
Fix: correctly get caller frame in case of escaping callee frame.
1 parent f605d96 commit d7e6c86

File tree

2 files changed

+23
-23
lines changed

2 files changed

+23
-23
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ private PFrame.Reference walkLevels(VirtualFrame frame, PFrame.Reference startFr
134134
* Walk up the stack to find the start frame and from then (level + 1)-times (counting only
135135
* non-internal Python frames).
136136
*/
137-
private static Frame getCallerFrame(PFrame.Reference startFrame, FrameInstance.FrameAccess frameAccess, boolean skipInternal, int level) {
137+
public static Frame getCallerFrame(PFrame.Reference startFrame, FrameInstance.FrameAccess frameAccess, boolean skipInternal, int level) {
138138
CompilerDirectives.transferToInterpreter();
139139
return Truffle.getRuntime().iterateFrames(new FrameInstanceVisitor<Frame>() {
140140
int i = -1;

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

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,12 @@
4747
import com.oracle.graal.python.nodes.PRootNode;
4848
import com.oracle.graal.python.nodes.frame.MaterializeFrameNode;
4949
import com.oracle.graal.python.nodes.frame.MaterializeFrameNodeGen;
50+
import com.oracle.graal.python.nodes.frame.ReadCallerFrameNode;
5051
import com.oracle.graal.python.nodes.util.ExceptionStateNodes.GetCaughtExceptionNode;
5152
import com.oracle.graal.python.runtime.exception.PException;
5253
import com.oracle.truffle.api.CompilerDirectives;
54+
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
5355
import com.oracle.truffle.api.RootCallTarget;
54-
import com.oracle.truffle.api.Truffle;
5556
import com.oracle.truffle.api.frame.Frame;
5657
import com.oracle.truffle.api.frame.FrameInstance;
5758
import com.oracle.truffle.api.frame.VirtualFrame;
@@ -127,6 +128,8 @@ public static final class CalleeContext extends Node {
127128

128129
@Child private MaterializeFrameNode materializeNode;
129130

131+
@CompilationFinal private boolean firstRequest = true;
132+
130133
/**
131134
* Wrap the execution of a Python callee called from a Python frame.
132135
*/
@@ -154,34 +157,31 @@ public void exit(VirtualFrame frame, PRootNode node) {
154157
if (info.isEscaped()) {
155158
// This assumption acts as our branch profile here
156159
PFrame.Reference callerInfo = PArguments.getCallerFrameInfo(frame);
157-
if (!node.needsCallerFrame()) {
158-
CompilerDirectives.transferToInterpreterAndInvalidate();
159-
node.setNeedsCallerFrame();
160-
if (callerInfo == null) {
161-
// we didn't request the caller frame reference. now we need
162-
// it.
160+
if (callerInfo == null) {
161+
if (firstRequest) {
162+
// we didn't request the caller frame reference. now we need it.
163163
CompilerDirectives.transferToInterpreterAndInvalidate();
164-
FrameInstance callerFrameInstance = Truffle.getRuntime().getCallerFrame();
165-
if (callerFrameInstance != null) {
166-
Frame callerFrame = callerFrameInstance.getFrame(FrameInstance.FrameAccess.READ_ONLY);
167-
if (PArguments.isPythonFrame(callerFrame)) {
168-
callerInfo = PArguments.getCurrentFrameInfo(callerFrame);
169-
} else {
170-
// TODO: frames: an assertion should be that this is one of our
171-
// entry point call nodes
172-
callerInfo = PFrame.Reference.EMPTY;
173-
}
164+
firstRequest = false;
165+
166+
// n.b. We need to use 'ReadCallerFrameNode.getCallerFrame' instead of
167+
// 'Truffle.getRuntime().getCallerFrame()' because we still need to filter
168+
// internal frames.
169+
Frame callerFrame = ReadCallerFrameNode.getCallerFrame(info, FrameInstance.FrameAccess.READ_ONLY, true, 0);
170+
if (PArguments.isPythonFrame(callerFrame)) {
171+
callerInfo = PArguments.getCurrentFrameInfo(callerFrame);
174172
} else {
173+
// TODO: frames: an assertion should be that this is one of our
174+
// entry point call nodes
175175
callerInfo = PFrame.Reference.EMPTY;
176176
}
177-
}
178-
} else {
179-
// caller info was requested, it must be here if there is
180-
// any. If it isn't, we're in a top-frame.
181-
if (callerInfo == null) {
177+
} else {
178+
// caller info was requested, it must be here if there is
179+
// any. If it isn't, we're in a top-frame.
180+
assert node.needsCallerFrame();
182181
callerInfo = PFrame.Reference.EMPTY;
183182
}
184183
}
184+
185185
// force the frame so that it can be accessed later
186186
node.getExitedEscapedWithoutFrameProfile().enter();
187187
ensureMaterializeNode().execute(frame, node, false, true);

0 commit comments

Comments
 (0)