@@ -604,7 +604,7 @@ public abstract static class PutNode extends Node {
604604 // @formatter:on
605605 @ HostCompilerDirectives .InliningRoot
606606 public final void execute (DynamicObject receiver , Object key , Object value ) {
607- executeImpl (receiver , key , value , Flags .DEFAULT , 0 );
607+ executeImpl (receiver , key , value , 0 , Flags .DEFAULT );
608608 }
609609
610610 /**
@@ -618,7 +618,7 @@ public final void execute(DynamicObject receiver, Object key, Object value) {
618618 */
619619 @ HostCompilerDirectives .InliningRoot
620620 public final boolean executeIfPresent (DynamicObject receiver , Object key , Object value ) {
621- return executeImpl (receiver , key , value , Flags .IF_PRESENT , 0 );
621+ return executeImpl (receiver , key , value , 0 , Flags .IF_PRESENT );
622622 }
623623
624624 /**
@@ -632,7 +632,7 @@ public final boolean executeIfPresent(DynamicObject receiver, Object key, Object
632632 */
633633 @ HostCompilerDirectives .InliningRoot
634634 public final boolean executeIfAbsent (DynamicObject receiver , Object key , Object value ) {
635- return executeImpl (receiver , key , value , Flags .IF_ABSENT , 0 );
635+ return executeImpl (receiver , key , value , 0 , Flags .IF_ABSENT );
636636 }
637637
638638 /**
@@ -647,7 +647,7 @@ public final boolean executeIfAbsent(DynamicObject receiver, Object key, Object
647647 */
648648 @ HostCompilerDirectives .InliningRoot
649649 public final void executeWithFlags (DynamicObject receiver , Object key , Object value , int propertyFlags ) {
650- executeImpl (receiver , key , value , Flags .DEFAULT | Flags .UPDATE_FLAGS , propertyFlags );
650+ executeImpl (receiver , key , value , propertyFlags , Flags .DEFAULT | Flags .UPDATE_FLAGS );
651651 }
652652
653653 /**
@@ -656,7 +656,7 @@ public final void executeWithFlags(DynamicObject receiver, Object key, Object va
656656 */
657657 @ HostCompilerDirectives .InliningRoot
658658 public final boolean executeWithFlagsIfPresent (DynamicObject receiver , Object key , Object value , int propertyFlags ) {
659- return executeImpl (receiver , key , value , Flags .IF_PRESENT | Flags .UPDATE_FLAGS , propertyFlags );
659+ return executeImpl (receiver , key , value , propertyFlags , Flags .IF_PRESENT | Flags .UPDATE_FLAGS );
660660 }
661661
662662 /**
@@ -665,33 +665,30 @@ public final boolean executeWithFlagsIfPresent(DynamicObject receiver, Object ke
665665 */
666666 @ HostCompilerDirectives .InliningRoot
667667 public final boolean executeWithFlagsIfAbsent (DynamicObject receiver , Object key , Object value , int propertyFlags ) {
668- return executeImpl (receiver , key , value , Flags .IF_ABSENT | Flags .UPDATE_FLAGS , propertyFlags );
668+ return executeImpl (receiver , key , value , propertyFlags , Flags .IF_ABSENT | Flags .UPDATE_FLAGS );
669669 }
670670
671671 // private
672672
673- abstract boolean executeImpl (DynamicObject receiver , Object key , Object value , int mode , int propertyFlags );
673+ abstract boolean executeImpl (DynamicObject receiver , Object key , Object value , int propertyFlags , int mode );
674674
675675 @ SuppressWarnings ("unused" )
676676 @ Specialization (guards = {
677677 "guard" ,
678678 "key == cachedKey" ,
679- "mode == cachedMode" ,
680- "propertyFlags == cachedPropertyFlags" ,
679+ "propertyFlagsEqual(propertyFlags, mode, oldShape, newShape, oldProperty, newProperty)" ,
681680 "newLocation == null || newLocation.canStoreValue(value)" ,
682681 }, assumptions = "newShapeValidAssumption" , limit = "SHAPE_CACHE_LIMIT" )
683- static boolean doCached (DynamicObject receiver , Object key , Object value , int mode , int propertyFlags ,
682+ static boolean doCached (DynamicObject receiver , Object key , Object value , int propertyFlags , int mode ,
684683 @ Bind ("receiver.getShape()" ) Shape shape ,
685684 @ Cached ("shape" ) Shape oldShape ,
686685 @ Bind ("shape == oldShape" ) boolean guard ,
687686 @ Cached ("key" ) Object cachedKey ,
688- @ Cached ("mode" ) int cachedMode ,
689- @ Cached ("propertyFlags" ) int cachedPropertyFlags ,
690687 @ Cached ("oldShape.getProperty(key)" ) Property oldProperty ,
691- @ Cached ("getNewShapeAndCheckOldShapeStillValid(key, value, cachedPropertyFlags, cachedMode, oldProperty, oldShape)" ) Shape newShape ,
692- @ Cached ("getNewLocation(oldShape, newShape, key, oldProperty)" ) Location newLocation ,
688+ @ Cached ("getNewShapeAndCheckOldShapeStillValid(key, value, propertyFlags, mode, oldProperty, oldShape)" ) Shape newShape ,
689+ @ Cached ("getNewProperty(oldShape, newShape, key, oldProperty)" ) Property newProperty ,
690+ @ Cached ("getLocation(newProperty)" ) Location newLocation ,
693691 @ Cached ("newShape.getValidAbstractAssumption()" ) AbstractAssumption newShapeValidAssumption ) {
694- // We use mode instead of cachedMode to fold it during host inlining
695692 CompilerAsserts .partialEvaluationConstant (mode );
696693 if ((mode & Flags .IF_ABSENT ) != 0 && oldProperty != null ) {
697694 return false ;
@@ -715,13 +712,13 @@ static boolean doCached(DynamicObject receiver, Object key, Object value, int mo
715712 * still create new doCached instances, which is important once we see objects with the new
716713 * non-obsolete shape.
717714 */
718- @ Specialization (guards = "!receiver.getShape().isValid()" )
719- static boolean doInvalid (DynamicObject receiver , Object key , Object value , int mode , int propertyFlags ) {
715+ @ Specialization (guards = "!receiver.getShape().isValid()" , excludeForUncached = true )
716+ static boolean doInvalid (DynamicObject receiver , Object key , Object value , int propertyFlags , int mode ) {
720717 return ObsolescenceStrategy .putGeneric (receiver , key , value , propertyFlags , mode );
721718 }
722719
723720 @ Specialization (replaces = {"doCached" , "doInvalid" })
724- static boolean doGeneric (DynamicObject receiver , Object key , Object value , int mode , int propertyFlags ) {
721+ static boolean doGeneric (DynamicObject receiver , Object key , Object value , int propertyFlags , int mode ) {
725722 return ObsolescenceStrategy .putGeneric (receiver , key , value , propertyFlags , mode );
726723 }
727724
@@ -772,23 +769,23 @@ public abstract static class PutConstantNode extends Node {
772769 */
773770 @ HostCompilerDirectives .InliningRoot
774771 public final void execute (DynamicObject receiver , Object key , Object value ) {
775- executeImpl (receiver , key , value , Flags .DEFAULT | Flags .CONST , 0 );
772+ executeImpl (receiver , key , value , 0 , Flags .DEFAULT | Flags .CONST );
776773 }
777774
778775 /**
779776 * Like {@link #execute(DynamicObject, Object, Object)} but only if the property is present.
780777 */
781778 @ HostCompilerDirectives .InliningRoot
782779 public final boolean executeIfPresent (DynamicObject receiver , Object key , Object value ) {
783- return executeImpl (receiver , key , value , Flags .IF_PRESENT | Flags .CONST , 0 );
780+ return executeImpl (receiver , key , value , 0 , Flags .IF_PRESENT | Flags .CONST );
784781 }
785782
786783 /**
787784 * Like {@link #execute(DynamicObject, Object, Object)} but only if the property is absent.
788785 */
789786 @ HostCompilerDirectives .InliningRoot
790787 public final boolean executeIfAbsent (DynamicObject receiver , Object key , Object value ) {
791- return executeImpl (receiver , key , value , Flags .IF_ABSENT | Flags .CONST , 0 );
788+ return executeImpl (receiver , key , value , 0 , Flags .IF_ABSENT | Flags .CONST );
792789 }
793790
794791 // @formatter:off
@@ -831,7 +828,7 @@ public final boolean executeIfAbsent(DynamicObject receiver, Object key, Object
831828 // @formatter:on
832829 @ HostCompilerDirectives .InliningRoot
833830 public final void executeWithFlags (DynamicObject receiver , Object key , Object value , int propertyFlags ) {
834- executeImpl (receiver , key , value , Flags .DEFAULT | Flags .CONST | Flags .UPDATE_FLAGS , propertyFlags );
831+ executeImpl (receiver , key , value , propertyFlags , Flags .DEFAULT | Flags .CONST | Flags .UPDATE_FLAGS );
835832 }
836833
837834 /**
@@ -840,7 +837,7 @@ public final void executeWithFlags(DynamicObject receiver, Object key, Object va
840837 */
841838 @ HostCompilerDirectives .InliningRoot
842839 public final boolean executeWithFlagsIfPresent (DynamicObject receiver , Object key , Object value , int propertyFlags ) {
843- return executeImpl (receiver , key , value , Flags .IF_PRESENT | Flags .CONST | Flags .UPDATE_FLAGS , propertyFlags );
840+ return executeImpl (receiver , key , value , propertyFlags , Flags .IF_PRESENT | Flags .CONST | Flags .UPDATE_FLAGS );
844841 }
845842
846843 /**
@@ -849,33 +846,29 @@ public final boolean executeWithFlagsIfPresent(DynamicObject receiver, Object ke
849846 */
850847 @ HostCompilerDirectives .InliningRoot
851848 public final boolean executeWithFlagsIfAbsent (DynamicObject receiver , Object key , Object value , int propertyFlags ) {
852- return executeImpl (receiver , key , value , Flags .IF_ABSENT | Flags .CONST | Flags .UPDATE_FLAGS , propertyFlags );
849+ return executeImpl (receiver , key , value , propertyFlags , Flags .IF_ABSENT | Flags .CONST | Flags .UPDATE_FLAGS );
853850 }
854851
855852 // private
856853
857- abstract boolean executeImpl (DynamicObject receiver , Object key , Object value , int mode , int propertyFlags );
854+ abstract boolean executeImpl (DynamicObject receiver , Object key , Object value , int propertyFlags , int mode );
858855
859856 @ SuppressWarnings ("unused" )
860857 @ Specialization (guards = {
861858 "guard" ,
862859 "key == cachedKey" ,
863- "mode == cachedMode" ,
864- "propertyFlags == cachedPropertyFlags" ,
865- "newLocation == null || newLocation.canStoreConstant(value)" ,
860+ "propertyFlagsEqual(propertyFlags, mode, oldShape, newShape, oldProperty, newProperty)" ,
861+ "newProperty == null || newProperty.getLocation().canStoreConstant(value)" ,
866862 }, assumptions = "newShapeValidAssumption" , limit = "SHAPE_CACHE_LIMIT" )
867- static boolean doCached (DynamicObject receiver , Object key , Object value , int mode , int propertyFlags ,
863+ static boolean doCached (DynamicObject receiver , Object key , Object value , int propertyFlags , int mode ,
868864 @ Bind ("receiver.getShape()" ) Shape shape ,
869865 @ Cached ("shape" ) Shape oldShape ,
870866 @ Bind ("shape == oldShape" ) boolean guard ,
871867 @ Cached ("key" ) Object cachedKey ,
872- @ Cached ("mode" ) int cachedMode ,
873- @ Cached ("propertyFlags" ) int cachedPropertyFlags ,
874868 @ Cached ("oldShape.getProperty(key)" ) Property oldProperty ,
875- @ Cached ("getNewShapeAndCheckOldShapeStillValid(key, value, cachedPropertyFlags, cachedMode , oldProperty, oldShape)" ) Shape newShape ,
876- @ Cached ("getNewLocation (oldShape, newShape, key, oldProperty)" ) Location newLocation ,
869+ @ Cached ("getNewShapeAndCheckOldShapeStillValid(key, value, propertyFlags, mode , oldProperty, oldShape)" ) Shape newShape ,
870+ @ Cached ("getNewProperty (oldShape, newShape, key, oldProperty)" ) Property newProperty ,
877871 @ Cached ("newShape.getValidAbstractAssumption()" ) AbstractAssumption newShapeValidAssumption ) {
878- // We use mode instead of cachedMode to fold it during host inlining
879872 CompilerAsserts .partialEvaluationConstant (mode );
880873 if ((mode & Flags .IF_ABSENT ) != 0 && oldProperty != null ) {
881874 return false ;
@@ -897,13 +890,13 @@ static boolean doCached(DynamicObject receiver, Object key, Object value, int mo
897890 * still create new doCached instances, which is important once we see objects with the new
898891 * non-obsolete shape.
899892 */
900- @ Specialization (guards = "!receiver.getShape().isValid()" )
901- static boolean doInvalid (DynamicObject receiver , Object key , Object value , int mode , int propertyFlags ) {
893+ @ Specialization (guards = "!receiver.getShape().isValid()" , excludeForUncached = true )
894+ static boolean doInvalid (DynamicObject receiver , Object key , Object value , int propertyFlags , int mode ) {
902895 return ObsolescenceStrategy .putGeneric (receiver , key , value , propertyFlags , mode );
903896 }
904897
905898 @ Specialization (replaces = {"doCached" , "doInvalid" })
906- static boolean doGeneric (DynamicObject receiver , Object key , Object value , int mode , int propertyFlags ) {
899+ static boolean doGeneric (DynamicObject receiver , Object key , Object value , int propertyFlags , int mode ) {
907900 return ObsolescenceStrategy .putGeneric (receiver , key , value , propertyFlags , mode );
908901 }
909902
@@ -924,6 +917,24 @@ public static PutConstantNode getUncached() {
924917 }
925918 }
926919
920+ /**
921+ * {@return true if the cache entry can be used with the passed property flags and mode}
922+ *
923+ * <ol>
924+ * <li>ignore flags => new flags must equal old flags, if any, else passed flags</li>
925+ * <li>update flags => new flags must equal passed flags</li>
926+ * </ol>
927+ */
928+ static boolean propertyFlagsEqual (int propertyFlags , int mode , Shape oldShape , Shape newShape , Property oldProperty , Property newProperty ) {
929+ if (newProperty == null ) {
930+ assert oldProperty == null ;
931+ return (mode & Flags .IF_PRESENT ) != 0 ;
932+ }
933+ return (mode & Flags .UPDATE_FLAGS ) == 0
934+ ? oldShape == newShape || (oldProperty == null ? propertyFlags : oldProperty .getFlags ()) == newProperty .getFlags ()
935+ : propertyFlags == newProperty .getFlags ();
936+ }
937+
927938 static Shape getNewShape (Object cachedKey , Object value , int newPropertyFlags , int mode , Property existingProperty , Shape oldShape ) {
928939 if (existingProperty == null ) {
929940 if ((mode & Flags .IF_PRESENT ) != 0 ) {
@@ -957,14 +968,18 @@ static Shape getNewShapeAndCheckOldShapeStillValid(Object cachedKey, Object valu
957968 return newShape ;
958969 }
959970
960- static Location getNewLocation (Shape oldShape , Shape newShape , Object cachedKey , Property oldProperty ) {
971+ static Property getNewProperty (Shape oldShape , Shape newShape , Object cachedKey , Property oldProperty ) {
961972 if (newShape == oldShape ) {
962- return oldProperty == null ? null : oldProperty . getLocation () ;
973+ return oldProperty ;
963974 } else {
964- return newShape .getLocation (cachedKey );
975+ return newShape .getProperty (cachedKey );
965976 }
966977 }
967978
979+ static Location getLocation (Property property ) {
980+ return property == null ? null : property .getLocation ();
981+ }
982+
968983 /**
969984 * Copies all properties of a DynamicObject to another, preserving property flags. Does not copy
970985 * hidden properties.
0 commit comments