Skip to content

Commit 20660bc

Browse files
committed
Split frame sync into two step process
1 parent c741105 commit 20660bc

File tree

11 files changed

+310
-339
lines changed

11 files changed

+310
-339
lines changed

graalpython/com.oracle.graal.python.test/src/tests/test_frame_tests.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
1+
# Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
22
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
33
#
44
# The Universal Permissive License (UPL), Version 1.0

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
import com.oracle.graal.python.nodes.call.CallNode;
7373
import com.oracle.graal.python.nodes.call.GenericInvokeNode;
7474
import com.oracle.graal.python.nodes.exception.TopLevelExceptionHandler;
75+
import com.oracle.graal.python.nodes.frame.GetFrameLocalsNode;
7576
import com.oracle.graal.python.nodes.frame.MaterializeFrameNode;
7677
import com.oracle.graal.python.pegparser.InputType;
7778
import com.oracle.graal.python.pegparser.NodeFactory;
@@ -589,13 +590,14 @@ public ExecutableNode parse(InlineParsingRequest request) {
589590
@Child private GilNode gilNode = GilNode.create();
590591
@Child private GenericInvokeNode invokeNode = GenericInvokeNode.create();
591592
@Child private MaterializeFrameNode materializeFrameNode = MaterializeFrameNode.create();
593+
@Child private GetFrameLocalsNode getFrameLocalsNode = GetFrameLocalsNode.create();
592594

593595
@Override
594596
public Object execute(VirtualFrame frame) {
595597
Object[] arguments = PArguments.create();
596598
// escape?
597599
PFrame pFrame = materializeFrameNode.execute(frame, this, false, true, frame);
598-
Object locals = pFrame.getLocals();
600+
Object locals = getFrameLocalsNode.execute(frame, pFrame);
599601
PArguments.setSpecialArgument(arguments, locals);
600602
PArguments.setGlobals(arguments, PArguments.getGlobals(frame));
601603
boolean wasAcquired = gilNode.acquire();

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

Lines changed: 15 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@
113113
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
114114
import com.oracle.graal.python.builtins.PythonBuiltins;
115115
import com.oracle.graal.python.builtins.modules.BuiltinFunctionsFactory.GetAttrNodeFactory;
116-
import com.oracle.graal.python.builtins.modules.BuiltinFunctionsFactory.GlobalsNodeFactory;
117116
import com.oracle.graal.python.builtins.modules.BuiltinFunctionsFactory.HexNodeFactory;
118117
import com.oracle.graal.python.builtins.modules.BuiltinFunctionsFactory.OctNodeFactory;
119118
import com.oracle.graal.python.builtins.modules.WarningsModuleBuiltins.WarnNode;
@@ -164,6 +163,7 @@
164163
import com.oracle.graal.python.lib.GetNextNode;
165164
import com.oracle.graal.python.lib.PyCallableCheckNode;
166165
import com.oracle.graal.python.lib.PyEvalGetGlobals;
166+
import com.oracle.graal.python.lib.PyEvalGetLocals;
167167
import com.oracle.graal.python.lib.PyMappingCheckNode;
168168
import com.oracle.graal.python.lib.PyNumberAsSizeNode;
169169
import com.oracle.graal.python.lib.PyNumberIndexNode;
@@ -215,6 +215,7 @@
215215
import com.oracle.graal.python.nodes.expression.BinaryOpNode;
216216
import com.oracle.graal.python.nodes.expression.CoerceToBooleanNode;
217217
import com.oracle.graal.python.nodes.expression.TernaryArithmetic;
218+
import com.oracle.graal.python.nodes.frame.GetFrameLocalsNode;
218219
import com.oracle.graal.python.nodes.frame.ReadCallerFrameNode;
219220
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
220221
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
@@ -765,12 +766,11 @@ public abstract static class DirNode extends PythonBuiltinNode {
765766
// logic like in 'Objects/object.c: _dir_locals'
766767
@Specialization(guards = "isNoValue(object)")
767768
Object locals(VirtualFrame frame, @SuppressWarnings("unused") Object object,
768-
@Cached ReadCallerFrameNode readCallerFrameNode,
769+
@Cached PyEvalGetLocals getLocals,
769770
@Cached("create(T_KEYS)") LookupAndCallUnaryNode callKeysNode,
770771
@Cached ListBuiltins.ListSortNode sortNode,
771772
@Cached ListNodes.ConstructListNode constructListNode) {
772-
773-
Object localsDict = LocalsNode.getLocalsDict(frame, readCallerFrameNode);
773+
Object localsDict = getLocals.execute(frame);
774774
Object keysObj = callKeysNode.executeObject(frame, localsDict);
775775
PList list = constructListNode.execute(frame, keysObj);
776776
sortNode.execute(frame, list);
@@ -861,8 +861,8 @@ private static void inheritGlobals(PFrame callerFrame, Object[] args) {
861861
PArguments.setGlobals(args, callerFrame.getGlobals());
862862
}
863863

864-
private static void inheritLocals(PFrame callerFrame, Object[] args) {
865-
Object callerLocals = callerFrame.getLocals();
864+
private static void inheritLocals(VirtualFrame frame, PFrame callerFrame, Object[] args, GetFrameLocalsNode getFrameLocalsNode) {
865+
Object callerLocals = getFrameLocalsNode.execute(frame, callerFrame);
866866
setCustomLocals(args, callerLocals);
867867
}
868868

@@ -889,12 +889,13 @@ private void setCustomGlobals(VirtualFrame frame, PDict globals, HashingCollecti
889889
@Specialization
890890
Object execInheritGlobalsInheritLocals(VirtualFrame frame, Object source, @SuppressWarnings("unused") PNone globals, @SuppressWarnings("unused") PNone locals,
891891
@Cached ReadCallerFrameNode readCallerFrameNode,
892-
@Shared("getCt") @Cached CodeNodes.GetCodeCallTargetNode getCt) {
892+
@Shared("getCt") @Cached CodeNodes.GetCodeCallTargetNode getCt,
893+
@Cached GetFrameLocalsNode getFrameLocalsNode) {
893894
PCode code = createAndCheckCode(frame, source);
894895
PFrame callerFrame = readCallerFrameNode.executeWith(frame, 0);
895896
Object[] args = PArguments.create();
896897
inheritGlobals(callerFrame, args);
897-
inheritLocals(callerFrame, args);
898+
inheritLocals(frame, callerFrame, args, getFrameLocalsNode);
898899

899900
return invokeNode.execute(frame, getCt.execute(code), args);
900901
}
@@ -2265,9 +2266,9 @@ private Object iterateGeneric(VirtualFrame frame, Object iterator, Object start,
22652266
}
22662267
}
22672268

2268-
@Builtin(name = "globals")
2269+
@Builtin(name = "globals", needsFrame = true, alwaysNeedsCallerFrame = true)
22692270
@GenerateNodeFactory
2270-
public abstract static class GlobalsNode extends PythonBuiltinNode {
2271+
abstract static class GlobalsNode extends PythonBuiltinNode {
22712272
private final ConditionProfile condProfile = ConditionProfile.create();
22722273

22732274
@Specialization
@@ -2281,10 +2282,6 @@ public Object globals(VirtualFrame frame,
22812282
return globals;
22822283
}
22832284
}
2284-
2285-
public static GlobalsNode create() {
2286-
return GlobalsNodeFactory.create(null);
2287-
}
22882285
}
22892286

22902287
@Builtin(name = "locals", needsFrame = true, alwaysNeedsCallerFrame = true)
@@ -2293,18 +2290,8 @@ abstract static class LocalsNode extends PythonBuiltinNode {
22932290

22942291
@Specialization
22952292
Object locals(VirtualFrame frame,
2296-
@Cached ReadCallerFrameNode readCallerFrameNode) {
2297-
return getLocalsDict(frame, readCallerFrameNode);
2298-
}
2299-
2300-
static Object getLocalsDict(VirtualFrame frame, ReadCallerFrameNode readCallerFrameNode) {
2301-
PFrame callerFrame = readCallerFrameNode.executeWith(frame, 0);
2302-
return callerFrame.getLocals();
2303-
}
2304-
2305-
@NeverDefault
2306-
public static LocalsNode create() {
2307-
return BuiltinFunctionsFactory.LocalsNodeFactory.create(null);
2293+
@Cached PyEvalGetLocals getLocals) {
2294+
return getLocals.execute(frame);
23082295
}
23092296
}
23102297

@@ -2314,8 +2301,8 @@ abstract static class VarsNode extends PythonUnaryBuiltinNode {
23142301

23152302
@Specialization(guards = "isNoValue(none)")
23162303
Object vars(VirtualFrame frame, @SuppressWarnings("unused") PNone none,
2317-
@Cached LocalsNode localsNode) {
2318-
return localsNode.execute(frame);
2304+
@Cached PyEvalGetLocals getLocals) {
2305+
return getLocals.execute(frame);
23192306
}
23202307

23212308
@Specialization(guards = "!isNoValue(obj)")

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@
2525
*/
2626
package com.oracle.graal.python.builtins.objects.frame;
2727

28-
import com.oracle.truffle.api.dsl.NeverDefault;
29-
3028
import static com.oracle.graal.python.builtins.objects.PythonAbstractObject.objectHashCodeAsHexString;
3129
import static com.oracle.graal.python.nodes.SpecialMethodNames.J___REPR__;
3230

@@ -47,6 +45,7 @@
4745
import com.oracle.graal.python.builtins.objects.str.StringUtils.SimpleTruffleStringFormatNode;
4846
import com.oracle.graal.python.nodes.ErrorMessages;
4947
import com.oracle.graal.python.nodes.PRaiseNode;
48+
import com.oracle.graal.python.nodes.frame.GetFrameLocalsNode;
5049
import com.oracle.graal.python.nodes.frame.MaterializeFrameNode;
5150
import com.oracle.graal.python.nodes.frame.ReadCallerFrameNode;
5251
import com.oracle.graal.python.nodes.frame.ReadCallerFrameNode.FrameSelector;
@@ -59,6 +58,7 @@
5958
import com.oracle.truffle.api.RootCallTarget;
6059
import com.oracle.truffle.api.dsl.Cached;
6160
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
61+
import com.oracle.truffle.api.dsl.NeverDefault;
6262
import com.oracle.truffle.api.dsl.NodeFactory;
6363
import com.oracle.truffle.api.dsl.Specialization;
6464
import com.oracle.truffle.api.frame.VirtualFrame;
@@ -222,7 +222,8 @@ public abstract static class GetLocalsNode extends PythonUnaryBuiltinNode {
222222
@Specialization
223223
Object getUpdating(VirtualFrame frame, PFrame self,
224224
@Cached ConditionProfile profile,
225-
@Cached MaterializeFrameNode materializeNode) {
225+
@Cached MaterializeFrameNode materializeNode,
226+
@Cached GetFrameLocalsNode getFrameLocalsNode) {
226227
// Special case because this builtin can be called without going through an invoke node:
227228
// we need to sync the values of the frame if and only if 'self' represents the current
228229
// frame. If 'self' represents another frame on the stack, the values are already
@@ -231,7 +232,7 @@ Object getUpdating(VirtualFrame frame, PFrame self,
231232
PFrame pyFrame = materializeNode.execute(frame, false, true, frame);
232233
assert pyFrame == self;
233234
}
234-
return self.getLocals();
235+
return getFrameLocalsNode.execute(frame, self);
235236
}
236237
}
237238

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

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,19 @@
4949
import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject;
5050
import com.oracle.graal.python.builtins.objects.object.PythonObject;
5151
import com.oracle.graal.python.nodes.bytecode.PBytecodeRootNode;
52+
import com.oracle.graal.python.nodes.frame.GetFrameLocalsNode;
5253
import com.oracle.graal.python.nodes.frame.MaterializeFrameNode;
5354
import com.oracle.graal.python.util.PythonUtils;
5455
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
5556
import com.oracle.truffle.api.RootCallTarget;
57+
import com.oracle.truffle.api.frame.MaterializedFrame;
5658
import com.oracle.truffle.api.nodes.Node;
5759
import com.oracle.truffle.api.source.SourceSection;
5860

5961
public final class PFrame extends PythonBuiltinObject {
6062
private Object[] arguments;
61-
private final Object localsDict;
63+
private final MaterializedFrame locals;
64+
private Object localsDict;
6265
private final Reference virtualFrameInfo;
6366
private Node location;
6467
private RootCallTarget callTarget;
@@ -150,44 +153,48 @@ public Reference getCallerInfo() {
150153
}
151154
}
152155

153-
public PFrame(PythonLanguage lang, Reference virtualFrameInfo, Node location) {
154-
this(lang, virtualFrameInfo, location, null);
155-
}
156-
157-
public PFrame(PythonLanguage lang, Reference virtualFrameInfo, Node location, Object locals) {
156+
public PFrame(PythonLanguage lang, Reference virtualFrameInfo, Node location, MaterializedFrame locals) {
158157
super(PythonBuiltinClassType.PFrame, PythonBuiltinClassType.PFrame.getInstanceShape(lang));
159158
this.virtualFrameInfo = virtualFrameInfo;
160-
this.localsDict = locals;
159+
this.locals = locals;
161160
this.location = location;
162161
}
163162

164-
public PFrame(PythonLanguage lang, @SuppressWarnings("unused") Object threadState, PCode code, PythonObject globals, Object locals) {
163+
public PFrame(PythonLanguage lang, @SuppressWarnings("unused") Object threadState, PCode code, PythonObject globals, Object localsDict) {
165164
super(PythonBuiltinClassType.PFrame, PythonBuiltinClassType.PFrame.getInstanceShape(lang));
166165
// TODO: frames: extract the information from the threadState object
167166
Object[] frameArgs = PArguments.create();
168167
PArguments.setGlobals(frameArgs, globals);
168+
PArguments.setSpecialArgument(frameArgs, localsDict);
169169
Reference curFrameInfo = new Reference(null);
170170
this.virtualFrameInfo = curFrameInfo;
171171
curFrameInfo.setPyFrame(this);
172172
this.location = GetCodeRootNode.getUncached().execute(code);
173173
this.line = this.location == null ? code.getFirstLineNo() : -2;
174174
this.arguments = frameArgs;
175+
this.locals = null;
176+
this.localsDict = localsDict;
177+
}
175178

176-
localsDict = locals;
179+
/**
180+
* Get the locals synced by {@link MaterializeFrameNode}. May be null when using custom locals.
181+
* In most cases, you should use {@link GetFrameLocalsNode}.
182+
*/
183+
public MaterializedFrame getLocals() {
184+
return locals;
177185
}
178186

179187
/**
180-
* Prefer to use the {@link GetLocalsNode}.<br/>
181-
* <br/>
182-
*
183-
* Returns a dictionary with the locals, possibly creating it from the frame. Note that the
184-
* dictionary may have been modified and should then be updated with the current frame locals.
185-
* To that end, use the {@link GetLocalsNode} instead of calling this method directly.
188+
* Use {@link GetFrameLocalsNode} instead of accessing this directly.
186189
*/
187190
public Object getLocalsDict() {
188191
return localsDict;
189192
}
190193

194+
public void setLocalsDict(Object dict) {
195+
localsDict = dict;
196+
}
197+
191198
public PFrame.Reference getRef() {
192199
return virtualFrameInfo;
193200
}
@@ -237,16 +244,6 @@ public int getLine() {
237244
return line;
238245
}
239246

240-
/**
241-
* Returns a dictionary with the locals. Note that the dictionary may have been modified and
242-
* should then be updated with the current frame locals. To that end, use the
243-
* {@link MaterializeFrameNode}.
244-
*/
245-
public Object getLocals() {
246-
assert localsDict != null;
247-
return localsDict;
248-
}
249-
250247
/**
251248
* Prefer to use the
252249
* {@link com.oracle.graal.python.builtins.objects.frame.FrameBuiltins.GetGlobalsNode}.<br/>

0 commit comments

Comments
 (0)