138
138
import com .oracle .graal .python .builtins .objects .function .PBuiltinFunction ;
139
139
import com .oracle .graal .python .builtins .objects .function .PFunction ;
140
140
import com .oracle .graal .python .builtins .objects .function .PKeyword ;
141
+ import com .oracle .graal .python .builtins .objects .getsetdescriptor .GetSetDescriptor ;
141
142
import com .oracle .graal .python .builtins .objects .getsetdescriptor .HiddenKeyDescriptor ;
142
143
import com .oracle .graal .python .builtins .objects .getsetdescriptor .HiddenPythonKey ;
143
144
import com .oracle .graal .python .builtins .objects .ints .PInt ;
149
150
import com .oracle .graal .python .builtins .objects .module .PythonModule ;
150
151
import com .oracle .graal .python .builtins .objects .object .ObjectBuiltins ;
151
152
import com .oracle .graal .python .builtins .objects .object .ObjectBuiltinsFactory ;
153
+ import com .oracle .graal .python .builtins .objects .object .ObjectBuiltinsFactory .DictNodeGen ;
152
154
import com .oracle .graal .python .builtins .objects .object .PythonObject ;
153
155
import com .oracle .graal .python .builtins .objects .object .PythonObjectLibrary ;
154
156
import com .oracle .graal .python .builtins .objects .range .PBigRange ;
191
193
import com .oracle .graal .python .nodes .classes .IsSubtypeNode ;
192
194
import com .oracle .graal .python .nodes .expression .CastToListExpressionNode .CastToListNode ;
193
195
import com .oracle .graal .python .nodes .frame .ReadCallerFrameNode ;
196
+ import com .oracle .graal .python .nodes .function .BuiltinFunctionRootNode ;
197
+ import com .oracle .graal .python .nodes .function .BuiltinFunctionRootNode .StandaloneBuiltinFactory ;
194
198
import com .oracle .graal .python .nodes .function .PythonBuiltinBaseNode ;
195
199
import com .oracle .graal .python .nodes .function .PythonBuiltinNode ;
196
200
import com .oracle .graal .python .nodes .function .builtins .PythonBinaryBuiltinNode ;
220
224
import com .oracle .truffle .api .CompilerDirectives ;
221
225
import com .oracle .truffle .api .CompilerDirectives .CompilationFinal ;
222
226
import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
227
+ import com .oracle .truffle .api .RootCallTarget ;
223
228
import com .oracle .truffle .api .Truffle ;
224
229
import com .oracle .truffle .api .dsl .Cached ;
225
230
import com .oracle .truffle .api .dsl .Cached .Shared ;
@@ -2080,7 +2085,8 @@ Object typeNew(VirtualFrame frame, Object cls, Object wName, PTuple bases, PDict
2080
2085
@ Cached CallNode callSetNameNode ,
2081
2086
@ Cached CallNode callInitSubclassNode ,
2082
2087
@ Cached CallNode callNewFuncNode ,
2083
- @ Cached GetBestBaseClassNode getBestBaseNode ) {
2088
+ @ Cached GetBestBaseClassNode getBestBaseNode ,
2089
+ @ Cached ("create(__DICT__)" ) LookupAttributeInMRONode getDictAttrNode ) {
2084
2090
// Determine the proper metatype to deal with this
2085
2091
String name = castStr .execute (wName );
2086
2092
Object metaclass = calculate_metaclass (frame , cls , bases , lib );
@@ -2095,7 +2101,7 @@ Object typeNew(VirtualFrame frame, Object cls, Object wName, PTuple bases, PDict
2095
2101
}
2096
2102
2097
2103
try {
2098
- PythonClass newType = typeMetaclass (frame , name , bases , namespace , metaclass , nslib , getBestBaseNode );
2104
+ PythonClass newType = typeMetaclass (frame , name , bases , namespace , metaclass , nslib , getDictAttrNode , getBestBaseNode );
2099
2105
2100
2106
for (DictEntry entry : nslib .entries (namespace .getDictStorage ())) {
2101
2107
Object setName = getSetNameNode .execute (entry .value );
@@ -2180,7 +2186,7 @@ private String getModuleNameFromGlobals(PythonObject globals, HashingStorageLibr
2180
2186
}
2181
2187
}
2182
2188
2183
- private PythonClass typeMetaclass (VirtualFrame frame , String name , PTuple bases , PDict namespace , Object metaclass , HashingStorageLibrary nslib ,
2189
+ private PythonClass typeMetaclass (VirtualFrame frame , String name , PTuple bases , PDict namespace , Object metaclass , HashingStorageLibrary nslib , LookupAttributeInMRONode getDictAttrNode ,
2184
2190
GetBestBaseClassNode getBestBaseNode ) {
2185
2191
Object [] array = ensureGetObjectArrayNode ().execute (bases );
2186
2192
@@ -2237,6 +2243,7 @@ private PythonClass typeMetaclass(VirtualFrame frame, String name, PTuple bases,
2237
2243
if (slots [0 ] == null ) {
2238
2244
// takes care of checking if we may_add_dict and adds it if needed
2239
2245
addDictIfNative (frame , pythonClass );
2246
+ addDictDescrAttribute (basesArray , getDictAttrNode , pythonClass );
2240
2247
// TODO: tfel - also deal with weaklistoffset
2241
2248
} else {
2242
2249
// have slots
@@ -2276,6 +2283,7 @@ private PythonClass typeMetaclass(VirtualFrame frame, String name, PTuple bases,
2276
2283
throw raise (TypeError , ErrorMessages .SLOT_DISALLOWED_WE_GOT_ONE , "__dict__" );
2277
2284
}
2278
2285
addDict = true ;
2286
+ addDictDescrAttribute (basesArray , getDictAttrNode , pythonClass );
2279
2287
} else {
2280
2288
// TODO: check for __weakref__
2281
2289
// TODO avoid if native slots are inherited
@@ -2309,6 +2317,41 @@ private PythonClass typeMetaclass(VirtualFrame frame, String name, PTuple bases,
2309
2317
return pythonClass ;
2310
2318
}
2311
2319
2320
+ private void addDictDescrAttribute (PythonAbstractClass [] basesArray , LookupAttributeInMRONode getDictAttrNode , PythonClass pythonClass ) {
2321
+ if ((!hasPythonClassBases (basesArray ) && getDictAttrNode .execute (pythonClass ) == PNone .NO_VALUE ) || basesHaveSlots (basesArray )) {
2322
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
2323
+ Builtin dictBuiltin = ObjectBuiltins .DictNode .class .getAnnotation (Builtin .class );
2324
+ BuiltinFunctionRootNode rootNode = new BuiltinFunctionRootNode (getCore ().getLanguage (), dictBuiltin , new StandaloneBuiltinFactory <PythonBinaryBuiltinNode >(DictNodeGen .create ()), true );
2325
+ RootCallTarget callTarget = PythonUtils .getOrCreateCallTarget (rootNode );
2326
+ PBuiltinFunction function = getCore ().factory ().createBuiltinFunction (__DICT__ , pythonClass , 1 , callTarget );
2327
+ GetSetDescriptor desc = factory ().createGetSetDescriptor (function , function , __DICT__ , pythonClass , true );
2328
+ pythonClass .setAttribute (__DICT__ , desc );
2329
+ }
2330
+ }
2331
+
2332
+ private static boolean basesHaveSlots (PythonAbstractClass [] basesArray ) {
2333
+ // this is merely based on empirical observation
2334
+ // see also test_type.py#test_dict()
2335
+ for (PythonAbstractClass c : basesArray ) {
2336
+ // TODO: what about native?
2337
+ if (c instanceof PythonClass ) {
2338
+ if (((PythonClass ) c ).getAttribute (__SLOTS__ ) != PNone .NO_VALUE ) {
2339
+ return true ;
2340
+ }
2341
+ }
2342
+ }
2343
+ return false ;
2344
+ }
2345
+
2346
+ private static boolean hasPythonClassBases (PythonAbstractClass [] basesArray ) {
2347
+ for (PythonAbstractClass c : basesArray ) {
2348
+ if (c instanceof PythonClass ) {
2349
+ return true ;
2350
+ }
2351
+ }
2352
+ return false ;
2353
+ }
2354
+
2312
2355
private void copyDictSlots (PythonClass pythonClass , PDict namespace , HashingStorageLibrary nslib , Object [] slots , boolean [] qualnameSet ) {
2313
2356
// copy the dictionary slots over, as CPython does through PyDict_Copy
2314
2357
// Also check for a __slots__ sequence variable in dict
0 commit comments