42
42
43
43
import com .oracle .graal .python .builtins .PythonBuiltinClassType ;
44
44
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 ;
46
46
import com .oracle .graal .python .builtins .objects .common .HashingStorage ;
47
+ import com .oracle .graal .python .builtins .objects .common .HashingStorageNodes ;
47
48
import com .oracle .graal .python .builtins .objects .common .LocalsStorage ;
48
49
import com .oracle .graal .python .builtins .objects .dict .PDict ;
49
50
import com .oracle .graal .python .builtins .objects .frame .PFrame ;
50
51
import com .oracle .graal .python .builtins .objects .function .PArguments ;
52
+ import com .oracle .graal .python .nodes .ModuleRootNode ;
51
53
import com .oracle .graal .python .nodes .SpecialMethodNames ;
52
54
import com .oracle .graal .python .nodes .function .ClassBodyRootNode ;
53
55
import com .oracle .graal .python .runtime .object .PythonObjectFactory ;
@@ -108,7 +110,7 @@ static PFrame freshPFrame(VirtualFrame frame, Node location, boolean markAsEscap
108
110
@ Shared ("syncValuesNode" ) @ Cached SyncFrameValuesNode syncValuesNode ) {
109
111
PDict locals = factory .createDictLocals (frameToMaterialize .getFrameDescriptor ());
110
112
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 );
112
114
}
113
115
114
116
@ Specialization (guards = {"getPFrame(frameToMaterialize) == null" , "inClassBody(frameToMaterialize)" })
@@ -130,19 +132,19 @@ static PFrame freshPFrameInClassBody(VirtualFrame frame, Node location, boolean
130
132
* @see PFrame#isIncomplete
131
133
**/
132
134
@ 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 ,
134
136
@ Shared ("factory" ) @ Cached PythonObjectFactory factory ,
135
137
@ Shared ("syncValuesNode" ) @ Cached SyncFrameValuesNode syncValuesNode ) {
136
138
Object locals = getPFrame (frameToMaterialize ).getLocalsDict ();
137
139
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 );
139
141
}
140
142
141
143
@ Specialization (guards = {"getPFrame(frameToMaterialize) != null" , "getPFrame(frameToMaterialize).hasFrame()" }, replaces = "freshPFrame" )
142
144
static PFrame alreadyEscapedFrame (VirtualFrame frame , Node location , boolean markAsEscaped , boolean forceSync , Frame frameToMaterialize ,
143
145
@ Shared ("syncValuesNode" ) @ Cached SyncFrameValuesNode syncValuesNode ) {
144
146
PFrame pyFrame = getPFrame (frameToMaterialize );
145
- if (forceSync ) {
147
+ if (forceSync && ! inClassBody ( frameToMaterialize ) && ! inModuleRoot ( location ) ) {
146
148
syncValuesNode .execute (frame , pyFrame , frameToMaterialize );
147
149
}
148
150
if (markAsEscaped ) {
@@ -211,6 +213,11 @@ protected static PFrame getPFrame(Frame frame) {
211
213
return PArguments .getCurrentFrameInfo (frame ).getPyFrame ();
212
214
}
213
215
216
+ protected static boolean inModuleRoot (Node location ) {
217
+ assert location != null ;
218
+ return location .getRootNode () instanceof ModuleRootNode ;
219
+ }
220
+
214
221
/**
215
222
* When refreshing the frame values in the locals dict, there are 4 cases:
216
223
* <ol>
@@ -314,7 +321,8 @@ static void doGenericDictCached(VirtualFrame frame, PFrame pyFrame, Frame frameT
314
321
@ Cached ("frameToSync.getFrameDescriptor()" ) @ SuppressWarnings ("unused" ) FrameDescriptor cachedFd ,
315
322
@ Cached (value = "getSlots(cachedFd)" , dimensions = 1 ) FrameSlot [] cachedSlots ,
316
323
@ Cached (value = "getProfiles(cachedSlots.length)" , dimensions = 1 ) ConditionProfile [] profiles ,
317
- @ Cached SetItemNode setItemNode ) {
324
+ @ Cached HashingCollectionNodes .SetItemNode setItemNode ,
325
+ @ Cached HashingStorageNodes .DelItemNode deleteItemNode ) {
318
326
// This can happen if someone received the locals dict using 'locals()' or similar and
319
327
// then assigned to the dictionary. Assigning will switch the storage. But we still must
320
328
// refresh the values.
@@ -327,19 +335,19 @@ static void doGenericDictCached(VirtualFrame frame, PFrame pyFrame, Frame frameT
327
335
if (FrameSlotIDs .isUserFrameSlot (slot .getIdentifier ())) {
328
336
Object value = frameToSync .getValue (slot );
329
337
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 ());
335
342
}
336
343
}
337
344
}
338
345
}
339
346
340
347
@ Specialization (guards = "isDictWithCustomStorage(pyFrame)" , replaces = "doGenericDictCached" )
341
348
static void doGenericDict (VirtualFrame frame , PFrame pyFrame , Frame frameToSync ,
342
- @ Cached SetItemNode setItemNode ) {
349
+ @ Cached HashingCollectionNodes .SetItemNode setItemNode ,
350
+ @ Cached HashingStorageNodes .DelItemNode deleteItemNode ) {
343
351
// This can happen if someone received the locals dict using 'locals()' or similar and
344
352
// then assigned to the dictionary. Assigning will switch the storage. But we still must
345
353
// refresh the values.
@@ -353,10 +361,11 @@ static void doGenericDict(VirtualFrame frame, PFrame pyFrame, Frame frameToSync,
353
361
FrameSlot slot = slots [i ];
354
362
if (FrameSlotIDs .isUserFrameSlot (slot .getIdentifier ())) {
355
363
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 ));
358
366
} else {
359
- setItemNode .execute (frame , localsDict , slot .getIdentifier (), value );
367
+ // delete variable
368
+ deleteItemNode .execute (frame , localsDict , localsDict .getDictStorage (), slot .getIdentifier ());
360
369
}
361
370
}
362
371
}
@@ -410,5 +419,12 @@ private static FrameDescriptor getFd(HashingStorage storage) {
410
419
}
411
420
return null ;
412
421
}
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
+ }
413
429
}
414
430
}
0 commit comments