50
50
import com .oracle .graal .python .builtins .objects .dict .PDict ;
51
51
import com .oracle .graal .python .builtins .objects .object .PythonObject ;
52
52
import com .oracle .graal .python .builtins .objects .object .PythonObjectLibrary ;
53
+ import com .oracle .graal .python .builtins .objects .type .PythonBuiltinClass ;
54
+ import com .oracle .graal .python .builtins .objects .type .PythonClass ;
53
55
import com .oracle .graal .python .builtins .objects .type .PythonManagedClass ;
54
56
import com .oracle .graal .python .builtins .objects .type .SpecialMethodSlot ;
55
57
import com .oracle .graal .python .builtins .objects .type .TypeNodes .IsTypeNode ;
70
72
import com .oracle .truffle .api .dsl .ImportStatic ;
71
73
import com .oracle .truffle .api .dsl .Specialization ;
72
74
import com .oracle .truffle .api .library .CachedLibrary ;
73
- import com .oracle .truffle .api .nodes .Node ;
75
+ import com .oracle .truffle .api .object .DynamicObjectLibrary ;
76
+ import com .oracle .truffle .api .object .HiddenKey ;
74
77
import com .oracle .truffle .api .profiles .BranchProfile ;
75
78
76
79
@ ImportStatic (PythonOptions .class )
77
80
public abstract class WriteAttributeToObjectNode extends ObjectAttributeNode {
78
81
79
82
public abstract boolean execute (Object primary , Object key , Object value );
80
83
84
+ public abstract boolean execute (Object primary , HiddenKey key , Object value );
85
+
81
86
public static WriteAttributeToObjectNode create () {
82
87
return WriteAttributeToObjectNotTypeNodeGen .create ();
83
88
}
@@ -97,61 +102,97 @@ protected static boolean isAttrWritable(PythonObject self, Object key) {
97
102
return (self .getShape ().getFlags () & PythonObject .HAS_SLOTS_BUT_NO_DICT_FLAG ) == 0 ;
98
103
}
99
104
100
- private static void handlePossiblePythonClass (HandlePythonClassProfiles profiles , PythonObject object , Object keyObj , Object value ) {
101
- if (PythonManagedClass .isInstance (object )) {
102
- profiles .isManagedClass .enter ();
103
- handlePythonClass (profiles , PythonManagedClass .cast (object ), keyObj , value );
105
+ private static String castKey (CastToJavaStringNode castNode , Object value ) {
106
+ try {
107
+ return castNode .execute (value );
108
+ } catch (CannotCastException ex ) {
109
+ throw CompilerDirectives .shouldNotReachHere (ex );
104
110
}
105
111
}
106
112
107
- private static void handlePythonClass (HandlePythonClassProfiles profiles , PythonManagedClass object , Object keyObj , Object value ) {
108
- String key = profiles .castKey (keyObj );
109
- if (key == null ) {
110
- return ;
111
- }
112
- object .invalidateFinalAttribute (key );
113
- // Note: we need to handle builtin classes here, because during initialization we are
114
- // setting attributes of some builtin types to Python functions (when given builtin method
115
- // is not intrinsified in Java)
116
- if (SpecialMethodSlot .canBeSpecial (key )) {
117
- profiles .isSpecialKey .enter ();
118
- SpecialMethodSlot slot = SpecialMethodSlot .findSpecialSlot (key );
119
- if (slot != null ) {
120
- SpecialMethodSlot .fixupSpecialMethodSlot (object , slot , value );
113
+ @ Specialization (guards = "isAttrWritable(object, key)" , limit = "getAttributeAccessInlineCacheMaxDepth()" )
114
+ static boolean writeHiddenKeyToDynamicStorage (PythonObject object , HiddenKey key , Object value ,
115
+ @ CachedLibrary ("object.getStorage()" ) DynamicObjectLibrary dylib ) {
116
+ // HiddenKeys are always written to the storage and do not have any other special handling
117
+ dylib .put (object .getStorage (), key , value );
118
+ return true ;
119
+ }
120
+
121
+ @ Specialization (guards = {"!isHiddenKey(key)" , "!lib.hasDict(object)" , "isAttrWritable(object, key)" , "!isManagedClass(object)" }, limit = "1" )
122
+ static boolean writeToDynamicStorageNoType (PythonObject object , Object key , Object value ,
123
+ @ Cached CastToJavaStringNode castToStrNode ,
124
+ @ CachedLibrary ("object" ) @ SuppressWarnings ("unused" ) PythonObjectLibrary lib ,
125
+ @ CachedLibrary (limit = "getAttributeAccessInlineCacheMaxDepth()" ) DynamicObjectLibrary dylib ) {
126
+ // Objects w/o dict that are not classes do not have any special handling
127
+ String strKey = castKey (castToStrNode , key );
128
+ dylib .put (object .getStorage (), strKey , value );
129
+ return true ;
130
+ }
131
+
132
+ @ Specialization (guards = {"!isHiddenKey(key)" , "!lib.hasDict(klass)" , "isAttrWritable(klass, key)" }, limit = "1" )
133
+ static boolean writeToDynamicStorageBuiltinType (PythonBuiltinClass klass , Object key , Object value ,
134
+ @ CachedLibrary ("klass" ) @ SuppressWarnings ("unused" ) PythonObjectLibrary lib ,
135
+ @ Cached CastToJavaStringNode castToStrNode ,
136
+ @ Cached BranchProfile callAttrUpdate ,
137
+ @ CachedLibrary (limit = "getAttributeAccessInlineCacheMaxDepth()" ) DynamicObjectLibrary dylib ) {
138
+ String strKey = castKey (castToStrNode , key );
139
+ try {
140
+ dylib .put (klass , strKey , value );
141
+ return true ;
142
+ } finally {
143
+ if (!klass .canSkipOnAttributeUpdate (strKey , value )) {
144
+ callAttrUpdate .enter ();
145
+ klass .onAttributeUpdate (strKey , value );
121
146
}
122
147
}
123
148
}
124
149
125
- // write to the DynamicObject
126
- @ Specialization (guards = {
127
- "isAttrWritable(object, key)" ,
128
- "isHiddenKey(key) || !lib.hasDict(object)"
129
- }, limit = "1" )
130
- static boolean writeToDynamicStorage (PythonObject object , Object key , Object value ,
131
- @ CachedLibrary ("object" ) @ SuppressWarnings ("unused" ) PythonObjectLibrary lib ,
132
- @ Cached WriteAttributeToDynamicObjectNode writeAttributeToDynamicObjectNode ,
133
- @ Exclusive @ Cached HandlePythonClassProfiles handlePythonClassProfiles ) {
150
+ static boolean [] createFlag () {
151
+ return new boolean [1 ];
152
+ }
153
+
154
+ @ Specialization (guards = {"!isHiddenKey(key)" , "!lib.hasDict(klass)" , "isAttrWritable(klass, key)" }, limit = "1" )
155
+ static boolean writeToDynamicStoragePythonClass (PythonClass klass , Object key , Object value ,
156
+ @ CachedLibrary ("klass" ) @ SuppressWarnings ("unused" ) PythonObjectLibrary lib ,
157
+ @ Cached CastToJavaStringNode castToStrNode ,
158
+ @ Cached BranchProfile callAttrUpdate ,
159
+ @ CachedLibrary (limit = "getAttributeAccessInlineCacheMaxDepth()" ) DynamicObjectLibrary dylib ) {
160
+ String strKey = castKey (castToStrNode , key );
134
161
try {
135
- return writeAttributeToDynamicObjectNode .execute (object .getStorage (), key , value );
162
+ dylib .put (klass , strKey , value );
163
+ return true ;
136
164
} finally {
137
- handlePossiblePythonClass (handlePythonClassProfiles , object , key , value );
165
+ if (!klass .canSkipOnAttributeUpdate (strKey , value )) {
166
+ callAttrUpdate .enter ();
167
+ klass .onAttributeUpdate (strKey , value );
168
+ }
138
169
}
139
170
}
140
171
141
172
// write to the dict
142
- @ Specialization (guards = {
143
- "!isHiddenKey(key)" ,
144
- "lib.hasDict(object)"
145
- }, limit = "1" )
146
- static boolean writeToDict (PythonObject object , Object key , Object value ,
173
+ @ Specialization (guards = {"!isHiddenKey(key)" , "lib.hasDict(object)" , "!isManagedClass(object)" }, limit = "1" )
174
+ static boolean writeToDictNoType (PythonObject object , Object key , Object value ,
147
175
@ CachedLibrary ("object" ) PythonObjectLibrary lib ,
148
176
@ Cached BranchProfile updateStorage ,
149
- @ CachedLibrary (limit = "1" ) HashingStorageLibrary hlib ,
150
- @ Exclusive @ Cached HandlePythonClassProfiles handlePythonClassProfiles ) {
177
+ @ CachedLibrary (limit = "1" ) HashingStorageLibrary hlib ) {
178
+ return writeToDict (lib .getDict (object ), key , value , updateStorage , hlib );
179
+ }
180
+
181
+ @ Specialization (guards = {"!isHiddenKey(key)" , "lib.hasDict(klass)" }, limit = "1" )
182
+ static boolean writeToDictBuiltinType (PythonManagedClass klass , Object key , Object value ,
183
+ @ Cached CastToJavaStringNode castToStrNode ,
184
+ @ Cached BranchProfile callAttrUpdate ,
185
+ @ CachedLibrary ("klass" ) PythonObjectLibrary lib ,
186
+ @ Cached BranchProfile updateStorage ,
187
+ @ CachedLibrary (limit = "1" ) HashingStorageLibrary hlib ) {
188
+ String strKey = castKey (castToStrNode , key );
151
189
try {
152
- return writeToDict (lib .getDict (object ), key , value , updateStorage , hlib );
190
+ return writeToDict (lib .getDict (klass ), strKey , value , updateStorage , hlib );
153
191
} finally {
154
- handlePossiblePythonClass (handlePythonClassProfiles , object , key , value );
192
+ if (!klass .canSkipOnAttributeUpdate (strKey , value )) {
193
+ callAttrUpdate .enter ();
194
+ klass .onAttributeUpdate (strKey , value );
195
+ }
155
196
}
156
197
}
157
198
@@ -277,46 +318,4 @@ private String castKey(Object keyObj) {
277
318
return castKeyNode .execute (keyObj );
278
319
}
279
320
}
280
-
281
- protected static final class HandlePythonClassProfiles extends Node {
282
- private static final HandlePythonClassProfiles UNCACHED = new HandlePythonClassProfiles (BranchProfile .getUncached (), BranchProfile .getUncached (), BranchProfile .getUncached (),
283
- CastToJavaStringNode .getUncached ());
284
- final BranchProfile isManagedClass ;
285
- final BranchProfile isUserClass ;
286
- final BranchProfile isSpecialKey ;
287
- @ Child CastToJavaStringNode castKeyNode ;
288
-
289
- public HandlePythonClassProfiles (BranchProfile isManagedClass , BranchProfile isUserClass , BranchProfile isSpecialKey , CastToJavaStringNode castKeyNode ) {
290
- this .isManagedClass = isManagedClass ;
291
- this .isUserClass = isUserClass ;
292
- this .isSpecialKey = isSpecialKey ;
293
- this .castKeyNode = castKeyNode ;
294
- }
295
-
296
- public static HandlePythonClassProfiles create () {
297
- return new HandlePythonClassProfiles (BranchProfile .create (), BranchProfile .create (), BranchProfile .create (), null );
298
- }
299
-
300
- public static HandlePythonClassProfiles getUncached () {
301
- return UNCACHED ;
302
- }
303
-
304
- String castKey (Object key ) {
305
- if (castKeyNode == null ) {
306
- // fast-path w/o node for two most common situations
307
- if (key instanceof String ) {
308
- return (String ) key ;
309
- } else if (isHiddenKey (key )) {
310
- return null ;
311
- }
312
- CompilerDirectives .transferToInterpreterAndInvalidate ();
313
- castKeyNode = insert (CastToJavaStringNode .create ());
314
- }
315
- try {
316
- return castKeyNode .execute (key );
317
- } catch (CannotCastException ex ) {
318
- return null ;
319
- }
320
- }
321
- }
322
321
}
0 commit comments