@@ -65,24 +65,70 @@ public static ReadAttributeFromObjectNode create() {
6565
6666 public abstract Object execute (Object object , Object key );
6767
68- protected Location getLocationOrNull (Property prop ) {
68+ protected static Location getLocationOrNull (Property prop ) {
6969 return prop == null ? null : prop .getLocation ();
7070 }
7171
72+ protected static boolean isNull (Object value ) {
73+ return value == null ;
74+ }
75+
76+ protected static Object readFinalValue (PythonObject object , Location location ) {
77+ Object value = location .get (object .getStorage ());
78+ return value == null ? PNone .NO_VALUE : value ;
79+ }
80+
81+ /*
82+ * Includes "object" as a parameter so that Truffle DSL sees this as a dynamic check.
83+ */
84+ protected static boolean checkShape (@ SuppressWarnings ("unused" ) PythonObject object , PythonObject cachedObject , Shape cachedShape ) {
85+ return cachedObject .getStorage ().getShape () == cachedShape ;
86+ }
87+
88+ @ SuppressWarnings ("unused" )
89+ @ Specialization (limit = "1" , //
90+ guards = {
91+ "object == cachedObject" ,
92+ "checkShape(object, cachedObject, cachedShape)" ,
93+ "key == cachedKey" ,
94+ "!isNull(loc)" ,
95+ "loc.isAssumedFinal()"
96+ }, //
97+ assumptions = {
98+ "layoutAssumption" ,
99+ "finalAssumption"
100+ })
101+ protected Object readDirectFinal (PythonObject object , Object key ,
102+ @ Cached ("object" ) PythonObject cachedObject ,
103+ @ Cached ("key" ) Object cachedKey ,
104+ @ Cached ("object.getStorage().getShape()" ) Shape cachedShape ,
105+ @ Cached ("cachedShape.getValidAssumption()" ) Assumption layoutAssumption ,
106+ @ Cached ("getLocationOrNull(cachedShape.getProperty(key))" ) Location loc ,
107+ @ Cached ("loc.getFinalAssumption()" ) Assumption finalAssumption ,
108+ @ Cached ("readFinalValue(object, loc)" ) Object cachedValue ) {
109+ assert assertFinal (object , key , cachedValue );
110+ return cachedValue ;
111+ }
112+
113+ private static boolean assertFinal (PythonObject object , Object key , Object cachedValue ) {
114+ Object other = object .getStorage ().get (key ) == null ? PNone .NO_VALUE : object .getStorage ().get (key );
115+ return cachedValue == other || cachedValue instanceof Number && other instanceof Number && ((Number ) cachedValue ).doubleValue () == ((Number ) other ).doubleValue ();
116+ }
117+
72118 @ SuppressWarnings ("unused" )
73119 @ Specialization (limit = "getIntOption(getContext(), AttributeAccessInlineCacheMaxDepth)" , //
74120 guards = {
75121 "object.getStorage().getShape() == cachedShape" ,
76- "key == cachedKey"
122+ "key == cachedKey" ,
123+ "isNull(loc) || !loc.isAssumedFinal()"
77124 }, //
78125 assumptions = "layoutAssumption" )
79126 protected Object readDirect (PythonObject object , Object key ,
80127 @ Cached ("key" ) Object cachedKey ,
81128 @ Cached ("object.getStorage().getShape()" ) Shape cachedShape ,
82129 @ Cached ("cachedShape.getValidAssumption()" ) Assumption layoutAssumption ,
83- @ Cached ("cachedShape.getProperty(key)" ) Property prop ,
84- @ Cached ("getLocationOrNull(prop)" ) Location loc ) {
85- if (prop == null ) {
130+ @ Cached ("getLocationOrNull(cachedShape.getProperty(key))" ) Location loc ) {
131+ if (loc == null ) {
86132 return PNone .NO_VALUE ;
87133 } else {
88134 return loc .get (object .getStorage ());
0 commit comments