Skip to content

Commit 432a3b7

Browse files
committed
Fix: do not refresh values of a module and class body frame.
1 parent 9e86467 commit 432a3b7

File tree

1 file changed

+31
-15
lines changed

1 file changed

+31
-15
lines changed

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

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,14 @@
4242

4343
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
4444
import com.oracle.graal.python.builtins.objects.cell.PCell;
45-
import com.oracle.graal.python.builtins.objects.common.HashingCollectionNodes.SetItemNode;
45+
import com.oracle.graal.python.builtins.objects.common.HashingCollectionNodes;
4646
import com.oracle.graal.python.builtins.objects.common.HashingStorage;
47+
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes;
4748
import com.oracle.graal.python.builtins.objects.common.LocalsStorage;
4849
import com.oracle.graal.python.builtins.objects.dict.PDict;
4950
import com.oracle.graal.python.builtins.objects.frame.PFrame;
5051
import com.oracle.graal.python.builtins.objects.function.PArguments;
52+
import com.oracle.graal.python.nodes.ModuleRootNode;
5153
import com.oracle.graal.python.nodes.SpecialMethodNames;
5254
import com.oracle.graal.python.nodes.function.ClassBodyRootNode;
5355
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
@@ -108,7 +110,7 @@ static PFrame freshPFrame(VirtualFrame frame, Node location, boolean markAsEscap
108110
@Shared("syncValuesNode") @Cached SyncFrameValuesNode syncValuesNode) {
109111
PDict locals = factory.createDictLocals(frameToMaterialize.getFrameDescriptor());
110112
PFrame escapedFrame = factory.createPFrame(PArguments.getCurrentFrameInfo(frameToMaterialize), location, locals, false);
111-
return doEscapeFrame(frame, frameToMaterialize, escapedFrame, markAsEscaped, forceSync, syncValuesNode);
113+
return doEscapeFrame(frame, frameToMaterialize, escapedFrame, markAsEscaped, forceSync && !inModuleRoot(location), syncValuesNode);
112114
}
113115

