Skip to content

Commit 934dcd9

Browse files
committed
Inherit special flags and slots.
1 parent 63b6055 commit 934dcd9

File tree

1 file changed

+74
-8
lines changed

1 file changed

+74
-8
lines changed

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

Lines changed: 74 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,70 @@ static PyObject* wrap_reverse_binop(binaryfunc f, PyObject* a, PyObject* b) {
168168
return f(b, a);
169169
}
170170

171+
static void
172+
inherit_special(PyTypeObject *type, PyTypeObject *base)
173+
{
174+
175+
/* Copying basicsize is connected to the GC flags */
176+
if (!(type->tp_flags & Py_TPFLAGS_HAVE_GC) &&
177+
(base->tp_flags & Py_TPFLAGS_HAVE_GC) &&
178+
(!type->tp_traverse && !type->tp_clear)) {
179+
type->tp_flags |= Py_TPFLAGS_HAVE_GC;
180+
if (type->tp_traverse == NULL)
181+
type->tp_traverse = base->tp_traverse;
182+
if (type->tp_clear == NULL)
183+
type->tp_clear = base->tp_clear;
184+
}
185+
{
186+
/* The condition below could use some explanation.
187+
It appears that tp_new is not inherited for static types
188+
whose base class is 'object'; this seems to be a precaution
189+
so that old extension types don't suddenly become
190+
callable (object.__new__ wouldn't insure the invariants
191+
that the extension type's own factory function ensures).
192+
Heap types, of course, are under our control, so they do
193+
inherit tp_new; static extension types that specify some
194+
other built-in type as the default also
195+
inherit object.__new__. */
196+
if (base != &PyBaseObject_Type ||
197+
(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
198+
if (type->tp_new == NULL)
199+
type->tp_new = base->tp_new;
200+
}
201+
}
202+
if (type->tp_basicsize == 0)
203+
type->tp_basicsize = base->tp_basicsize;
204+
205+
/* Copy other non-function slots */
206+
207+
#undef COPYVAL
208+
#define COPYVAL(SLOT) \
209+
if (type->SLOT == 0) type->SLOT = base->SLOT
210+
211+
COPYVAL(tp_itemsize);
212+
COPYVAL(tp_weaklistoffset);
213+
COPYVAL(tp_dictoffset);
214+
215+
/* Setup fast subclass flags */
216+
if (PyType_IsSubtype(base, (PyTypeObject*)PyExc_BaseException))
217+
type->tp_flags |= Py_TPFLAGS_BASE_EXC_SUBCLASS;
218+
else if (PyType_IsSubtype(base, &PyType_Type))
219+
type->tp_flags |= Py_TPFLAGS_TYPE_SUBCLASS;
220+
else if (PyType_IsSubtype(base, &PyLong_Type))
221+
type->tp_flags |= Py_TPFLAGS_LONG_SUBCLASS;
222+
else if (PyType_IsSubtype(base, &PyBytes_Type))
223+
type->tp_flags |= Py_TPFLAGS_BYTES_SUBCLASS;
224+
else if (PyType_IsSubtype(base, &PyUnicode_Type))
225+
type->tp_flags |= Py_TPFLAGS_UNICODE_SUBCLASS;
226+
else if (PyType_IsSubtype(base, &PyTuple_Type))
227+
type->tp_flags |= Py_TPFLAGS_TUPLE_SUBCLASS;
228+
else if (PyType_IsSubtype(base, &PyList_Type))
229+
type->tp_flags |= Py_TPFLAGS_LIST_SUBCLASS;
230+
else if (PyType_IsSubtype(base, &PyDict_Type))
231+
type->tp_flags |= Py_TPFLAGS_DICT_SUBCLASS;
232+
}
233+
234+
171235
// TODO(fa): there should actually be 'native_to_java' just in case 'javacls' goes to native in between
172236
// TODO support member flags other than READONLY
173237
UPCALL_ID(AddMember);
@@ -251,7 +315,7 @@ int PyType_Ready(PyTypeObject* cls) {
251315
if (base == NULL) {
252316
bases = PyTuple_New(0);
253317
} else {
254-
bases = PyTuple_Pack(1, native_to_java(base));
318+
bases = PyTuple_Pack(1, base);
255319
}
256320
} else {
257321
// we need to resolve pointers to Python classes
@@ -327,9 +391,13 @@ int PyType_Ready(PyTypeObject* cls) {
327391
}
328392
}
329393

330-
// initialize mro
394+
/* initialize mro */
331395
cls->tp_mro = UPCALL_CEXT_O(_jls_PyTruffle_Compute_Mro, cls);
332396

397+
/* Inherit special flags from dominant base */
398+
if (cls->tp_base != NULL)
399+
inherit_special(cls, cls->tp_base);
400+
333401
ADD_IF_MISSING(cls->tp_alloc, PyType_GenericAlloc);
334402
ADD_IF_MISSING(cls->tp_new, PyType_GenericNew);
335403

@@ -451,12 +519,10 @@ int PyType_Ready(PyTypeObject* cls) {
451519
// CPython doesn't do that in 'PyType_Ready' but we must because a native type can inherit
452520
// dynamic slots from a managed Python class. Since the managed Python class may be created
453521
// when the C API is not loaded, we need to do that later.
454-
// PyObject* inherited_slots_tuple = UPCALL_CEXT_O(_jls_PyTruffle_Type_Slots, native_to_java((PyObject*)javacls));
455-
// PyObject* inherited_slots_tuple = PyObject_GetAttrString(cls, "__slots__");
456-
// if(inherited_slots_tuple != NULL) {
457-
// PyTruffle_Debug(native_to_java(inherited_slots_tuple));
458-
// PyTruffle_Type_AddSlots(cls, inherited_slots_tuple);
459-
// }
522+
PyObject* inherited_slots_tuple = UPCALL_CEXT_O(_jls_PyTruffle_Type_Slots, native_to_java((PyObject*)cls));
523+
if(inherited_slots_tuple != NULL) {
524+
PyTruffle_Type_AddSlots(cls, inherited_slots_tuple);
525+
}
460526

461527
/* Link into each base class's list of subclasses */
462528
bases = cls->tp_bases;

0 commit comments

Comments
 (0)