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