|
40 | 40 | */
|
41 | 41 | package com.oracle.graal.python.nodes.object;
|
42 | 42 |
|
| 43 | +import com.oracle.graal.python.builtins.objects.common.DynamicObjectStorage; |
| 44 | +import com.oracle.graal.python.builtins.objects.common.HashingStorage; |
| 45 | +import com.oracle.graal.python.builtins.objects.common.HashingStorageLibrary; |
| 46 | +import com.oracle.graal.python.builtins.objects.dict.PDict; |
43 | 47 | import com.oracle.graal.python.builtins.objects.object.PythonObject;
|
44 |
| -import com.oracle.graal.python.builtins.objects.type.PythonClass; |
| 48 | +import com.oracle.graal.python.nodes.PGuards; |
45 | 49 | import com.oracle.graal.python.nodes.PNodeWithContext;
|
| 50 | +import com.oracle.graal.python.runtime.object.PythonObjectFactory; |
46 | 51 | import com.oracle.truffle.api.dsl.Cached;
|
47 |
| -import com.oracle.truffle.api.dsl.Cached.Shared; |
48 |
| -import com.oracle.truffle.api.dsl.Fallback; |
49 | 52 | import com.oracle.truffle.api.dsl.GenerateUncached;
|
50 | 53 | import com.oracle.truffle.api.dsl.Specialization;
|
51 | 54 | import com.oracle.truffle.api.library.CachedLibrary;
|
52 | 55 | import com.oracle.truffle.api.object.DynamicObjectLibrary;
|
53 |
| -import com.oracle.truffle.api.profiles.BranchProfile; |
54 | 56 |
|
55 | 57 | @GenerateUncached
|
56 | 58 | public abstract class DeleteDictNode extends PNodeWithContext {
|
57 | 59 | public abstract void execute(PythonObject object);
|
58 | 60 |
|
59 | 61 | @Specialization
|
60 |
| - static void doPythonClass(PythonClass object, |
61 |
| - @Shared("dylib") @CachedLibrary(limit = "4") DynamicObjectLibrary dylib, |
62 |
| - @Cached BranchProfile hasMroShapeProfile) { |
63 |
| - object.setDictHiddenProp(dylib, hasMroShapeProfile, null); |
64 |
| - } |
65 |
| - |
66 |
| - @Fallback |
67 |
| - static void doPythonObjectNotClass(PythonObject object, |
68 |
| - @Shared("dylib") @CachedLibrary(limit = "4") DynamicObjectLibrary dylib) { |
69 |
| - dylib.put(object, PythonObject.DICT, null); |
| 62 | + static void doPythonObject(PythonObject object, |
| 63 | + @CachedLibrary(limit = "4") DynamicObjectLibrary dylib, |
| 64 | + @CachedLibrary(limit = "1") HashingStorageLibrary hlib, |
| 65 | + @Cached PythonObjectFactory factory) { |
| 66 | + /* There is no special handling for class MROs because type.__dict__ cannot be deleted. */ |
| 67 | + assert !PGuards.isPythonClass(object); |
| 68 | + PDict oldDict = (PDict) dylib.getOrDefault(object, PythonObject.DICT, null); |
| 69 | + if (oldDict != null) { |
| 70 | + HashingStorage storage = oldDict.getDictStorage(); |
| 71 | + if (storage instanceof DynamicObjectStorage && ((DynamicObjectStorage) storage).getStore() == object) { |
| 72 | + /* |
| 73 | + * We have to dissociate the dict from this DynamicObject so that changes to it no |
| 74 | + * longer affect this object. |
| 75 | + */ |
| 76 | + oldDict.setDictStorage(hlib.copy(storage)); |
| 77 | + } |
| 78 | + } |
| 79 | + /* |
| 80 | + * Ideally we would use resetShape, but that would lose all the hidden keys. Creating a new |
| 81 | + * empty dict dissociated from this object seems like the cleanest option. The disadvantage |
| 82 | + * is that the current values won't get garbage collected. |
| 83 | + */ |
| 84 | + PDict newDict = factory.createDict(); |
| 85 | + object.setDict(dylib, newDict); |
70 | 86 | }
|
71 | 87 |
|
72 | 88 | public static DeleteDictNode create() {
|
|
0 commit comments