Skip to content

Commit 6641fa5

Browse files
committed
Support native types in 'GetSubclassesNode'.
1 parent 934dcd9 commit 6641fa5

File tree

2 files changed

+106
-10
lines changed
  • graalpython
    • com.oracle.graal.python.cext/src
    • com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type

2 files changed

+106
-10
lines changed

graalpython/com.oracle.graal.python.cext/src/typeobject.c

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -326,14 +326,6 @@ int PyType_Ready(PyTypeObject* cls) {
326326
}
327327
cls->tp_bases = bases;
328328

329-
PyObject* native_members = PyDict_New();
330-
PyDict_SetItemString(native_members, "tp_name", polyglot_from_string(cls->tp_name, SRC_CS));
331-
PyDict_SetItemString(native_members, "tp_doc", polyglot_from_string(cls->tp_doc ? cls->tp_doc : "", SRC_CS));
332-
PyDict_SetItemString(native_members, "tp_basicsize", PyLong_FromSsize_t(cls->tp_basicsize));
333-
PyDict_SetItemString(native_members, "tp_itemsize", PyLong_FromSsize_t(cls->tp_itemsize));
334-
PyDict_SetItemString(native_members, "tp_dictoffset", PyLong_FromSsize_t(cls->tp_dictoffset));
335-
const char* class_name = cls->tp_name;
336-
337329
/* Initialize tp_dict */
338330
PyObject* dict = cls->tp_dict;
339331
if (dict == NULL) {
@@ -344,7 +336,6 @@ int PyType_Ready(PyTypeObject* cls) {
344336
cls->tp_dict = dict;
345337
}
346338

347-
348339
PyMethodDef* methods = cls->tp_methods;
349340
if (methods) {
350341
int idx = 0;
@@ -524,6 +515,9 @@ int PyType_Ready(PyTypeObject* cls) {
524515
PyTruffle_Type_AddSlots(cls, inherited_slots_tuple);
525516
}
526517

518+
/* Initialize this classes' tp_subclasses dict. This is necessary because our managed classes won't do. */
519+
cls->tp_subclasses = PyDict_New();
520+
527521
/* Link into each base class's list of subclasses */
528522
bases = cls->tp_bases;
529523
Py_ssize_t n = PyTuple_GET_SIZE(bases);

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

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@
4343
import static com.oracle.graal.python.nodes.SpecialMethodNames.__EQ__;
4444

4545
import java.util.ArrayList;
46+
import java.util.Collection;
47+
import java.util.HashSet;
48+
import java.util.Iterator;
4649
import java.util.List;
4750
import java.util.Set;
4851

@@ -53,7 +56,11 @@
5356
import com.oracle.graal.python.builtins.objects.cext.NativeMemberNames;
5457
import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject;
5558
import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass;
59+
import com.oracle.graal.python.builtins.objects.cext.PythonNativeVoidPtr;
60+
import com.oracle.graal.python.builtins.objects.common.HashingStorage;
61+
import com.oracle.graal.python.builtins.objects.common.HashingStorage.Equivalence;
5662
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
63+
import com.oracle.graal.python.builtins.objects.dict.PDict;
5764
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
5865
import com.oracle.graal.python.builtins.objects.type.ManagedPythonClass.FlagsContainer;
5966
import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetBaseClassesNodeGen;
@@ -68,6 +75,7 @@
6875
import com.oracle.graal.python.nodes.PGuards;
6976
import com.oracle.graal.python.nodes.PNodeWithContext;
7077
import com.oracle.graal.python.nodes.SpecialMethodNames;
78+
import com.oracle.graal.python.nodes.truffle.PythonTypes;
7179
import com.oracle.graal.python.runtime.sequence.storage.MroSequenceStorage;
7280
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
7381
import com.oracle.truffle.api.CompilerAsserts;
@@ -77,8 +85,10 @@
7785
import com.oracle.truffle.api.dsl.Fallback;
7886
import com.oracle.truffle.api.dsl.ImportStatic;
7987
import com.oracle.truffle.api.dsl.Specialization;
88+
import com.oracle.truffle.api.dsl.TypeSystemReference;
8089
import com.oracle.truffle.api.interop.ForeignAccess;
8190
import com.oracle.truffle.api.interop.Message;
91+
import com.oracle.truffle.api.interop.TruffleObject;
8292
import com.oracle.truffle.api.interop.UnknownIdentifierException;
8393
import com.oracle.truffle.api.interop.UnsupportedMessageException;
8494
import com.oracle.truffle.api.nodes.Node;
@@ -285,6 +295,8 @@ public static GetSuperClassNode create() {
285295

286296
}
287297

298+
@TypeSystemReference(PythonTypes.class)
299+
@ImportStatic(NativeMemberNames.class)
288300
public abstract static class GetSubclassesNode extends PNodeWithContext {
289301

290302
public abstract Set<AbstractPythonClass> execute(Object obj);
@@ -299,18 +311,108 @@ Set<AbstractPythonClass> doPythonClass(PythonBuiltinClassType obj) {
299311
return getBuiltinPythonClass(obj).getSubClasses();
300312
}
301313

314+
@Specialization
315+
@TruffleBoundary
316+
Set<AbstractPythonClass> doNativeClass(PythonNativeClass obj,
317+
@Cached("create(TP_SUBCLASSES)") GetTypeMemberNode getTpSubclassesNode,
318+
@Cached("createClassProfile()") ValueProfile profile) {
319+
Object tpSubclasses = getTpSubclassesNode.execute(obj);
320+
321+
Object profiled = profile.profile(tpSubclasses);
322+
if (profiled instanceof PDict) {
323+
return wrapDict(profiled);
324+
}
325+
CompilerDirectives.transferToInterpreter();
326+
throw new IllegalStateException("invalid subclasses dict " + profiled.getClass().getName());
327+
}
328+
302329
@TruffleBoundary
303330
public static Set<AbstractPythonClass> doSlowPath(Object obj) {
304331
if (obj instanceof ManagedPythonClass) {
305332
return ((ManagedPythonClass) obj).getSubClasses();
306333
} else if (obj instanceof PythonBuiltinClassType) {
307334
return PythonLanguage.getCore().lookupType((PythonBuiltinClassType) obj).getSubClasses();
308335
} else if (PGuards.isNativeClass(obj)) {
309-
// TODO implement
336+
Object tpSubclasses = GetTypeMemberNode.doSlowPath(obj, NativeMemberNames.TP_SUBCLASSES);
337+
if (tpSubclasses instanceof PDict) {
338+
return wrapDict(tpSubclasses);
339+
}
340+
throw new IllegalStateException("invalid subclasses dict " + tpSubclasses.getClass().getName());
310341
}
311342
throw new IllegalStateException("unknown type " + obj.getClass().getName());
312343
}
313344

345+
private static Set<AbstractPythonClass> wrapDict(Object tpSubclasses) {
346+
return new Set<AbstractPythonClass>() {
347+
private final PDict dict = (PDict) tpSubclasses;
348+
349+
public int size() {
350+
return dict.getDictStorage().length();
351+
}
352+
353+
public boolean isEmpty() {
354+
return size() == 0;
355+
}
356+
357+
public boolean contains(Object o) {
358+
HashingStorage s = dict.getDictStorage();
359+
Equivalence equiv = HashingStorage.getSlowPathEquivalence(o);
360+
for (Object val : s.values()) {
361+
if (equiv.equals(o, val)) {
362+
return true;
363+
}
364+
}
365+
return false;
366+
}
367+
368+
@SuppressWarnings("unchecked")
369+
public Iterator<AbstractPythonClass> iterator() {
370+
return (Iterator<AbstractPythonClass>) dict.getDictStorage().values();
371+
}
372+
373+
public Object[] toArray() {
374+
return dict.getDictStorage().valuesAsArray();
375+
}
376+
377+
public <T> T[] toArray(T[] a) {
378+
throw new UnsupportedOperationException();
379+
}
380+
381+
public boolean add(AbstractPythonClass e) {
382+
if (PGuards.isNativeClass(e)) {
383+
dict.setItem(PythonNativeClass.cast(e).getPtr(), e);
384+
}
385+
dict.setItem(new PythonNativeVoidPtr((TruffleObject) e), e);
386+
return true;
387+
}
388+
389+
public boolean remove(Object o) {
390+
throw new UnsupportedOperationException();
391+
}
392+
393+
public boolean containsAll(Collection<?> c) {
394+
throw new UnsupportedOperationException();
395+
}
396+
397+
public boolean addAll(Collection<? extends AbstractPythonClass> c) {
398+
throw new UnsupportedOperationException();
399+
}
400+
401+
public boolean retainAll(Collection<?> c) {
402+
throw new UnsupportedOperationException();
403+
}
404+
405+
public boolean removeAll(Collection<?> c) {
406+
throw new UnsupportedOperationException();
407+
}
408+
409+
public void clear() {
410+
throw new UnsupportedOperationException();
411+
}
412+
413+
};
414+
}
415+
314416
public static GetSubclassesNode create() {
315417
return GetSubclassesNodeGen.create();
316418
}

0 commit comments

Comments
 (0)