5757import com .oracle .graal .python .nodes .function .ClassBodyRootNode ;
5858import com .oracle .graal .python .nodes .object .GetClassNode ;
5959import com .oracle .graal .python .runtime .object .PythonObjectFactory ;
60+ import com .oracle .graal .python .util .PythonUtils ;
6061import com .oracle .truffle .api .CompilerDirectives ;
6162import com .oracle .truffle .api .dsl .Cached ;
6263import com .oracle .truffle .api .dsl .Cached .Shared ;
@@ -295,138 +296,30 @@ public abstract static class SyncFrameValuesNode extends Node {
295296 static void doLocalsStorageCachedAST (PFrame pyFrame , Frame frameToSync , @ SuppressWarnings ("unused" ) Node location ,
296297 @ Cached ("createClassProfile()" ) ValueProfile frameProfile ,
297298 @ Cached ("frameToSync.getFrameDescriptor()" ) FrameDescriptor cachedFd ) {
298- boolean invalidState = false ;
299299 LocalsStorage localsStorage = getLocalsStorage (pyFrame );
300300 MaterializedFrame target = frameProfile .profile (localsStorage .getFrame ());
301301 assert cachedFd == target .getFrameDescriptor ();
302302
303303 for (int slot = 0 ; slot < cachedFd .getNumberOfSlots (); slot ++) {
304304 if (FrameSlotIDs .isUserFrameSlot (cachedFd .getSlotName (slot ))) {
305- if (frameToSync .isBoolean (slot )) {
306- try {
307- target .setBoolean (slot , frameToSync .getBoolean (slot ));
308- } catch (FrameSlotTypeException e ) {
309- CompilerDirectives .transferToInterpreter ();
310- invalidState = true ;
311- }
312- } else if (frameToSync .isByte (slot )) {
313- try {
314- target .setByte (slot , frameToSync .getByte (slot ));
315- } catch (FrameSlotTypeException e ) {
316- CompilerDirectives .transferToInterpreter ();
317- invalidState = true ;
318- }
319- } else if (frameToSync .isDouble (slot )) {
320- try {
321- target .setDouble (slot , frameToSync .getDouble (slot ));
322- } catch (FrameSlotTypeException e ) {
323- CompilerDirectives .transferToInterpreter ();
324- invalidState = true ;
325- }
326- } else if (frameToSync .isFloat (slot )) {
327- try {
328- target .setFloat (slot , frameToSync .getFloat (slot ));
329- } catch (FrameSlotTypeException e ) {
330- CompilerDirectives .transferToInterpreter ();
331- invalidState = true ;
332- }
333- } else if (frameToSync .isInt (slot )) {
334- try {
335- target .setInt (slot , frameToSync .getInt (slot ));
336- } catch (FrameSlotTypeException e ) {
337- CompilerDirectives .transferToInterpreter ();
338- invalidState = true ;
339- }
340- } else if (frameToSync .isLong (slot )) {
341- try {
342- target .setLong (slot , frameToSync .getLong (slot ));
343- } catch (FrameSlotTypeException e ) {
344- CompilerDirectives .transferToInterpreter ();
345- invalidState = true ;
346- }
347- } else if (frameToSync .isObject (slot )) {
348- try {
349- target .setObject (slot , frameToSync .getObject (slot ));
350- } catch (FrameSlotTypeException e ) {
351- CompilerDirectives .transferToInterpreter ();
352- invalidState = true ;
353- }
354- }
305+ PythonUtils .copyFrameSlot (frameToSync , target , slot );
355306 }
356307 }
357- if (CompilerDirectives .inInterpreter () && invalidState ) {
358- // we're always in the interpreter if invalidState was set
359- throw new IllegalStateException ("the frame lied about the frame slot type" );
360- }
361308 }
362309
363310 @ Specialization (guards = {"!isBytecodeFrame(frameToSync)" , "hasLocalsStorage(pyFrame, frameToSync, frameProfile)" , "frameToSync.getFrameDescriptor() == cachedFd" }, limit = "1" )
364311 static void doLocalsStorageLoopAST (PFrame pyFrame , Frame frameToSync , @ SuppressWarnings ("unused" ) Node location ,
365312 @ Cached ("createClassProfile()" ) ValueProfile frameProfile ,
366313 @ Cached ("frameToSync.getFrameDescriptor()" ) FrameDescriptor cachedFd ) {
367- boolean invalidState = false ;
368314 LocalsStorage localsStorage = getLocalsStorage (pyFrame );
369315 MaterializedFrame target = frameProfile .profile (localsStorage .getFrame ());
370316 assert cachedFd == target .getFrameDescriptor ();
371317
372318 for (int slot = 0 ; slot < cachedFd .getNumberOfSlots (); slot ++) {
373319 if (FrameSlotIDs .isUserFrameSlot (cachedFd .getSlotName (slot ))) {
374- if (frameToSync .isBoolean (slot )) {
375- try {
376- target .setBoolean (slot , frameToSync .getBoolean (slot ));
377- } catch (FrameSlotTypeException e ) {
378- CompilerDirectives .transferToInterpreter ();
379- invalidState = true ;
380- }
381- } else if (frameToSync .isByte (slot )) {
382- try {
383- target .setByte (slot , frameToSync .getByte (slot ));
384- } catch (FrameSlotTypeException e ) {
385- CompilerDirectives .transferToInterpreter ();
386- invalidState = true ;
387- }
388- } else if (frameToSync .isDouble (slot )) {
389- try {
390- target .setDouble (slot , frameToSync .getDouble (slot ));
391- } catch (FrameSlotTypeException e ) {
392- CompilerDirectives .transferToInterpreter ();
393- invalidState = true ;
394- }
395- } else if (frameToSync .isFloat (slot )) {
396- try {
397- target .setFloat (slot , frameToSync .getFloat (slot ));
398- } catch (FrameSlotTypeException e ) {
399- CompilerDirectives .transferToInterpreter ();
400- invalidState = true ;
401- }
402- } else if (frameToSync .isInt (slot )) {
403- try {
404- target .setInt (slot , frameToSync .getInt (slot ));
405- } catch (FrameSlotTypeException e ) {
406- CompilerDirectives .transferToInterpreter ();
407- invalidState = true ;
408- }
409- } else if (frameToSync .isLong (slot )) {
410- try {
411- target .setLong (slot , frameToSync .getLong (slot ));
412- } catch (FrameSlotTypeException e ) {
413- CompilerDirectives .transferToInterpreter ();
414- invalidState = true ;
415- }
416- } else if (frameToSync .isObject (slot )) {
417- try {
418- target .setObject (slot , frameToSync .getObject (slot ));
419- } catch (FrameSlotTypeException e ) {
420- CompilerDirectives .transferToInterpreter ();
421- invalidState = true ;
422- }
423- }
320+ PythonUtils .copyFrameSlot (frameToSync , target , slot );
424321 }
425322 }
426- if (CompilerDirectives .inInterpreter () && invalidState ) {
427- // we're always in the interpreter if invalidState was set
428- throw new IllegalStateException ("the frame lied about the frame slot type" );
429- }
430323 }
431324
432325 @ Specialization (guards = {"!isBytecodeFrame(frameToSync)" , "hasLocalsStorage(pyFrame, frameToSync, frameProfile)" }, replaces = {"doLocalsStorageCachedAST" , "doLocalsStorageLoopAST" })
@@ -440,21 +333,7 @@ static void doLocalsStorageUncachedAST(PFrame pyFrame, Frame frameToSync, @Suppr
440333
441334 for (int slot = 0 ; slot < fd .getNumberOfSlots (); slot ++) {
442335 if (FrameSlotIDs .isUserFrameSlot (fd .getSlotName (slot ))) {
443- if (frameToSync .isBoolean (slot )) {
444- target .setBoolean (slot , frameToSync .getBoolean (slot ));
445- } else if (frameToSync .isByte (slot )) {
446- target .setByte (slot , frameToSync .getByte (slot ));
447- } else if (frameToSync .isDouble (slot )) {
448- target .setDouble (slot , frameToSync .getDouble (slot ));
449- } else if (frameToSync .isFloat (slot )) {
450- target .setFloat (slot , frameToSync .getFloat (slot ));
451- } else if (frameToSync .isInt (slot )) {
452- target .setInt (slot , frameToSync .getInt (slot ));
453- } else if (frameToSync .isLong (slot )) {
454- target .setLong (slot , frameToSync .getLong (slot ));
455- } else if (frameToSync .isObject (slot )) {
456- target .setObject (slot , frameToSync .getObject (slot ));
457- }
336+ PythonUtils .copyFrameSlot (frameToSync , target , slot );
458337 }
459338 }
460339 } catch (FrameSlotTypeException e ) {
@@ -560,7 +439,8 @@ static void doCustomLocalsObject(PFrame pyFrame, Frame frameToSync, @SuppressWar
560439 // nothing to do; we already worked on the custom object
561440 }
562441
563- @ Specialization (guards = {"isBytecodeFrame(frameToSync)" , "hasLocalsStorage(pyFrame, frameToSync, frameProfile)" , "frameToSync.getFrameDescriptor() == cachedFd" }, limit = "1" )
442+ @ Specialization (guards = {"isBytecodeFrame(frameToSync)" , "hasLocalsStorage(pyFrame, frameToSync, frameProfile)" , "frameToSync.getFrameDescriptor() == cachedFd" ,
443+ "variableSlotCount(cachedFd) < 32" }, limit = "1" )
564444 @ ExplodeLoop
565445 static void doLocalsStorageCachedExploded (PFrame pyFrame , Frame frameToSync , @ SuppressWarnings ("unused" ) Node location ,
566446 @ Cached ("createClassProfile()" ) ValueProfile frameProfile ,
@@ -570,7 +450,7 @@ static void doLocalsStorageCachedExploded(PFrame pyFrame, Frame frameToSync, @Su
570450 assert cachedFd == target .getFrameDescriptor ();
571451 int slotCount = variableSlotCount (cachedFd );
572452 for (int slot = 0 ; slot < slotCount ; slot ++) {
573- copySlot (frameToSync , target , slot );
453+ PythonUtils . copyFrameSlot (frameToSync , target , slot );
574454 }
575455 }
576456
@@ -584,7 +464,7 @@ static void doLocalsStorageCachedLoop(PFrame pyFrame, Frame frameToSync, @Suppre
584464 assert cachedFd == target .getFrameDescriptor ();
585465 int slotCount = variableSlotCount (cachedFd );
586466 for (int slot = 0 ; slot < slotCount ; slot ++) {
587- copySlot (frameToSync , target , slot );
467+ PythonUtils . copyFrameSlot (frameToSync , target , slot );
588468 }
589469 }
590470
@@ -595,17 +475,18 @@ static void doLocalsStorageUncached(PFrame pyFrame, Frame frameToSync, @Suppress
595475 MaterializedFrame target = frameProfile .profile (localsStorage .getFrame ());
596476 int slotCount = variableSlotCount (frameToSync .getFrameDescriptor ());
597477 for (int slot = 0 ; slot < slotCount ; slot ++) {
598- copySlot (frameToSync , target , slot );
478+ PythonUtils . copyFrameSlot (frameToSync , target , slot );
599479 }
600480 }
601481
602482 @ Specialization (guards = { //
603483 "isBytecodeFrame(frameToSync)" ,
604484 "isDictWithCustomStorage(pyFrame)" ,
605485 "frameToSync.getFrameDescriptor() == cachedFd" ,
486+ "variableSlotCount(cachedFd) < 32"
606487 }, limit = "1" )
607488 @ ExplodeLoop
608- static void doGenericDictCached (VirtualFrame frame , PFrame pyFrame , Frame frameToSync , @ SuppressWarnings ("unused" ) Node location ,
489+ static void doGenericDictCachedExploded (VirtualFrame frame , PFrame pyFrame , Frame frameToSync , @ SuppressWarnings ("unused" ) Node location ,
609490 @ Cached ("frameToSync.getFrameDescriptor()" ) @ SuppressWarnings ("unused" ) FrameDescriptor cachedFd ,
610491 @ Cached (value = "getProfiles(variableSlotCount(cachedFd))" , dimensions = 1 ) ConditionProfile [] profiles ,
611492 @ Cached BranchProfile updatedStorage ,
@@ -625,7 +506,32 @@ static void doGenericDictCached(VirtualFrame frame, PFrame pyFrame, Frame frameT
625506 }
626507 }
627508
628- @ Specialization (guards = {"isBytecodeFrame(frameToSync)" , "isDictWithCustomStorage(pyFrame)" }, replaces = "doGenericDictCached" )
509+ @ Specialization (guards = { //
510+ "isBytecodeFrame(frameToSync)" ,
511+ "isDictWithCustomStorage(pyFrame)" ,
512+ "frameToSync.getFrameDescriptor() == cachedFd" ,
513+ }, limit = "1" , replaces = "doGenericDictCachedExploded" )
514+ static void doGenericDictCachedLoop (VirtualFrame frame , PFrame pyFrame , Frame frameToSync , @ SuppressWarnings ("unused" ) Node location ,
515+ @ Cached ("frameToSync.getFrameDescriptor()" ) @ SuppressWarnings ("unused" ) FrameDescriptor cachedFd ,
516+ @ Cached (value = "getProfiles(variableSlotCount(cachedFd))" , dimensions = 1 ) ConditionProfile [] profiles ,
517+ @ Cached BranchProfile updatedStorage ,
518+ @ Cached ConditionProfile hasFrame ,
519+ @ CachedLibrary (limit = "1" ) HashingStorageLibrary lib ) {
520+ // This can happen if someone received the locals dict using 'locals()' or similar and
521+ // then assigned to the dictionary. Assigning will switch the storage. But we still must
522+ // refresh the values.
523+
524+ // The cast is guaranteed by the guard.
525+ PDict localsDict = (PDict ) pyFrame .getLocalsDict ();
526+ FrameInfo info = (FrameInfo ) cachedFd .getInfo ();
527+ int slotCount = info .getVariableCount ();
528+ for (int slot = 0 ; slot < slotCount ; slot ++) {
529+ ConditionProfile profile = profiles [slot ];
530+ syncDict (frame , slot , info , frameToSync , localsDict , lib , hasFrame , updatedStorage , profile );
531+ }
532+ }
533+
534+ @ Specialization (guards = {"isBytecodeFrame(frameToSync)" , "isDictWithCustomStorage(pyFrame)" }, replaces = {"doGenericDictCachedExploded" , "doGenericDictCachedLoop" })
629535 static void doGenericDict (VirtualFrame frame , PFrame pyFrame , Frame frameToSync , @ SuppressWarnings ("unused" ) Node location ,
630536 @ Cached BranchProfile updatedStorage ,
631537 @ Cached ConditionProfile hasFrame ,
@@ -728,23 +634,5 @@ private static Object resolveCellValue(ConditionProfile profile, Object value) {
728634 public static SyncFrameValuesNode create () {
729635 return SyncFrameValuesNodeGen .create ();
730636 }
731-
732- public static void copySlot (Frame frameToSync , MaterializedFrame target , int slot ) {
733- if (frameToSync .isBoolean (slot )) {
734- target .setBoolean (slot , frameToSync .getBoolean (slot ));
735- } else if (frameToSync .isByte (slot )) {
736- target .setByte (slot , frameToSync .getByte (slot ));
737- } else if (frameToSync .isDouble (slot )) {
738- target .setDouble (slot , frameToSync .getDouble (slot ));
739- } else if (frameToSync .isFloat (slot )) {
740- target .setFloat (slot , frameToSync .getFloat (slot ));
741- } else if (frameToSync .isInt (slot )) {
742- target .setInt (slot , frameToSync .getInt (slot ));
743- } else if (frameToSync .isLong (slot )) {
744- target .setLong (slot , frameToSync .getLong (slot ));
745- } else if (frameToSync .isObject (slot )) {
746- target .setObject (slot , frameToSync .getObject (slot ));
747- }
748- }
749637 }
750638}
0 commit comments