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 . HiddenKey ;
74
76
import com .oracle .truffle .api .profiles .BranchProfile ;
75
77
76
78
@ ImportStatic (PythonOptions .class )
77
79
public abstract class WriteAttributeToObjectNode extends ObjectAttributeNode {
78
80
79
81
public abstract boolean execute (Object primary , Object key , Object value );
80
82
83
+ public abstract boolean execute (Object primary , HiddenKey key , Object value );
84
+
81
85
public static WriteAttributeToObjectNode create () {
82
86
return WriteAttributeToObjectNotTypeNodeGen .create ();
83
87
}
@@ -97,61 +101,92 @@ protected static boolean isAttrWritable(PythonObject self, Object key) {
97
101
return (self .getShape ().getFlags () & PythonObject .HAS_SLOTS_BUT_NO_DICT_FLAG ) == 0 ;
98
102
}
99
103
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 );
104
- }
105
- }
106
-
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)
104
+ private static void fixupSpecialMethodSlots (BranchProfile isSpecialKey , PythonManagedClass object , String key , Object value ) {
116
105
if (SpecialMethodSlot .canBeSpecial (key )) {
117
- profiles . isSpecialKey .enter ();
106
+ isSpecialKey .enter ();
118
107
SpecialMethodSlot slot = SpecialMethodSlot .findSpecialSlot (key );
119
108
if (slot != null ) {
120
109
SpecialMethodSlot .fixupSpecialMethodSlot (object , slot , value );
121
110
}
122
111
}
123
112
}
124
113
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 ,
114
+ private static String castKey (CastToJavaStringNode castNode , Object value ) {
115
+ try {
116
+ return castNode .execute (value );
117
+ } catch (CannotCastException ex ) {
118
+ throw CompilerDirectives .shouldNotReachHere (ex );
119
+ }
120
+ }
121
+
122
+ @ Specialization (guards = "isAttrWritable(object, key)" )
123
+ static boolean writeHiddenKeyToDynamicStorage (PythonObject object , HiddenKey key , Object value ,
124
+ @ Cached WriteAttributeToDynamicObjectNode writeAttributeToDynamicObjectNode ) {
125
+ // HiddenKeys are always written to the storage and do not have any other special handling
126
+ return writeAttributeToDynamicObjectNode .execute (object .getStorage (), key , value );
127
+ }
128
+
129
+ @ Specialization (guards = {"!isHiddenKey(key)" , "!lib.hasDict(object)" , "isAttrWritable(object, key)" , "!isManagedClass(object)" }, limit = "1" )
130
+ static boolean writeToDynamicStorageNoType (PythonObject object , Object key , Object value ,
131
131
@ CachedLibrary ("object" ) @ SuppressWarnings ("unused" ) PythonObjectLibrary lib ,
132
- @ Cached WriteAttributeToDynamicObjectNode writeAttributeToDynamicObjectNode ,
133
- @ Exclusive @ Cached HandlePythonClassProfiles handlePythonClassProfiles ) {
132
+ @ Cached WriteAttributeToDynamicObjectNode writeAttributeToDynamicObjectNode ) {
133
+ // Objects w/o dict that are not classes do not have any special handling
134
+ return writeAttributeToDynamicObjectNode .execute (object .getStorage (), key , value );
135
+ }
136
+
137
+ @ Specialization (guards = {"!isHiddenKey(key)" , "!lib.hasDict(klass)" , "isAttrWritable(klass, key)" }, limit = "1" )
138
+ static boolean writeToDynamicStorageBuiltinType (PythonBuiltinClass klass , Object key , Object value ,
139
+ @ CachedLibrary ("klass" ) @ SuppressWarnings ("unused" ) PythonObjectLibrary lib ,
140
+ @ Cached CastToJavaStringNode castToStrNode ,
141
+ @ Cached BranchProfile isSpecialKey ,
142
+ @ Cached BranchProfile changedShape ,
143
+ @ Cached WriteAttributeToDynamicObjectNode writeAttributeToDynamicObjectNode ) {
144
+ String strKey = castKey (castToStrNode , key );
134
145
try {
135
- return writeAttributeToDynamicObjectNode .execute (object . getStorage (), key , value );
146
+ return writeAttributeToDynamicObjectNode .execute (klass , strKey , value );
136
147
} finally {
137
- handlePossiblePythonClass (handlePythonClassProfiles , object , key , value );
148
+ klass .invalidateFinalAttribute (strKey );
149
+ fixupSpecialMethodSlots (isSpecialKey , klass , strKey , value );
150
+ }
151
+ }
152
+
153
+ @ Specialization (guards = {"!isHiddenKey(key)" , "!lib.hasDict(klass)" , "isAttrWritable(klass, key)" }, limit = "1" )
154
+ static boolean writeToDynamicStoragePythonClass (PythonClass klass , Object key , Object value ,
155
+ @ CachedLibrary ("klass" ) @ SuppressWarnings ("unused" ) PythonObjectLibrary lib ,
156
+ @ Cached CastToJavaStringNode castToStrNode ,
157
+ @ Cached BranchProfile isSpecialKey ,
158
+ @ Cached WriteAttributeToDynamicObjectNode writeAttributeToDynamicObjectNode ) {
159
+ String strKey = castKey (castToStrNode , key );
160
+ try {
161
+ return writeAttributeToDynamicObjectNode .execute (klass , strKey , value );
162
+ } finally {
163
+ klass .invalidateFinalAttribute (strKey );
164
+ fixupSpecialMethodSlots (isSpecialKey , klass , strKey , value );
138
165
}
139
166
}
140
167
141
168
// 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 ,
169
+ @ Specialization (guards = {"!isHiddenKey(key)" , "lib.hasDict(object)" , "!isManagedClass(object)" }, limit = "1" )
170
+ static boolean writeToDictNoType (PythonObject object , Object key , Object value ,
147
171
@ CachedLibrary ("object" ) PythonObjectLibrary lib ,
148
172
@ Cached BranchProfile updateStorage ,
149
- @ CachedLibrary (limit = "1" ) HashingStorageLibrary hlib ,
150
- @ Exclusive @ Cached HandlePythonClassProfiles handlePythonClassProfiles ) {
173
+ @ CachedLibrary (limit = "1" ) HashingStorageLibrary hlib ) {
174
+ return writeToDict (lib .getDict (object ), key , value , updateStorage , hlib );
175
+ }
176
+
177
+ @ Specialization (guards = {"!isHiddenKey(key)" , "lib.hasDict(klass)" }, limit = "1" )
178
+ static boolean writeToDictBuiltinType (PythonManagedClass klass , Object key , Object value ,
179
+ @ Cached CastToJavaStringNode castToStrNode ,
180
+ @ Cached BranchProfile isSpecialKey ,
181
+ @ CachedLibrary ("klass" ) PythonObjectLibrary lib ,
182
+ @ Cached BranchProfile updateStorage ,
183
+ @ CachedLibrary (limit = "1" ) HashingStorageLibrary hlib ) {
184
+ String strKey = castKey (castToStrNode , key );
151
185
try {
152
- return writeToDict (lib .getDict (object ), key , value , updateStorage , hlib );
186
+ return writeToDict (lib .getDict (klass ), strKey , value , updateStorage , hlib );
153
187
} finally {
154
- handlePossiblePythonClass (handlePythonClassProfiles , object , key , value );
188
+ klass .invalidateFinalAttribute (strKey );
189
+ fixupSpecialMethodSlots (isSpecialKey , klass , strKey , value );
155
190
}
156
191
}
157
192
@@ -277,46 +312,4 @@ private String castKey(Object keyObj) {
277
312
return castKeyNode .execute (keyObj );
278
313
}
279
314
}
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
315
}
0 commit comments