@@ -2198,8 +2198,8 @@ Object type(Object cls, Object obj, PNone bases, PNone dict, PKeyword[] kwds,
2198
2198
2199
2199
@ Specialization (guards = "isString(wName)" )
2200
2200
Object typeNew (VirtualFrame frame , Object cls , Object wName , PTuple bases , PDict namespaceOrig , PKeyword [] kwds ,
2201
- @ CachedLibrary (limit = "4 " ) PythonObjectLibrary lib ,
2202
- @ CachedLibrary (limit = "2 " ) HashingStorageLibrary nslib ,
2201
+ @ CachedLibrary (limit = "5 " ) PythonObjectLibrary lib ,
2202
+ @ CachedLibrary (limit = "3 " ) HashingStorageLibrary hashingStoragelib ,
2203
2203
@ Cached BranchProfile updatedStorage ,
2204
2204
@ Cached ("create(__NEW__)" ) LookupInheritedAttributeNode getNewFuncNode ,
2205
2205
@ Cached ("create(__INIT_SUBCLASS__)" ) GetAttributeNode getInitSubclassNode ,
@@ -2229,9 +2229,9 @@ Object typeNew(VirtualFrame frame, Object cls, Object wName, PTuple bases, PDict
2229
2229
2230
2230
try {
2231
2231
PDict namespace = (PDict ) copyDict .call (frame , namespaceOrig );
2232
- PythonClass newType = typeMetaclass (frame , name , bases , namespace , metaclass , nslib , getDictAttrNode , getWeakRefAttrNode , getBestBaseNode , getItemSize , writeItemSize );
2232
+ PythonClass newType = typeMetaclass (frame , name , bases , namespace , metaclass , lib , hashingStoragelib , getDictAttrNode , getWeakRefAttrNode , getBestBaseNode , getItemSize , writeItemSize );
2233
2233
2234
- for (DictEntry entry : nslib .entries (namespace .getDictStorage ())) {
2234
+ for (DictEntry entry : hashingStoragelib .entries (namespace .getDictStorage ())) {
2235
2235
Object setName = getSetNameNode .execute (entry .value );
2236
2236
if (setName != PNone .NO_VALUE ) {
2237
2237
try {
@@ -2253,32 +2253,32 @@ Object typeNew(VirtualFrame frame, Object cls, Object wName, PTuple bases, PDict
2253
2253
PFrame callerFrame = getReadCallerFrameNode ().executeWith (frame , 0 );
2254
2254
PythonObject globals = callerFrame .getGlobals ();
2255
2255
if (globals != null ) {
2256
- String moduleName = getModuleNameFromGlobals (globals , nslib );
2256
+ String moduleName = getModuleNameFromGlobals (globals , hashingStoragelib );
2257
2257
if (moduleName != null ) {
2258
2258
ensureWriteAttrNode ().execute (frame , newType , __MODULE__ , moduleName );
2259
2259
}
2260
2260
}
2261
2261
}
2262
2262
2263
2263
// delete __qualname__ from namespace
2264
- if (nslib .hasKey (namespace .getDictStorage (), __QUALNAME__ )) {
2265
- HashingStorage newStore = nslib .delItem (namespace .getDictStorage (), __QUALNAME__ );
2264
+ if (hashingStoragelib .hasKey (namespace .getDictStorage (), __QUALNAME__ )) {
2265
+ HashingStorage newStore = hashingStoragelib .delItem (namespace .getDictStorage (), __QUALNAME__ );
2266
2266
if (newStore != namespace .getDictStorage ()) {
2267
2267
updatedStorage .enter ();
2268
2268
namespace .setDictStorage (newStore );
2269
2269
}
2270
2270
}
2271
2271
2272
2272
// set __class__ cell contents
2273
- Object classcell = nslib .getItem (namespace .getDictStorage (), __CLASSCELL__ );
2273
+ Object classcell = hashingStoragelib .getItem (namespace .getDictStorage (), __CLASSCELL__ );
2274
2274
if (classcell != null ) {
2275
2275
if (classcell instanceof PCell ) {
2276
2276
((PCell ) classcell ).setRef (newType );
2277
2277
} else {
2278
2278
raise (TypeError , ErrorMessages .MUST_BE_A_CELL , "__classcell__" );
2279
2279
}
2280
- if (nslib .hasKey (namespace .getDictStorage (), __CLASSCELL__ )) {
2281
- HashingStorage newStore = nslib .delItem (namespace .getDictStorage (), __CLASSCELL__ );
2280
+ if (hashingStoragelib .hasKey (namespace .getDictStorage (), __CLASSCELL__ )) {
2281
+ HashingStorage newStore = hashingStoragelib .delItem (namespace .getDictStorage (), __CLASSCELL__ );
2282
2282
if (newStore != namespace .getDictStorage ()) {
2283
2283
updatedStorage .enter ();
2284
2284
namespace .setDictStorage (newStore );
@@ -2324,8 +2324,8 @@ private String getModuleNameFromGlobals(PythonObject globals, HashingStorageLibr
2324
2324
}
2325
2325
2326
2326
private PythonClass typeMetaclass (VirtualFrame frame , String name , PTuple bases , PDict namespace , Object metaclass ,
2327
- HashingStorageLibrary nslib , LookupAttributeInMRONode getDictAttrNode , LookupAttributeInMRONode getWeakRefAttrNode , GetBestBaseClassNode getBestBaseNode ,
2328
- GetItemsizeNode getItemSize , WriteAttributeToObjectNode writeItemSize ) {
2327
+ PythonObjectLibrary lib , HashingStorageLibrary hashingStorageLib , LookupAttributeInMRONode getDictAttrNode ,
2328
+ LookupAttributeInMRONode getWeakRefAttrNode , GetBestBaseClassNode getBestBaseNode , GetItemsizeNode getItemSize , WriteAttributeToObjectNode writeItemSize ) {
2329
2329
Object [] array = ensureGetObjectArrayNode ().execute (bases );
2330
2330
2331
2331
PythonAbstractClass [] basesArray ;
@@ -2359,7 +2359,7 @@ private PythonClass typeMetaclass(VirtualFrame frame, String name, PTuple bases,
2359
2359
// 2.) copy the dictionary slots
2360
2360
Object [] slots = new Object [1 ];
2361
2361
boolean [] qualnameSet = new boolean []{false };
2362
- copyDictSlots (pythonClass , namespace , nslib , slots , qualnameSet );
2362
+ copyDictSlots (pythonClass , namespace , lib , hashingStorageLib , slots , qualnameSet );
2363
2363
if (!qualnameSet [0 ]) {
2364
2364
pythonClass .setQualName (name );
2365
2365
}
@@ -2369,9 +2369,9 @@ private PythonClass typeMetaclass(VirtualFrame frame, String name, PTuple bases,
2369
2369
2370
2370
// CPython masks the __hash__ method with None when __eq__ is overriden, but __hash__ is
2371
2371
// not
2372
- Object hashMethod = nslib .getItem (namespace .getDictStorage (), __HASH__ );
2372
+ Object hashMethod = hashingStorageLib .getItem (namespace .getDictStorage (), __HASH__ );
2373
2373
if (hashMethod == null ) {
2374
- Object eqMethod = nslib .getItem (namespace .getDictStorage (), __EQ__ );
2374
+ Object eqMethod = hashingStorageLib .getItem (namespace .getDictStorage (), __EQ__ );
2375
2375
if (eqMethod != null ) {
2376
2376
pythonClass .setAttribute (__HASH__ , PNone .NONE );
2377
2377
}
@@ -2455,7 +2455,7 @@ private PythonClass typeMetaclass(VirtualFrame frame, String name, PTuple bases,
2455
2455
}
2456
2456
2457
2457
// checks for some name errors too
2458
- PTuple newSlots = copySlots (name , slotsStorage , slotlen , addDict , addWeakRef , namespace , nslib );
2458
+ PTuple newSlots = copySlots (name , slotsStorage , slotlen , addDict , addWeakRef , namespace , hashingStorageLib );
2459
2459
2460
2460
// add native slot descriptors
2461
2461
if (pythonClass .needsNativeAllocation ()) {
@@ -2515,10 +2515,11 @@ private static boolean hasPythonClassBases(PythonAbstractClass[] basesArray) {
2515
2515
return false ;
2516
2516
}
2517
2517
2518
- private void copyDictSlots (PythonClass pythonClass , PDict namespace , HashingStorageLibrary nslib , Object [] slots , boolean [] qualnameSet ) {
2518
+ private void copyDictSlots (PythonClass pythonClass , PDict namespace , PythonObjectLibrary lib , HashingStorageLibrary hashingStorageLib , Object [] slots , boolean [] qualnameSet ) {
2519
2519
// copy the dictionary slots over, as CPython does through PyDict_Copy
2520
2520
// Also check for a __slots__ sequence variable in dict
2521
- for (DictEntry entry : nslib .entries (namespace .getDictStorage ())) {
2521
+ PDict typeDict = null ;
2522
+ for (DictEntry entry : hashingStorageLib .entries (namespace .getDictStorage ())) {
2522
2523
Object key = entry .getKey ();
2523
2524
Object value = entry .getValue ();
2524
2525
if (__SLOTS__ .equals (key )) {
@@ -2565,8 +2566,25 @@ private void copyDictSlots(PythonClass pythonClass, PDict namespace, HashingStor
2565
2566
}
2566
2567
} else if (SpecialAttributeNames .__CLASSCELL__ .equals (key )) {
2567
2568
// don't populate this attribute
2568
- } else {
2569
+ } else if ( key instanceof String && typeDict == null ) {
2569
2570
pythonClass .setAttribute (key , value );
2571
+ } else {
2572
+ // DynamicObjectStorage ignores non-string keys
2573
+ typeDict = lib .getDict (pythonClass );
2574
+ if (typeDict == null ) {
2575
+ // 1.) create DynamicObjectStorage based dict from pythonClass
2576
+ typeDict = PythonObjectFactory .getUncached ().createDictFixedStorage (pythonClass );
2577
+ try {
2578
+ lib .setDict (pythonClass , typeDict );
2579
+ } catch (UnsupportedMessageException ex ) {
2580
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
2581
+ throw new IllegalStateException ("can't set dict into " + pythonClass , ex );
2582
+ }
2583
+ }
2584
+ // 2.) writing a non string key converts DynamicObjectStorage to
2585
+ // EconomicMapStorage
2586
+ HashingStorage updatedStore = hashingStorageLib .setItem (typeDict .getDictStorage (), key , value );
2587
+ typeDict .setDictStorage (updatedStore );
2570
2588
}
2571
2589
}
2572
2590
}
0 commit comments