28
28
29
29
import static com .oracle .graal .python .nodes .SpecialAttributeNames .__CLASS__ ;
30
30
import static com .oracle .graal .python .nodes .SpecialAttributeNames .__DICT__ ;
31
- import static com .oracle .graal .python .nodes .SpecialAttributeNames .__SLOTS__ ;
32
31
import static com .oracle .graal .python .nodes .SpecialMethodNames .RICHCMP ;
33
32
import static com .oracle .graal .python .nodes .SpecialMethodNames .__DELATTR__ ;
34
33
import static com .oracle .graal .python .nodes .SpecialMethodNames .__DELETE__ ;
60
59
import com .oracle .graal .python .builtins .objects .cext .CExtNodes ;
61
60
import com .oracle .graal .python .builtins .objects .cext .PythonAbstractNativeObject ;
62
61
import com .oracle .graal .python .builtins .objects .cext .PythonNativeClass ;
63
- import com .oracle .graal .python .builtins .objects .common .HashingCollectionNodes .GetDictStorageNode ;
64
- import com .oracle .graal .python .builtins .objects .common .HashingStorage ;
65
- import com .oracle .graal .python .builtins .objects .common .HashingStorageLibrary ;
66
62
import com .oracle .graal .python .builtins .objects .common .PHashingCollection ;
67
- import com .oracle .graal .python .builtins .objects .common .SequenceNodes .GetObjectArrayNode ;
68
- import com .oracle .graal .python .builtins .objects .common .SequenceNodesFactory .GetObjectArrayNodeGen ;
69
63
import com .oracle .graal .python .builtins .objects .dict .PDict ;
70
64
import com .oracle .graal .python .builtins .objects .function .PBuiltinFunction ;
71
65
import com .oracle .graal .python .builtins .objects .function .PKeyword ;
72
66
import com .oracle .graal .python .builtins .objects .object .ObjectBuiltinsFactory .GetAttributeNodeFactory ;
73
67
import com .oracle .graal .python .builtins .objects .str .StringNodes ;
74
68
import com .oracle .graal .python .builtins .objects .type .PythonAbstractClass ;
75
69
import com .oracle .graal .python .builtins .objects .type .PythonBuiltinClass ;
76
- import com .oracle .graal .python .builtins .objects .type .TypeNodes ;
77
- import com .oracle .graal .python .builtins .objects .type .TypeNodes .GetBaseClassNode ;
78
- import com .oracle .graal .python .builtins .objects .type .TypeNodesFactory .GetBaseClassNodeGen ;
70
+ import com .oracle .graal .python .builtins .objects .type .TypeNodes .CheckCompatibleForAssigmentNode ;
71
+ import com .oracle .graal .python .builtins .objects .type .TypeNodesFactory .CheckCompatibleForAssigmentNodeGen ;
79
72
import com .oracle .graal .python .nodes .BuiltinNames ;
80
73
import com .oracle .graal .python .nodes .ErrorMessages ;
81
74
import com .oracle .graal .python .nodes .PGuards ;
82
75
import com .oracle .graal .python .nodes .SpecialAttributeNames ;
83
- import static com .oracle .graal .python .nodes .SpecialMethodNames .__NEW__ ;
84
76
import com .oracle .graal .python .nodes .attributes .GetAttributeNode .GetFixedAttributeNode ;
85
77
import com .oracle .graal .python .nodes .attributes .LookupAttributeInMRONode ;
86
78
import com .oracle .graal .python .nodes .attributes .ReadAttributeFromObjectNode ;
@@ -128,16 +120,7 @@ protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFa
128
120
@ GenerateNodeFactory
129
121
abstract static class ClassNode extends PythonBinaryBuiltinNode {
130
122
131
- @ Child private LookupAttributeInMRONode lookupSlotsNode ;
132
- @ Child private TypeNodes .GetNameNode getTypeNameNode ;
133
-
134
- @ Child private LookupAttributeInMRONode lookupNewNode ;
135
- @ Child private GetBaseClassNode getBaseClassNode ;
136
- @ Child private GetDictStorageNode getDictStorageNode ;
137
- @ Child private LookupAndCallBinaryNode getDictNode ;
138
- @ Child private HashingStorageLibrary hashingStorageLib ;
139
- @ Child private PythonObjectLibrary objectLibrary ;
140
- @ Child private GetObjectArrayNode getObjectArrayNode ;
123
+ @ Child private CheckCompatibleForAssigmentNode compatibleForAssigmentNode ;
141
124
142
125
private static final String ERROR_MESSAGE = "__class__ assignment only supported for heap types or ModuleType subclasses" ;
143
126
@@ -161,8 +144,7 @@ Object setClass(@SuppressWarnings("unused") Object self, @SuppressWarnings("unus
161
144
PNone setClass (VirtualFrame frame , PythonObject self , PythonAbstractClass value ,
162
145
@ CachedLibrary (limit = "2" ) PythonObjectLibrary lib1 ,
163
146
@ Cached ("create()" ) BranchProfile errorValueBranch ,
164
- @ Cached ("create()" ) BranchProfile errorSelfBranch ,
165
- @ Cached ("create()" ) BranchProfile errorSlotsBranch ) {
147
+ @ Cached ("create()" ) BranchProfile errorSelfBranch ) {
166
148
if (value instanceof PythonBuiltinClass || PGuards .isNativeClass (value )) {
167
149
errorValueBranch .enter ();
168
150
throw raise (TypeError , ERROR_MESSAGE );
@@ -173,184 +155,12 @@ PNone setClass(VirtualFrame frame, PythonObject self, PythonAbstractClass value,
173
155
throw raise (TypeError , ERROR_MESSAGE );
174
156
}
175
157
176
- if (!compatibleForAssignment (frame , lazyClass , value )) {
177
- errorSlotsBranch .enter ();
178
- throw raise (TypeError , ErrorMessages .CLASS_ASIGMENT_S_LAYOUT_DIFFERS_FROM_S , getTypeName (value ), getTypeName (lazyClass ));
179
- }
158
+ getCheckCompatibleForAssigmentNode ().execute (frame , lazyClass , value );
159
+
180
160
lib1 .setLazyPythonClass (self , value );
181
161
return PNone .NONE ;
182
162
}
183
163
184
- /**
185
- * Attempt to get as close as possible to typeobject.compatible_for_assignment()
186
- */
187
- private boolean compatibleForAssignment (VirtualFrame frame , Object self , PythonAbstractClass other ) {
188
- Object newBase = other ;
189
- Object oldBase = self ;
190
-
191
- Object newParent = getBaseClassNode ().execute (frame , newBase );
192
- while (newParent != null && compatibleWithBase (frame , newBase , newParent )) {
193
- newBase = newParent ;
194
- newParent = getBaseClassNode ().execute (frame , newBase );
195
- }
196
-
197
- Object oldParent = getBaseClassNode ().execute (frame , oldBase );
198
- while (oldParent != null && compatibleWithBase (frame , oldBase , oldParent )) {
199
- oldBase = oldParent ;
200
- oldParent = getBaseClassNode ().execute (frame , oldBase );
201
- }
202
-
203
- if (newBase != oldBase && (newParent != oldParent || !compareSlotsFromDict (frame , newBase , oldBase ))) {
204
- return false ;
205
- }
206
- return true ;
207
- }
208
-
209
- /**
210
- * Attempt to get as close as possible to typeobject.compatible_with_tp_base().
211
- */
212
- private boolean compatibleWithBase (VirtualFrame frame , Object child , Object parent ) {
213
- if (PGuards .isNativeClass (child ) && PGuards .isNativeClass (parent )) {
214
- // TODO: call C function 'compatible_for_assignment'
215
- return false ;
216
- }
217
-
218
- // (child->tp_flags & Py_TPFLAGS_HAVE_GC) == (parent->tp_flags & Py_TPFLAGS_HAVE_GC)
219
- if (PGuards .isNativeClass (child ) != PGuards .isNativeClass (parent )) {
220
- return false ;
221
- }
222
-
223
- // instead of child->tp_dictoffset == parent->tp_dictoffset
224
- if (hasDict (child ) != hasDict (parent )) {
225
- return false ;
226
- }
227
-
228
- // instead of child->tp_basicsize == parent->tp_basicsize
229
- // the assumption is made that a different "allocator" => different basic size, hm
230
- Object childNewMethod = getLookupNewNode ().execute (child );
231
- Object parentNewMethod = getLookupNewNode ().execute (parent );
232
- if (childNewMethod != parentNewMethod ) {
233
- return false ;
234
- }
235
-
236
- // instead of child->tp_itemsize == parent->tp_itemsize
237
- Object childSlots = getSlotsFromDict (frame , child );
238
- Object parentSlots = getSlotsFromDict (frame , parent );
239
- if (childSlots == null && parentSlots == null ) {
240
- return true ;
241
- }
242
- if (childSlots == null && parentSlots != null || childSlots != null && parentSlots == null ) {
243
- return false ;
244
- }
245
- if (!compareSlots (parent , child , parentSlots , childSlots )) {
246
- return false ;
247
- }
248
-
249
- return true ;
250
- }
251
-
252
- private boolean compareSlotsFromDict (VirtualFrame frame , Object a , Object b ) {
253
- Object aSlots = getSlotsFromDict (frame , b );
254
- Object bSlots = getSlotsFromDict (frame , a );
255
- return compareSlots (a , b , aSlots , bSlots );
256
- }
257
-
258
- private boolean compareSlots (Object aType , Object bType , Object aSlotsArg , Object bSlotsArg ) {
259
- Object aSlots = aSlotsArg ;
260
- Object bSlots = bSlotsArg ;
261
-
262
- if (aSlots == null && bSlots == null ) {
263
- return true ;
264
- }
265
-
266
- if (aSlots != null && bSlots != null ) {
267
- return TypeNodes .compareSortedSlots (aSlots , bSlots , getObjectArrayNode ());
268
- }
269
-
270
- aSlots = getLookupSlots ().execute (aType );
271
- bSlots = getLookupSlots ().execute (bType );
272
- int aSize = aSlots != PNone .NO_VALUE ? getObjectLibrary ().length (aSlots ) : 0 ;
273
- int bSize = bSlots != PNone .NO_VALUE ? getObjectLibrary ().length (bSlots ) : 0 ;
274
- return aSize == bSize ;
275
- }
276
-
277
- private Object getSlotsFromDict (VirtualFrame frame , Object type ) {
278
- Object dict = getDictNode ().executeObject (frame , type , __DICT__ );
279
- if (dict != PNone .NO_VALUE ) {
280
- HashingStorage storage = getDictStorageNode ().execute ((PHashingCollection ) dict );
281
- return getHashingStorageLibrary ().getItem (storage , __SLOTS__ );
282
- }
283
- return null ;
284
- }
285
-
286
- private boolean hasDict (Object obj ) {
287
- return getObjectLibrary ().lookupAttribute (obj , __DICT__ ) != PNone .NO_VALUE ;
288
- }
289
-
290
- private GetObjectArrayNode getObjectArrayNode () {
291
- if (getObjectArrayNode == null ) {
292
- CompilerDirectives .transferToInterpreterAndInvalidate ();
293
- getObjectArrayNode = insert (GetObjectArrayNodeGen .create ());
294
- }
295
- return getObjectArrayNode ;
296
- }
297
-
298
- private PythonObjectLibrary getObjectLibrary () {
299
- if (objectLibrary == null ) {
300
- CompilerDirectives .transferToInterpreterAndInvalidate ();
301
- objectLibrary = insert (PythonObjectLibrary .getFactory ().createDispatched (4 ));
302
- }
303
- return objectLibrary ;
304
- }
305
-
306
- private LookupAndCallBinaryNode getDictNode () {
307
- if (getDictNode == null ) {
308
- CompilerDirectives .transferToInterpreterAndInvalidate ();
309
- getDictNode = insert (LookupAndCallBinaryNode .create (__GETATTRIBUTE__ ));
310
- }
311
- return getDictNode ;
312
- }
313
-
314
- private GetDictStorageNode getDictStorageNode () {
315
- if (getDictStorageNode == null ) {
316
- CompilerDirectives .transferToInterpreterAndInvalidate ();
317
- getDictStorageNode = insert (GetDictStorageNode .create ());
318
- }
319
- return getDictStorageNode ;
320
- }
321
-
322
- private HashingStorageLibrary getHashingStorageLibrary () {
323
- if (hashingStorageLib == null ) {
324
- CompilerDirectives .transferToInterpreterAndInvalidate ();
325
- hashingStorageLib = insert (HashingStorageLibrary .getFactory ().createDispatched (4 ));
326
- }
327
- return hashingStorageLib ;
328
- }
329
-
330
- private LookupAttributeInMRONode getLookupSlots () {
331
- if (lookupSlotsNode == null ) {
332
- CompilerDirectives .transferToInterpreterAndInvalidate ();
333
- lookupSlotsNode = insert (LookupAttributeInMRONode .create (__SLOTS__ ));
334
- }
335
- return lookupSlotsNode ;
336
- }
337
-
338
- private GetBaseClassNode getBaseClassNode () {
339
- if (getBaseClassNode == null ) {
340
- CompilerDirectives .transferToInterpreterAndInvalidate ();
341
- getBaseClassNode = insert (GetBaseClassNodeGen .create ());
342
- }
343
- return getBaseClassNode ;
344
- }
345
-
346
- private LookupAttributeInMRONode getLookupNewNode () {
347
- if (lookupNewNode == null ) {
348
- CompilerDirectives .transferToInterpreterAndInvalidate ();
349
- lookupNewNode = insert (LookupAttributeInMRONode .createForLookupOfUnmanagedClasses (__NEW__ ));
350
- }
351
- return lookupNewNode ;
352
- }
353
-
354
164
@ Specialization (guards = "!isPythonObject(self)" )
355
165
Object getClass (@ SuppressWarnings ("unused" ) Object self , @ SuppressWarnings ("unused" ) PythonAbstractClass value ) {
356
166
throw raise (TypeError , ERROR_MESSAGE );
@@ -361,12 +171,12 @@ Object getClass(@SuppressWarnings("unused") Object self, Object value) {
361
171
throw raise (TypeError , ErrorMessages .CLASS_MUST_BE_SET_TO_CLASS , value );
362
172
}
363
173
364
- private String getTypeName ( Object clazz ) {
365
- if (getTypeNameNode == null ) {
174
+ private CheckCompatibleForAssigmentNode getCheckCompatibleForAssigmentNode ( ) {
175
+ if (compatibleForAssigmentNode == null ) {
366
176
CompilerDirectives .transferToInterpreterAndInvalidate ();
367
- getTypeNameNode = insert (TypeNodes . GetNameNode .create ());
177
+ compatibleForAssigmentNode = insert (CheckCompatibleForAssigmentNodeGen .create ());
368
178
}
369
- return getTypeNameNode . execute ( clazz ) ;
179
+ return compatibleForAssigmentNode ;
370
180
}
371
181
}
372
182
0 commit comments