Skip to content

Commit 2714c3f

Browse files
committed
[GR-48216] Unify storage type for native and managed type's subclasses
2 parents b6d7748 + 741a261 commit 2714c3f

File tree

12 files changed

+243
-228
lines changed

12 files changed

+243
-228
lines changed

graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_object.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,36 @@ def test_slots(self):
571571
assert tester.year == 1, "year was %s "% tester.year
572572
assert tester.is_binary_compatible()
573573

574+
def test_subclasses(self):
575+
TestSubclasses = CPyExtType(
576+
'TestSubclasses',
577+
'''
578+
static PyObject* create_type(PyObject* unused, PyObject* args) {
579+
PyObject* bases;
580+
if (!PyArg_ParseTuple(args, "O", &bases))
581+
return NULL;
582+
PyType_Slot slots[] = {
583+
{ 0 }
584+
};
585+
PyType_Spec spec = { "DynamicType", sizeof(PyHeapTypeObject), 0, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, slots };
586+
PyObject* result = PyType_FromSpecWithBases(&spec, bases);
587+
return result;
588+
}
589+
''',
590+
tp_methods='{"create_type", (PyCFunction)create_type, METH_VARARGS | METH_STATIC, ""}'
591+
)
592+
593+
class ManagedBase:
594+
pass
595+
DynamicType = TestSubclasses.create_type((ManagedBase,))
596+
assert ManagedBase.__subclasses__() == [DynamicType]
597+
598+
def add(a, b):
599+
return 42
600+
ManagedBase.__add__ = add
601+
foo = DynamicType()
602+
assert foo + foo == 42
603+
574604
def test_tp_name(self):
575605
TestTpName = CPyExtType("TestTpName",
576606
'''

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/modules/cext/PythonCextSlotBuiltins.java

Lines changed: 1 addition & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,6 @@
9494

9595
import java.nio.charset.CharsetEncoder;
9696
import java.nio.charset.StandardCharsets;
97-
import java.util.Set;
9897

9998
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
10099
import com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiBinaryBuiltinNode;
@@ -118,13 +117,9 @@
118117
import com.oracle.graal.python.builtins.objects.cext.structs.CStructs;
119118
import com.oracle.graal.python.builtins.objects.common.DynamicObjectStorage;
120119
import com.oracle.graal.python.builtins.objects.common.HashingStorage;
121-
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageForEach;
122-
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageForEachCallback;
123-
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageGetItemWithHash;
124120
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageGetIterator;
125121
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageIterator;
126122
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageIteratorKey;
127-
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageIteratorKeyHash;
128123
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageIteratorNext;
129124
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageIteratorValue;
130125
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageLen;
@@ -143,12 +138,9 @@
143138
import com.oracle.graal.python.builtins.objects.str.PString;
144139
import com.oracle.graal.python.builtins.objects.str.StringNodes.StringLenNode;
145140
import com.oracle.graal.python.builtins.objects.str.StringNodes.StringMaterializeNode;
146-
import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass;
147-
import com.oracle.graal.python.builtins.objects.type.PythonClass;
148141
import com.oracle.graal.python.builtins.objects.type.PythonManagedClass;
149142
import com.oracle.graal.python.builtins.objects.type.TypeBuiltins;
150143
import com.oracle.graal.python.builtins.objects.type.TypeNodes;
151-
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetSubclassesNode;
152144
import com.oracle.graal.python.lib.PyObjectLookupAttr;
153145
import com.oracle.graal.python.nodes.PGuards;
154146
import com.oracle.graal.python.nodes.SpecialAttributeNames;
@@ -170,9 +162,7 @@
170162
import com.oracle.truffle.api.dsl.Cached;
171163
import com.oracle.truffle.api.dsl.Cached.Exclusive;
172164
import com.oracle.truffle.api.dsl.Fallback;
173-
import com.oracle.truffle.api.dsl.GenerateUncached;
174165
import com.oracle.truffle.api.dsl.Specialization;
175-
import com.oracle.truffle.api.frame.Frame;
176166
import com.oracle.truffle.api.library.CachedLibrary;
177167
import com.oracle.truffle.api.nodes.Node;
178168
import com.oracle.truffle.api.object.DynamicObjectLibrary;
@@ -856,45 +846,6 @@ static Object doTpDictoffset(PythonManagedClass object, long value,
856846

857847
}
858848

859-
@CApiBuiltin(ret = Void, args = {PyTypeObject, PyObject}, call = Ignored)
860-
abstract static class Py_set_PyTypeObject_tp_subclasses extends CApiBinaryBuiltinNode {
861-
862-
@GenerateUncached
863-
abstract static class EachSubclassAdd extends HashingStorageForEachCallback<Set<PythonAbstractClass>> {
864-
865-
@Override
866-
public abstract Set<PythonAbstractClass> execute(Frame frame, Node inliningTarget, HashingStorage storage, HashingStorageIterator it, Set<PythonAbstractClass> subclasses);
867-
868-
@Specialization
869-
public Set<PythonAbstractClass> doIt(Frame frame, @SuppressWarnings("unused") Node inliningTarget, HashingStorage storage, HashingStorageIterator it, Set<PythonAbstractClass> subclasses,
870-
@Cached HashingStorageIteratorKey itKey,
871-
@Cached HashingStorageIteratorKeyHash itKeyHash,
872-
@Cached HashingStorageGetItemWithHash getItemNode) {
873-
long hash = itKeyHash.execute(inliningTarget, storage, it);
874-
Object key = itKey.execute(inliningTarget, storage, it);
875-
setAdd(subclasses, (PythonClass) getItemNode.execute(frame, inliningTarget, storage, key, hash));
876-
return subclasses;
877-
}
878-
879-
@TruffleBoundary
880-
protected static void setAdd(Set<PythonAbstractClass> set, PythonClass cls) {
881-
set.add(cls);
882-
}
883-
}
884-
885-
@Specialization
886-
static Object doTpSubclasses(PythonClass object, PDict dict,
887-
@Bind("this") Node inliningTarget,
888-
@Cached GetSubclassesNode getSubclassesNode,
889-
@Cached EachSubclassAdd eachNode,
890-
@Cached HashingStorageForEach forEachNode) {
891-
HashingStorage storage = dict.getDictStorage();
892-
Set<PythonAbstractClass> subclasses = getSubclassesNode.execute(inliningTarget, object);
893-
forEachNode.execute(null, inliningTarget, storage, eachNode, subclasses);
894-
return PNone.NO_VALUE;
895-
}
896-
}
897-
898849
@CApiBuiltin(name = "Py_get_dummy", ret = Pointer, args = {Pointer}, call = Ignored)
899850
abstract static class PyGetSlotDummyPtr extends CApiUnaryBuiltinNode {
900851

@@ -909,6 +860,7 @@ Object get(@SuppressWarnings("unused") Object object) {
909860
@CApiBuiltin(name = "Py_set_PyTypeObject_tp_getattro", ret = Void, args = {PyTypeObject, getattrofunc}, call = Ignored)
910861
@CApiBuiltin(name = "Py_set_PyTypeObject_tp_setattr", ret = Void, args = {PyTypeObject, setattrfunc}, call = Ignored)
911862
@CApiBuiltin(name = "Py_set_PyTypeObject_tp_setattro", ret = Void, args = {PyTypeObject, setattrofunc}, call = Ignored)
863+
@CApiBuiltin(name = "Py_set_PyTypeObject_tp_subclasses", ret = Void, args = {PyTypeObject, PyObject}, call = Ignored)
912864
@CApiBuiltin(name = "Py_set_PyTypeObject_tp_finalize", ret = Void, args = {PyTypeObject, destructor}, call = Ignored)
913865
@CApiBuiltin(name = "Py_set_PyTypeObject_tp_iter", ret = Void, args = {PyTypeObject, getiterfunc}, call = Ignored)
914866
@CApiBuiltin(name = "Py_set_PyTypeObject_tp_iternext", ret = Void, args = {PyTypeObject, iternextfunc}, call = Ignored)

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
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;
8182
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetTypeFlagsNode;
8283
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetWeakListOffsetNode;
8384
import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetDictOffsetNodeGen;
@@ -373,7 +374,8 @@ static void initializeType(PythonClassNativeWrapper obj, Object mem,
373374
}
374375
writePtrNode.write(mem, CFields.PyTypeObject__tp_mro, toNative.execute(clazz.mroStore));
375376
writePtrNode.write(mem, CFields.PyTypeObject__tp_cache, nullValue);
376-
writePtrNode.write(mem, CFields.PyTypeObject__tp_subclasses, toNativeNewRef.execute(factory.createDict()));
377+
PDict subclasses = GetSubclassesNode.executeUncached(clazz);
378+
writePtrNode.write(mem, CFields.PyTypeObject__tp_subclasses, toNativeNewRef.execute(subclasses));
377379
writePtrNode.write(mem, CFields.PyTypeObject__tp_weaklist, nullValue);
378380
writePtrNode.write(mem, CFields.PyTypeObject__tp_del, lookup(clazz, PyTypeObject__tp_del, TypeBuiltins.TYPE_DEL));
379381
writeI32Node.write(mem, CFields.PyTypeObject__tp_version_tag, 0);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/HashingStorageNodes.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,10 @@
4848
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodesFactory.HashingStorageDelItemNodeGen;
4949
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodesFactory.HashingStorageForEachNodeGen;
5050
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodesFactory.HashingStorageGetItemNodeGen;
51+
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodesFactory.HashingStorageGetItemWithHashNodeGen;
5152
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodesFactory.HashingStorageGetIteratorNodeGen;
5253
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodesFactory.HashingStorageGetReverseIteratorNodeGen;
54+
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodesFactory.HashingStorageIteratorKeyHashNodeGen;
5355
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodesFactory.HashingStorageIteratorKeyNodeGen;
5456
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodesFactory.HashingStorageIteratorNextNodeGen;
5557
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodesFactory.HashingStorageIteratorValueNodeGen;
@@ -114,6 +116,11 @@ public static boolean mayHaveSideEffects(PHashingCollection wrapper) {
114116
@GenerateInline
115117
@GenerateCached(false)
116118
public abstract static class HashingStorageGetItemWithHash extends Node {
119+
120+
public static Object getItemWithHash(HashingStorage self, Object key, long keyHash) {
121+
return HashingStorageGetItemWithHashNodeGen.getUncached().execute(null, null, self, key, keyHash);
122+
}
123+
117124
public abstract Object execute(Frame frame, Node inliningTarget, HashingStorage self, Object key, long keyHash);
118125

119126
@Specialization
@@ -479,6 +486,10 @@ public static void executeUncached(HashingStorage self, Object key, PHashingColl
479486
HashingStorageDelItemNodeGen.getUncached().executeWithAsserts(null, null, self, key, false, toUpdate);
480487
}
481488

489+
public static void executeUncachedWithHash(EconomicMapStorage storage, Object key, long hash) {
490+
ObjectHashMapFactory.RemoveNodeGen.getUncached().execute(null, null, storage.map, key, hash);
491+
}
492+
482493
public final void execute(Node inliningTarget, HashingStorage self, TruffleString key, PHashingCollection toUpdate) {
483494
// Shortcut for frequent usage with TruffleString. We do not need a frame in such case,
484495
// because the string's __hash__ does not need it. Some fast-paths avoid even invoking
@@ -644,6 +655,10 @@ public static HashingStorageCopy create() {
644655
return HashingStorageCopyNodeGen.create();
645656
}
646657

658+
public static HashingStorage executeUncached(HashingStorage source) {
659+
return HashingStorageCopyNodeGen.getUncached().execute(null, source);
660+
}
661+
647662
public final HashingStorage executeCached(HashingStorage source) {
648663
return execute(this, source);
649664
}
@@ -997,6 +1012,11 @@ static Object keywords(KeywordsStorage self, HashingStorageIterator it) {
9971012
@GenerateCached(false)
9981013
@ImportStatic({PGuards.class})
9991014
public abstract static class HashingStorageIteratorKeyHash extends Node {
1015+
1016+
public static long executeUncached(HashingStorage storage, HashingStorageIterator it) {
1017+
return HashingStorageIteratorKeyHashNodeGen.getUncached().execute(null, storage, it);
1018+
}
1019+
10001020
public abstract long execute(Node node, HashingStorage storage, HashingStorageIterator it);
10011021

10021022
@Specialization

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
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.type.TypeNodes.GetSubclassesAsArrayNode;
3738
import com.oracle.graal.python.nodes.attributes.ReadAttributeFromDynamicObjectNode;
3839
import com.oracle.graal.python.nodes.classes.IsSubtypeNode;
3940
import com.oracle.graal.python.nodes.interop.PForeignToPTypeNode;
@@ -373,7 +374,7 @@ static void updateMroShapeSubTypes(PythonBuiltinClass klass) {
373374
if (next instanceof PythonClass) {
374375
((PythonClass) next).updateMroShapeSubTypes(lang);
375376
} else {
376-
toProcess.addAll(((PythonBuiltinClass) next).getSubClasses());
377+
toProcess.addAll(Arrays.asList(GetSubclassesAsArrayNode.executeUncached(next)));
377378
}
378379
}
379380
}

0 commit comments

Comments
 (0)