Skip to content

Commit 0cdeb1d

Browse files
committed
Add CallerFlags.NEEDS_LASTI
1 parent 667a876 commit 0cdeb1d

File tree

17 files changed

+99
-63
lines changed

17 files changed

+99
-63
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -786,7 +786,7 @@ public ExecutableNode parse(InlineParsingRequest request) {
786786
public Object execute(VirtualFrame frame) {
787787
Object[] arguments = PArguments.create();
788788
PFrame pFrame = materializeFrameNode.execute(this, false, true, frame);
789-
Object pLocals = getFrameLocalsNode.executeCached(frame, pFrame);
789+
Object pLocals = getFrameLocalsNode.executeCached(frame, pFrame, true);
790790
PArguments.setSpecialArgument(arguments, pLocals);
791791
PArguments.setGlobals(arguments, PArguments.getGlobals(frame));
792792
boolean wasAcquired = gilNode.acquire();

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -812,7 +812,7 @@ static Object[] inheritGlobals(VirtualFrame frame, Node inliningTarget, @Suppres
812812
@Exclusive @Cached GetFrameLocalsNode getFrameLocalsNode,
813813
@Exclusive @Cached PRaiseNode raiseNode) {
814814
boolean inheritLocals = inheritLocalsProfile.profile(inliningTarget, locals instanceof PNone);
815-
PFrame callerFrame = readFrameNode.getCurrentPythonFrame(frame, inheritLocals);
815+
PFrame callerFrame = readFrameNode.getCurrentPythonFrame(frame, inheritLocals ? CallerFlags.NEEDS_LOCALS : 0);
816816
Object[] args = PArguments.create();
817817
boolean haveCallerFrame = haveCallerFrameProfile.profile(inliningTarget, callerFrame != null);
818818
if (haveCallerFrame) {
@@ -822,7 +822,7 @@ static Object[] inheritGlobals(VirtualFrame frame, Node inliningTarget, @Suppres
822822
}
823823
if (inheritLocals) {
824824
if (haveCallerFrame) {
825-
Object callerLocals = getFrameLocalsNode.execute(frame, inliningTarget, callerFrame);
825+
Object callerLocals = getFrameLocalsNode.execute(frame, inliningTarget, callerFrame, true);
826826
setCustomLocals(args, callerLocals);
827827
} else {
828828
setCustomLocals(args, PArguments.getGlobals(args));

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SysModuleBuiltins.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -864,7 +864,7 @@ static PFrame counted(VirtualFrame frame, int depth,
864864
@Bind Node inliningTarget,
865865
@Cached ReadFrameNode readFrameNode,
866866
@Cached PRaiseNode raiseNode) {
867-
PFrame requested = readFrameNode.getFrameForReference(frame, PArguments.getCurrentFrameInfo(frame), ReadFrameNode.AllPythonFramesSelector.INSTANCE, depth, false);
867+
PFrame requested = readFrameNode.getFrameForReference(frame, PArguments.getCurrentFrameInfo(frame), ReadFrameNode.AllPythonFramesSelector.INSTANCE, depth, 0);
868868
if (requested == null) {
869869
throw raiseNode.raise(inliningTarget, ValueError, ErrorMessages.CALL_STACK_NOT_DEEP_ENOUGH);
870870
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/WarningsModuleBuiltins.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,7 @@ private PFrame getCallerFrame(VirtualFrame frame, int stackLevel, TruffleString[
424424
stackLevel--;
425425
selector = rootNode -> ReadFrameNode.VisiblePythonFramesSelector.INSTANCE.skip(rootNode) || isFilenameToSkip(skipFilePrefixes, rootNode);
426426
}
427-
return readFrameNode.getFrameForReference(frame, PArguments.getCurrentFrameInfo(frame), selector, stackLevel, false);
427+
return readFrameNode.getFrameForReference(frame, PArguments.getCurrentFrameInfo(frame), selector, stackLevel, CallerFlags.NEEDS_LASTI);
428428
}
429429

430430
@TruffleBoundary

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextFrameBuiltins.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ abstract static class PyFrame_GetLocals extends CApiUnaryBuiltinNode {
9494
static Object get(PFrame frame,
9595
@Bind Node inliningTarget,
9696
@Cached GetFrameLocalsNode getFrameLocalsNode) {
97-
return getFrameLocalsNode.execute(null, inliningTarget, frame);
97+
return getFrameLocalsNode.execute(null, inliningTarget, frame, false);
9898
}
9999
}
100100

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextTracebackBuiltins.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
import com.oracle.graal.python.builtins.objects.frame.PFrame;
5959
import com.oracle.graal.python.builtins.objects.traceback.PTraceback;
6060
import com.oracle.graal.python.nodes.frame.ReadFrameNode;
61+
import com.oracle.graal.python.runtime.CallerFlags;
6162
import com.oracle.graal.python.runtime.PythonContext;
6263
import com.oracle.graal.python.runtime.object.PFactory;
6364
import com.oracle.truffle.api.dsl.Bind;
@@ -95,7 +96,7 @@ static int tbHere(PFrame frame,
9596
Object currentException = readAndClearNativeException.execute(inliningTarget, threadState);
9697
if (currentException instanceof PBaseException) {
9798
Object traceback = ExceptionNodes.GetTracebackNode.executeUncached(currentException);
98-
frame = readFrameNode.ensureFresh(null, frame);
99+
frame = readFrameNode.ensureFresh(null, frame, CallerFlags.NEEDS_LASTI);
99100
PTraceback newTraceback = PFactory.createTraceback(language, frame, frame.getLine(), traceback instanceof PTraceback ptb ? ptb : null);
100101
ExceptionNodes.SetTracebackNode.executeUncached(currentException, newTraceback);
101102
}

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

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
5858
import com.oracle.graal.python.nodes.util.CannotCastException;
5959
import com.oracle.graal.python.nodes.util.CastToJavaBooleanNode;
60+
import com.oracle.graal.python.runtime.CallerFlags;
6061
import com.oracle.graal.python.runtime.PythonContext;
6162
import com.oracle.graal.python.runtime.object.PFactory;
6263
import com.oracle.graal.python.util.OverflowException;
@@ -90,7 +91,7 @@ TruffleString repr(VirtualFrame frame, PFrame self,
9091
@Cached GetCodeNode getCodeNode,
9192
@Cached ReadFrameNode readFrameNode,
9293
@Cached SimpleTruffleStringFormatNode simpleTruffleStringFormatNode) {
93-
self = readFrameNode.ensureFresh(frame, self);
94+
self = readFrameNode.ensureFresh(frame, self, CallerFlags.NEEDS_LASTI);
9495
PCode code = getCodeNode.executeObject(frame, self);
9596
int lineno = self.getLine();
9697
return simpleTruffleStringFormatNode.format("<frame at 0x%s, file '%s', line %d, code %s>",
@@ -158,7 +159,7 @@ Object delete(PFrame self, DescriptorDeleteMarker ignored,
158159
@Specialization(guards = "isNoValue(newLineno)")
159160
int get(VirtualFrame frame, PFrame self, Object newLineno,
160161
@Cached @Cached.Exclusive ReadFrameNode readFrameNode) {
161-
return readFrameNode.ensureFresh(frame, self).getLine();
162+
return readFrameNode.ensureFresh(frame, self, CallerFlags.NEEDS_LASTI).getLine();
162163
}
163164

164165
@Specialization(guards = {"!isNoValue(newLineno)", "!isDeleteMarker(newLineno)"})
@@ -168,7 +169,7 @@ static PNone set(VirtualFrame frame, PFrame self, Object newLineno,
168169
@Cached @Cached.Exclusive PRaiseNode raise,
169170
@Cached PyLongCheckExactNode isLong,
170171
@Cached PyLongAsLongAndOverflowNode toLong) {
171-
readFrameNode.ensureFresh(frame, self);
172+
readFrameNode.ensureFresh(frame, self, CallerFlags.NEEDS_LASTI);
172173
if (self.isTraceArgument()) {
173174
if (isLong.execute(inliningTarget, newLineno)) {
174175
try {
@@ -199,7 +200,7 @@ public abstract static class GetLastiNode extends PythonUnaryBuiltinNode {
199200
@Specialization
200201
int get(VirtualFrame frame, PFrame self,
201202
@Cached ReadFrameNode readFrameNode) {
202-
return readFrameNode.ensureFresh(frame, self).getLasti();
203+
return readFrameNode.ensureFresh(frame, self, CallerFlags.NEEDS_LASTI).getLasti();
203204
}
204205
}
205206

@@ -272,7 +273,7 @@ public abstract static class GetLocalsNode extends PythonUnaryBuiltinNode {
272273
Object getUpdating(VirtualFrame frame, PFrame self,
273274
@Bind Node inliningTarget,
274275
@Cached GetFrameLocalsNode getFrameLocalsNode) {
275-
Object locals = getFrameLocalsNode.execute(frame, inliningTarget, self);
276+
Object locals = getFrameLocalsNode.execute(frame, inliningTarget, self, false);
276277
self.setLocalsAccessed(true);
277278
return locals;
278279
}
@@ -286,7 +287,7 @@ public abstract static class GetBackrefNode extends PythonBuiltinNode {
286287
@Specialization
287288
Object getBackref(VirtualFrame frame, PFrame self,
288289
@Cached ReadFrameNode readCallerFrame) {
289-
PFrame backref = readCallerFrame.getFrameForReference(frame, self.getRef(), 1, false);
290+
PFrame backref = readCallerFrame.getFrameForReference(frame, self.getRef(), 1, 0);
290291
if (backref != null) {
291292
backref.getRef().markAsEscaped();
292293
return backref;

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

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,15 @@
5353
import com.oracle.graal.python.nodes.bytecode_dsl.PBytecodeDSLRootNode;
5454
import com.oracle.graal.python.nodes.frame.GetFrameLocalsNode;
5555
import com.oracle.graal.python.nodes.frame.MaterializeFrameNode;
56+
import com.oracle.graal.python.nodes.frame.ReadFrameNode;
57+
import com.oracle.graal.python.runtime.CallerFlags;
5658
import com.oracle.graal.python.runtime.PythonOptions;
5759
import com.oracle.graal.python.util.PythonUtils;
5860
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
5961
import com.oracle.truffle.api.RootCallTarget;
6062
import com.oracle.truffle.api.bytecode.BytecodeNode;
6163
import com.oracle.truffle.api.frame.MaterializedFrame;
64+
import com.oracle.truffle.api.frame.VirtualFrame;
6265
import com.oracle.truffle.api.nodes.Node;
6366
import com.oracle.truffle.api.nodes.RootNode;
6467

@@ -67,6 +70,8 @@ public final class PFrame extends PythonBuiltinObject {
6770

6871
private Object[] arguments;
6972
private MaterializedFrame locals;
73+
// Whether the frame has dict locals passed from the caller (happens in eval/exec and class
74+
// bodies)
7075
private final boolean hasCustomLocals;
7176
private Object localsDict;
7277
private final Reference virtualFrameInfo;
@@ -98,6 +103,7 @@ public final class PFrame extends PythonBuiltinObject {
98103

99104
private PFrame.Reference backref = null;
100105

106+
// Whether lasti and locals are stale, see isStale
101107
private boolean stale;
102108

103109
public Object getLocalTraceFun() {
@@ -225,8 +231,25 @@ public void setLocals(MaterializedFrame locals) {
225231
this.locals = locals;
226232
}
227233

228-
public boolean isStale() {
229-
return stale;
234+
/**
235+
* PFrame is created once for each real frame, but some information in it, like locals and
236+
* lasti+lineno can get out of sync when the frame is still executing. The PFrame is normally
237+
* updated by the caller when the callee requests it. But the PFrame might sometimes be passed
238+
* down before the callee has set the flags to request the update and thus the callee might see
239+
* stale info. This method can tell that this happened and an explicit update via
240+
* {@link ReadFrameNode#refreshFrame(VirtualFrame, Reference, int)} is needed.
241+
*
242+
* @param frame The current frame. If the current executing frame is this PFrame, then sync is
243+
* always needed.
244+
* @param callerFlags Specifies which fields should be checked for needing sync. It should be
245+
* flags from {@link CallerFlags}.
246+
*/
247+
public boolean isStale(VirtualFrame frame, int callerFlags) {
248+
boolean needsLocals = CallerFlags.needsLocals(callerFlags) && !hasCustomLocals;
249+
if (needsLocals && locals == null) {
250+
return true;
251+
}
252+
return (CallerFlags.needsLasti(callerFlags) || needsLocals) && (stale || (frame != null && PArguments.getCurrentFrameInfo(frame) == getRef()));
230253
}
231254

232255
public void setStale(boolean stale) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ PNone init(VirtualFrame frame, SuperObject self, @SuppressWarnings("unused") PNo
294294
@Shared @Cached PRaiseNode raiseNode,
295295
@Cached ReadFrameNode readCaller,
296296
@Shared @Cached CellBuiltins.GetRefNode getRefNode) {
297-
PFrame target = readCaller.getCurrentPythonFrame(frame, true);
297+
PFrame target = readCaller.getCurrentPythonFrame(frame, CallerFlags.NEEDS_LOCALS);
298298
if (target == null) {
299299
throw raiseNode.raise(inliningTarget, RuntimeError, ErrorMessages.NO_CURRENT_FRAME, "super()");
300300
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/traceback/TracebackBuiltins.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ static PFrame doOnStack(VirtualFrame frame, PTraceback tb,
266266
Reference frameInfo = tb.getFrameInfo();
267267
assert frameInfo.isEscaped() : "cannot create traceback for non-escaped frame";
268268

269-
PFrame escapedFrame = readCallerFrame.getFrameForReference(frame, frameInfo, ReadFrameNode.AllPythonFramesSelector.INSTANCE, 0, false);
269+
PFrame escapedFrame = readCallerFrame.getFrameForReference(frame, frameInfo, ReadFrameNode.AllPythonFramesSelector.INSTANCE, 0, 0);
270270
assert escapedFrame != null : "Failed to find escaped frame on stack";
271271

272272
tb.setFrame(escapedFrame);

0 commit comments

Comments
 (0)