114116
@Specialization(guards = {"getPFrame(frameToMaterialize) == null", "inClassBody(frameToMaterialize)"})
@@ -130,19 +132,19 @@ static PFrame freshPFrameInClassBody(VirtualFrame frame, Node location, boolean
130132
* @see PFrame#isIncomplete
131133
**/
132134
@Specialization(guards = {"getPFrame(frameToMaterialize) != null", "!getPFrame(frameToMaterialize).hasFrame()"})
133-
static PFrame incompleteFrame(VirtualFrame frame, Node location, boolean markAsEscaped, @SuppressWarnings("unused") boolean forceSync, Frame frameToMaterialize,
135+
static PFrame incompleteFrame(VirtualFrame frame, Node location, boolean markAsEscaped, boolean forceSync, Frame frameToMaterialize,
134136
@Shared("factory") @Cached PythonObjectFactory factory,
135137
@Shared("syncValuesNode") @Cached SyncFrameValuesNode syncValuesNode) {
136138
Object locals = getPFrame(frameToMaterialize).getLocalsDict();
137139
PFrame escapedFrame = factory.createPFrame(PArguments.getCurrentFrameInfo(frameToMaterialize), location, locals, inClassBody(frameToMaterialize));
138-
return doEscapeFrame(frame, frameToMaterialize, escapedFrame, markAsEscaped, forceSync, syncValuesNode);
140+
return doEscapeFrame(frame, frameToMaterialize, escapedFrame, markAsEscaped, forceSync && !inModuleRoot(location), syncValuesNode);
139141
}
140142

141143
@Specialization(guards = {"getPFrame(frameToMaterialize) != null", "getPFrame(frameToMaterialize).hasFrame()"}, replaces = "freshPFrame")
142144
static PFrame alreadyEscapedFrame(VirtualFrame frame, Node location, boolean markAsEscaped, boolean forceSync, Frame frameToMaterialize,
143145
@Shared("syncValuesNode") @Cached SyncFrameValuesNode syncValuesNode) {
144146
PFrame pyFrame = getPFrame(frameToMaterialize);
145-
if (forceSync) {
147+
if (forceSync && !inClassBody(frameToMaterialize) && !inModuleRoot(location)) {
146148
syncValuesNode.execute(frame, pyFrame, frameToMaterialize);
147149
}
148150
if (markAsEscaped) {
@@ -211,6 +213,11 @@ protected static PFrame getPFrame(Frame frame) {
211213
return PArguments.getCurrentFrameInfo(frame).getPyFrame();
212214
}
213215

216+
protected static boolean inModuleRoot(Node location) {
217+
assert location != null;
218+
return location.getRootNode() instanceof ModuleRootNode;
219+
}
220+
214221
/**
215222
* When refreshing the frame values in the locals dict, there are 4 cases:
216223
* <ol>
@@ -314,7 +321,8 @@ static void doGenericDictCached(VirtualFrame frame, PFrame pyFrame, Frame frameT
314321
@Cached("frameToSync.getFrameDescriptor()") @SuppressWarnings("unused") FrameDescriptor cachedFd,
315322
@Cached(value = "getSlots(cachedFd)", dimensions = 1) FrameSlot[] cachedSlots,
316323
@Cached(value = "getProfiles(cachedSlots.length)", dimensions = 1) ConditionProfile[] profiles,
317-
@Cached SetItemNode setItemNode) {
324+
@Cached HashingCollectionNodes.SetItemNode setItemNode,
325+
@Cached HashingStorageNodes.DelItemNode deleteItemNode) {
318326
// This can happen if someone received the locals dict using 'locals()' or similar and
319327
// then assigned to the dictionary. Assigning will switch the storage. But we still must
320328
// refresh the values.
@@ -327,19 +335,19 @@ static void doGenericDictCached(VirtualFrame frame, PFrame pyFrame, Frame frameT
327335
if (FrameSlotIDs.isUserFrameSlot(slot.getIdentifier())) {
328336
Object value = frameToSync.getValue(slot);
329337
if (value != null) {
330-
if (profiles[i].profile(value instanceof PCell)) {
331-
setItemNode.execute(frame, localsDict, slot.getIdentifier(), ((PCell) value).getRef());
332-
} else {
333-
setItemNode.execute(frame, localsDict, slot.getIdentifier(), value);
334-
}
338+
setItemNode.execute(frame, localsDict, slot.getIdentifier(), resolveCellValue(profiles[i], value));
339+
} else {
340+
// delete variable
341+
deleteItemNode.execute(frame, localsDict, localsDict.getDictStorage(), slot.getIdentifier());
335342
}
336343
}
337344
}
338345
}
339346

340347
@Specialization(guards = "isDictWithCustomStorage(pyFrame)", replaces = "doGenericDictCached")
341348
static void doGenericDict(VirtualFrame frame, PFrame pyFrame, Frame frameToSync,
342-
@Cached SetItemNode setItemNode) {
349+
@Cached HashingCollectionNodes.SetItemNode setItemNode,
350+
@Cached HashingStorageNodes.DelItemNode deleteItemNode) {
343351
// This can happen if someone received the locals dict using 'locals()' or similar and
344352
// then assigned to the dictionary. Assigning will switch the storage. But we still must
345353
// refresh the values.
@@ -353,10 +361,11 @@ static void doGenericDict(VirtualFrame frame, PFrame pyFrame, Frame frameToSync,
353361
FrameSlot slot = slots[i];
354362
if (FrameSlotIDs.isUserFrameSlot(slot.getIdentifier())) {
355363
Object value = frameToSync.getValue(slot);
356-
if (value instanceof PCell) {
357-
setItemNode.execute(frame, localsDict, slot.getIdentifier(), ((PCell) value).getRef());
364+
if (value != null) {
365+
setItemNode.execute(frame, localsDict, slot.getIdentifier(), resolveCellValue(ConditionProfile.getUncached(), value));
358366
} else {
359-
setItemNode.execute(frame, localsDict, slot.getIdentifier(), value);
367+
// delete variable
368+
deleteItemNode.execute(frame, localsDict, localsDict.getDictStorage(), slot.getIdentifier());
360369
}
361370
}
362371
}
@@ -410,5 +419,12 @@ private static FrameDescriptor getFd(HashingStorage storage) {
410419
}
411420
return null;
412421
}
422+
423+
private static Object resolveCellValue(ConditionProfile profile, Object value) {
424+
if (profile.profile(value instanceof PCell)) {
425+
return ((PCell) value).getRef();
426+
}
427+
return value;
428+
}
413429
}
414430
}

0 commit comments

Comments
 (0)