Skip to content

Commit 4a78fe8

Browse files
qunaibitsteve-s
authored andcommitted
Use dict instead HashSet for type's subclasses
1 parent 5876e5a commit 4a78fe8

File tree

8 files changed

+173
-165
lines changed

8 files changed

+173
-165
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/AbcModuleBuiltins.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@
4747
import static com.oracle.graal.python.util.PythonUtils.toTruffleStringUncached;
4848

4949
import java.util.List;
50-
import java.util.Set;
5150

5251
import com.oracle.graal.python.builtins.Builtin;
5352
import com.oracle.graal.python.builtins.CoreFunctions;
@@ -56,6 +55,7 @@
5655
import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass;
5756
import com.oracle.graal.python.builtins.objects.type.TypeFlags;
5857
import com.oracle.graal.python.builtins.objects.type.TypeNodes;
58+
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetSubclassesAsArrayNode;
5959
import com.oracle.graal.python.lib.PyObjectLookupAttr;
6060
import com.oracle.graal.python.nodes.ErrorMessages;
6161
import com.oracle.graal.python.nodes.attributes.DeleteAttributeNode;
@@ -139,7 +139,7 @@ private static void setCollectionFlagRecursive(Object child, long flag) {
139139
return;
140140
}
141141
TypeNodes.SetTypeFlagsNode.executeUncached(child, tpFlags);
142-
Set<PythonAbstractClass> grandchildren = TypeNodes.GetSubclassesNode.executeUncached(child);
142+
PythonAbstractClass[] grandchildren = GetSubclassesAsArrayNode.executeUncached(child);
143143
for (PythonAbstractClass c : grandchildren) {
144144
if (TypeNodes.IsTypeNode.executeUncached(c)) {
145145
setCollectionFlagRecursive(c, flag);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextBuiltinRegistry.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1745,7 +1745,7 @@ static CApiBuiltinNode createBuiltinNode(int id) {
17451745
case 399:
17461746
return com.oracle.graal.python.builtins.modules.cext.PythonCextSlotBuiltinsFactory.PySetSlotDummyPtrNodeGen.create();
17471747
case 400:
1748-
return com.oracle.graal.python.builtins.modules.cext.PythonCextSlotBuiltinsFactory.Py_set_PyTypeObject_tp_subclassesNodeGen.create();
1748+
return com.oracle.graal.python.builtins.modules.cext.PythonCextSlotBuiltinsFactory.PySetSlotDummyPtrNodeGen.create();
17491749
case 401:
17501750
return com.oracle.graal.python.builtins.modules.cext.PythonCextSlotBuiltinsFactory.PySetSlotDummyPtrNodeGen.create();
17511751
case 402:

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/ToNativeTypeNode.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@
7878
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetBasicSizeNode;
7979
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetItemSizeNode;
8080
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroStorageNode;
81+
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetSubclassesNode;
82+
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetSuperClassNode;
8183
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetTypeFlagsNode;
8284
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetWeakListOffsetNode;
8385
import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetDictOffsetNodeGen;
@@ -373,7 +375,8 @@ static void initializeType(PythonClassNativeWrapper obj, Object mem,
373375
}
374376
writePtrNode.write(mem, CFields.PyTypeObject__tp_mro, toNative.execute(clazz.mroStore));
375377
writePtrNode.write(mem, CFields.PyTypeObject__tp_cache, nullValue);
376-
writePtrNode.write(mem, CFields.PyTypeObject__tp_subclasses, toNativeNewRef.execute(factory.createDict()));
378+
PDict subclasses = GetSubclassesNode.executeUncached(clazz);
379+
writePtrNode.write(mem, CFields.PyTypeObject__tp_subclasses, toNativeNewRef.execute(subclasses));
377380
writePtrNode.write(mem, CFields.PyTypeObject__tp_weaklist, nullValue);
378381
writePtrNode.write(mem, CFields.PyTypeObject__tp_del, lookup(clazz, PyTypeObject__tp_del, TypeBuiltins.TYPE_DEL));
379382
writeI32Node.write(mem, CFields.PyTypeObject__tp_version_tag, 0);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonClass.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,15 @@
3434
import com.oracle.graal.python.builtins.objects.PNone;
3535
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyDef;
3636
import com.oracle.graal.python.builtins.objects.cext.hpy.HPyTypeExtra;
37+
import com.oracle.graal.python.builtins.objects.common.HashingStorage;
38+
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageGetItemWithHash;
39+
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageGetIterator;
40+
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageIterator;
41+
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageIteratorKey;
42+
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageIteratorKeyHash;
43+
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageIteratorNext;
44+
import com.oracle.graal.python.builtins.objects.dict.PDict;
45+
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetSubclassesAsArrayNode;
3746
import com.oracle.graal.python.nodes.attributes.ReadAttributeFromDynamicObjectNode;
3847
import com.oracle.graal.python.nodes.classes.IsSubtypeNode;
3948
import com.oracle.graal.python.nodes.interop.PForeignToPTypeNode;
@@ -360,6 +369,18 @@ private void updateMroShapeSubTypes(PythonLanguage lang) {
360369
}
361370
}
362371

372+
private static void addToProcess(ArrayDeque<Object> toProcess, PythonManagedClass klass) {
373+
PDict subclasses = klass.getSubClasses();
374+
HashingStorage storage = subclasses.getDictStorage();
375+
HashingStorageIterator it = HashingStorageGetIterator.executeUncached(storage);
376+
while (HashingStorageIteratorNext.executeUncached(storage, it)) {
377+
long hash = HashingStorageIteratorKeyHash.executeUncached(storage, it);
378+
Object key = HashingStorageIteratorKey.executeUncached(storage, it);
379+
Object clazz = HashingStorageGetItemWithHash.getItemWithHash(storage, key, hash);
380+
toProcess.add(clazz);
381+
}
382+
}
383+
363384
/**
364385
* Can be used to update MRO shapes in inheritance hierarchy of a builtin.
365386
*/
@@ -373,7 +394,7 @@ static void updateMroShapeSubTypes(PythonBuiltinClass klass) {
373394
if (next instanceof PythonClass) {
374395
((PythonClass) next).updateMroShapeSubTypes(lang);
375396
} else {
376-
toProcess.addAll(((PythonBuiltinClass) next).getSubClasses());
397+
toProcess.addAll(Arrays.asList(GetSubclassesAsArrayNode.executeUncached(next)));
377398
}
378399
}
379400
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonManagedClass.java

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -30,22 +30,25 @@
3030
import static com.oracle.graal.python.nodes.truffle.TruffleStringMigrationHelpers.assertNoJavaString;
3131

3232
import java.util.ArrayList;
33-
import java.util.LinkedHashSet;
34-
import java.util.Set;
3533

3634
import com.oracle.graal.python.PythonLanguage;
3735
import com.oracle.graal.python.builtins.objects.PNone;
3836
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes.PCallCapiFunction;
3937
import com.oracle.graal.python.builtins.objects.cext.capi.NativeCAPISymbol;
4038
import com.oracle.graal.python.builtins.objects.cext.capi.PythonClassNativeWrapper;
4139
import com.oracle.graal.python.builtins.objects.cext.capi.transitions.CApiTransitionsFactory.PythonToNativeNodeGen;
40+
import com.oracle.graal.python.builtins.objects.common.HashingStorage;
41+
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageCopy;
42+
import com.oracle.graal.python.builtins.objects.dict.PDict;
4243
import com.oracle.graal.python.builtins.objects.object.PythonObject;
4344
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
4445
import com.oracle.graal.python.builtins.objects.type.TypeNodes.ComputeMroNode;
46+
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetSubclassesAsArrayNode;
4547
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetSubclassesNode;
4648
import com.oracle.graal.python.nodes.ErrorMessages;
4749
import com.oracle.graal.python.nodes.PGuards;
4850
import com.oracle.graal.python.nodes.PRaiseNode;
51+
import com.oracle.graal.python.runtime.PythonContext;
4952
import com.oracle.graal.python.runtime.exception.PException;
5053
import com.oracle.graal.python.runtime.sequence.storage.MroSequenceStorage;
5154
import com.oracle.truffle.api.Assumption;
@@ -65,7 +68,7 @@ public abstract class PythonManagedClass extends PythonObject implements PythonA
6568
private boolean abstractClass;
6669

6770
// Needs to maintain the order. It would make sense to use weakrefs, but CPython doesn't do that
68-
private final LinkedHashSet<PythonAbstractClass> subClasses = new LinkedHashSet<>();
71+
private final PDict subClasses;
6972
@CompilationFinal private Shape instanceShape;
7073
private TruffleString name;
7174
private TruffleString qualName;
@@ -124,6 +127,8 @@ protected PythonManagedClass(PythonLanguage lang, Object typeClass, Shape classS
124127
// provide our instances with a fresh shape tree
125128
this.instanceShape = lang.getShapeForClass(this);
126129
}
130+
131+
this.subClasses = new PDict(lang);
127132
}
128133

129134
public boolean isMROInitialized() {
@@ -153,7 +158,7 @@ public Assumption getLookupStableAssumption() {
153158
public void lookupChanged() {
154159
CompilerAsserts.neverPartOfCompilation();
155160
methodResolutionOrder.lookupChanged();
156-
for (PythonAbstractClass subclass : getSubClasses()) {
161+
for (PythonAbstractClass subclass : GetSubclassesAsArrayNode.executeUncached(this)) {
157162
if (subclass != null) {
158163
subclass.lookupChanged();
159164
}
@@ -276,7 +281,7 @@ private void unsafeSetSuperClass(PythonAbstractClass... newBaseClasses) {
276281
Object nativeBase = PythonToNativeNodeGen.getUncached().execute(base);
277282
PCallCapiFunction.getUncached().call(NativeCAPISymbol.FUN_TRUFFLE_CHECK_TYPE_READY, nativeBase);
278283
}
279-
GetSubclassesNode.executeUncached(base).add(this);
284+
GetSubclassesNode.unsafeAddSubclass(base, this);
280285
}
281286
}
282287
}
@@ -285,16 +290,16 @@ private void unsafeSetSuperClass(PythonAbstractClass... newBaseClasses) {
285290
public final void setBases(Object newBaseClass, PythonAbstractClass[] newBaseClasses) {
286291
ArrayList<Set<PythonAbstractClass>> newBasesSubclasses = new ArrayList<>(newBaseClasses.length);
287292
for (PythonAbstractClass type : newBaseClasses) {
288-
newBasesSubclasses.add(GetSubclassesNode.executeUncached(type));
293+
HashingStorage storage = GetSubclassesNode.executeUncached(newBase).getDictStorage();
294+
newBasesSubclasses.add(HashingStorageCopy.executeUncached(storage));
289295
}
290296

291297
Object oldBase = getBase();
292298
PythonAbstractClass[] oldBaseClasses = getBaseClasses();
293299
PythonAbstractClass[] oldMRO = (PythonAbstractClass[]) this.methodResolutionOrder.getInternalArray();
294300

295-
Set<PythonAbstractClass> subclasses = GetSubclassesNode.executeUncached(this);
296-
PythonAbstractClass[] subclassesArray = subclasses.toArray(new PythonAbstractClass[subclasses.size()]);
297-
PythonAbstractClass[][] oldSubClasssMROs = new PythonAbstractClass[subclasses.size()][];
301+
PythonAbstractClass[] subclassesArray = GetSubclassesAsArrayNode.executeUncached(this);
302+
PythonAbstractClass[][] oldSubClasssMROs = new PythonAbstractClass[subclassesArray.length][];
298303
for (int i = 0; i < subclassesArray.length; i++) {
299304
PythonAbstractClass scls = subclassesArray[i];
300305
if (scls instanceof PythonManagedClass) {
@@ -309,23 +314,35 @@ public final void setBases(Object newBaseClass, PythonAbstractClass[] newBaseCla
309314
this.methodResolutionOrder.lookupChanged();
310315
this.setMRO(ComputeMroNode.doSlowPath(this));
311316

312-
for (PythonAbstractClass scls : subclasses) {
317+
for (PythonAbstractClass scls : subclassesArray) {
313318
if (scls instanceof PythonManagedClass) {
314319
PythonManagedClass pmc = (PythonManagedClass) scls;
315320
pmc.methodResolutionOrder.lookupChanged();
316321
pmc.setMRO(ComputeMroNode.doSlowPath(scls));
317322
}
318323
}
324+
325+
boolean isCtxInitialized = PythonContext.get(null).isInitialized();
319326
if (this.baseClasses == newBaseClasses) {
320327
// take no action if bases were replaced through reentrance
321328
for (PythonAbstractClass base : oldBaseClasses) {
322329
if (base instanceof PythonManagedClass) {
323-
GetSubclassesNode.executeUncached(base).remove(this);
330+
if (isCtxInitialized) {
331+
GetSubclassesNode.executeUncached(base).delItem(this);
332+
} else {
333+
// slots aren't populated yet during context initialization
334+
GetSubclassesNode.unsafeRemoveSubclass(base, this);
335+
}
324336
}
325337
}
326338
for (PythonAbstractClass base : newBaseClasses) {
327339
if (base instanceof PythonManagedClass) {
328-
GetSubclassesNode.executeUncached(base).add(this);
340+
if (isCtxInitialized) {
341+
GetSubclassesNode.executeUncached(base).setItem(this, this);
342+
} else {
343+
// slots aren't populated yet during context initialization
344+
GetSubclassesNode.unsafeAddSubclass(base, this);
345+
}
329346
}
330347
}
331348
}
@@ -335,9 +352,8 @@ public final void setBases(Object newBaseClass, PythonAbstractClass[] newBaseCla
335352
for (int i = 0; i < newBaseClasses.length; i++) {
336353
PythonAbstractClass base = newBaseClasses[i];
337354
if (base != null) {
338-
Set<PythonAbstractClass> s = GetSubclassesNode.executeUncached(base);
339-
s.clear();
340-
s.addAll(newBasesSubclasses.get(i));
355+
PDict dict = GetSubclassesNode.executeUncached(base);
356+
dict.setDictStorage(newBasesSubclasses.get(i));
341357
}
342358
}
343359
if (this.baseClasses == newBaseClasses) {
@@ -362,7 +378,7 @@ public final void setBases(Object newBaseClass, PythonAbstractClass[] newBaseCla
362378
}
363379
}
364380

365-
final LinkedHashSet<PythonAbstractClass> getSubClasses() {
381+
final PDict getSubClasses() {
366382
return subClasses;
367383
}
368384

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/SpecialMethodSlot.java

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@
162162
import com.oracle.graal.python.builtins.objects.method.PBuiltinMethod;
163163
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetBaseClassNode;
164164
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroStorageNode;
165-
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetSubclassesNode;
165+
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetSubclassesAsArrayNode;
166166
import com.oracle.graal.python.lib.GetMethodsFlagsNodeGen;
167167
import com.oracle.graal.python.nodes.attributes.LookupAttributeInMRONode;
168168
import com.oracle.graal.python.nodes.attributes.LookupCallableSlotInMRONode;
@@ -497,9 +497,8 @@ public static void reinitializeSpecialMethodSlots(PythonNativeClass klass, Pytho
497497
}
498498

499499
private static void reinitializeSpecialMethodSlots(Object klass, PythonLanguage language) {
500-
java.util.Set<PythonAbstractClass> subClasses;
501-
if (klass instanceof PythonManagedClass) {
502-
PythonManagedClass managedClass = (PythonManagedClass) klass;
500+
PythonAbstractClass[] subClasses;
501+
if (klass instanceof PythonManagedClass managedClass) {
503502
// specialMethodSlots can be null if the type is just being initialized, for example,
504503
// when the initialization calls the "mro" method, which may execute arbitrary code
505504
// including setting its __bases__ to something.
@@ -510,9 +509,9 @@ private static void reinitializeSpecialMethodSlots(Object klass, PythonLanguage
510509
managedClass.specialMethodSlots = null;
511510
initializeSpecialMethodSlots(managedClass, GetMroStorageNode.executeUncached(managedClass), language);
512511
}
513-
subClasses = managedClass.getSubClasses();
514-
} else if (klass instanceof PythonNativeClass) {
515-
subClasses = GetSubclassesNode.executeUncached(klass);
512+
subClasses = GetSubclassesAsArrayNode.executeUncached(managedClass);
513+
} else if (klass instanceof PythonNativeClass clazz) {
514+
subClasses = GetSubclassesAsArrayNode.executeUncached(clazz);
516515
} else {
517516
throw new AssertionError(Objects.toString(klass));
518517
}
@@ -740,7 +739,7 @@ public static void fixupSpecialMethodSlot(PythonNativeClass klass, SpecialMethod
740739
// proceed with that
741740
newValue = LookupAttributeInMRONode.lookupSlowPath(klass, slot.getName());
742741
}
743-
fixupSpecialMethodInSubClasses(GetSubclassesNode.executeUncached(klass), slot, newValue, PythonContext.get(null));
742+
fixupSpecialMethodInSubClasses(GetSubclassesAsArrayNode.executeUncached(klass), slot, newValue, PythonContext.get(null));
744743
}
745744

746745
@TruffleBoundary
@@ -770,7 +769,7 @@ public static void fixupSpecialMethodSlot(PythonManagedClass klass, SpecialMetho
770769
if (oldValue == PNone.NO_VALUE) {
771770
setMethodsFlag(klass, slot.getMethodsFlag(), context);
772771
}
773-
fixupSpecialMethodInSubClasses(klass.getSubClasses(), slot, value, context);
772+
fixupSpecialMethodInSubClasses(GetSubclassesAsArrayNode.executeUncached(klass), slot, value, context);
774773
}
775774

776775
// Note: originalValue == null means originalValue is not available
@@ -791,7 +790,7 @@ private static void fixupSpecialMethodSlotInternal(PythonManagedClass klass, Spe
791790
if (currentOldValue != currentNewValue) {
792791
// Something actually changed, fixup subclasses...
793792
slot.setValue(klass, currentNewValue, context);
794-
fixupSpecialMethodInSubClasses(klass.getSubClasses(), slot, newValue, context);
793+
fixupSpecialMethodInSubClasses(GetSubclassesAsArrayNode.executeUncached(klass), slot, newValue, context);
795794
}
796795
}
797796

@@ -801,13 +800,13 @@ private static void fixupSpecialMethodSlot(Object klass, SpecialMethodSlot slot,
801800
fixupSpecialMethodSlotInternal((PythonManagedClass) klass, slot, newValue, context);
802801
} else if (klass instanceof PythonNativeClass clazz) {
803802
setMethodsFlag(clazz, slot.getMethodsFlag(), context);
804-
fixupSpecialMethodInSubClasses(GetSubclassesNode.executeUncached(klass), slot, newValue, context);
803+
fixupSpecialMethodInSubClasses(GetSubclassesAsArrayNode.executeUncached(clazz), slot, newValue, context);
805804
} else {
806805
throw new AssertionError(Objects.toString(klass));
807806
}
808807
}
809808

810-
private static void fixupSpecialMethodInSubClasses(java.util.Set<PythonAbstractClass> subClasses, SpecialMethodSlot slot, Object newValue, PythonContext context) {
809+
private static void fixupSpecialMethodInSubClasses(PythonAbstractClass[] subClasses, SpecialMethodSlot slot, Object newValue, PythonContext context) {
811810
for (PythonAbstractClass subClass : subClasses) {
812811
fixupSpecialMethodSlot(subClass, slot, newValue, context);
813812
}

0 commit comments

Comments
 (0)