@@ -168,6 +168,70 @@ static PyObject* wrap_reverse_binop(binaryfunc f, PyObject* a, PyObject* b) {
168
168
return f (b , a );
169
169
}
170
170
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
+
171
235
// TODO(fa): there should actually be 'native_to_java' just in case 'javacls' goes to native in between
172
236
// TODO support member flags other than READONLY
173
237
UPCALL_ID (AddMember );
@@ -251,7 +315,7 @@ int PyType_Ready(PyTypeObject* cls) {
251
315
if (base == NULL ) {
252
316
bases = PyTuple_New (0 );
253
317
} else {
254
- bases = PyTuple_Pack (1 , native_to_java ( base ) );
318
+ bases = PyTuple_Pack (1 , base );
255
319
}
256
320
} else {
257
321
// we need to resolve pointers to Python classes
@@ -327,9 +391,13 @@ int PyType_Ready(PyTypeObject* cls) {
327
391
}
328
392
}
329
393
330
- // initialize mro
394
+ /* initialize mro */
331
395
cls -> tp_mro = UPCALL_CEXT_O (_jls_PyTruffle_Compute_Mro , cls );
332
396
397
+ /* Inherit special flags from dominant base */
398
+ if (cls -> tp_base != NULL )
399
+ inherit_special (cls , cls -> tp_base );
400
+
333
401
ADD_IF_MISSING (cls -> tp_alloc , PyType_GenericAlloc );
334
402
ADD_IF_MISSING (cls -> tp_new , PyType_GenericNew );
335
403
@@ -451,12 +519,10 @@ int PyType_Ready(PyTypeObject* cls) {
451
519
// CPython doesn't do that in 'PyType_Ready' but we must because a native type can inherit
452
520
// dynamic slots from a managed Python class. Since the managed Python class may be created
453
521
// 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
+ }
460
526
461
527
/* Link into each base class's list of subclasses */
462
528
bases = cls -> tp_bases ;
0 commit comments