@@ -178,34 +178,19 @@ void PyType_Modified(PyTypeObject* type) {
178178static void inherit_special (PyTypeObject * type , PyTypeObject * base ) {
179179
180180 /* Copying basicsize is connected to the GC flags */
181- unsigned long flags = PyTypeObject_tp_flags (type );
182- unsigned long base_flags = PyTypeObject_tp_flags (base );
181+ unsigned long flags = PyTypeObject_tp_flags (type );
182+ unsigned long base_flags = PyTypeObject_tp_flags (base );
183183 if (!(flags & Py_TPFLAGS_HAVE_GC ) &&
184184 (base_flags & Py_TPFLAGS_HAVE_GC ) &&
185185 (!PyTypeObject_tp_traverse (type ) && !PyTypeObject_tp_clear (type ))) {
186- flags |= Py_TPFLAGS_HAVE_GC ;
186+
187+ flags |= Py_TPFLAGS_HAVE_GC ;
187188 if (PyTypeObject_tp_traverse (type ) == NULL )
188189 set_PyTypeObject_tp_traverse (type , PyTypeObject_tp_traverse (base ));
189190 if (PyTypeObject_tp_clear (type ) == NULL )
190- set_PyTypeObject_tp_clear (type , PyTypeObject_tp_clear (base ));
191- }
192- {
193- /* The condition below could use some explanation.
194- It appears that tp_new is not inherited for static types
195- whose base class is 'object'; this seems to be a precaution
196- so that old extension types don't suddenly become
197- callable (object.__new__ wouldn't insure the invariants
198- that the extension type's own factory function ensures).
199- Heap types, of course, are under our control, so they do
200- inherit tp_new; static extension types that specify some
201- other built-in type as the default also
202- inherit object.__new__. */
203- if (base != & PyBaseObject_Type ||
204- (flags & Py_TPFLAGS_HEAPTYPE )) {
205- if (PyTypeObject_tp_new (type ) == NULL )
206- set_PyTypeObject_tp_new (type , PyTypeObject_tp_new (base )) ;
207- }
191+ set_PyTypeObject_tp_clear (type , PyTypeObject_tp_clear (base ));
208192 }
193+
209194 /* Copy other non-function slots */
210195
211196#undef COPYVAL
@@ -238,7 +223,7 @@ static void inherit_special(PyTypeObject *type, PyTypeObject *base) {
238223 flags |= _Py_TPFLAGS_MATCH_SELF ;
239224
240225 if (flags != PyTypeObject_tp_flags (type )) {
241- set_PyTypeObject_tp_flags (type , flags );
226+ set_PyTypeObject_tp_flags (type , flags );
242227 }
243228}
244229
@@ -372,13 +357,55 @@ static void add_slot(PyTypeObject* cls, PyObject* type_dict, char* name, void* m
372357 }
373358}
374359
375- #define ADD_MEMBER (__javacls__ , __tpdict__ , __mname__ , __mtype__ , __moffset__ , __mflags__ , __mdoc__ ) \
360+ #define ADD_MEMBER (__javacls__ , __tpdict__ , __mname__ , __mtype__ , __moffset__ , __mflags__ , __mdoc__ ) \
376361 add_member((__javacls__), (__tpdict__), (__mname__), (__mtype__), (__moffset__), (__mflags__), (__mdoc__))
377362
378363
379- #define ADD_GETSET (__javacls__ , __tpdict__ , __name__ , __getter__ , __setter__ , __doc__ , __closure__ ) \
364+ #define ADD_GETSET (__javacls__ , __tpdict__ , __name__ , __getter__ , __setter__ , __doc__ , __closure__ ) \
380365 add_getset((__javacls__), (__tpdict__), (__name__), (__getter__), (__setter__), (__doc__), (__closure__))
381366
367+ // Set tp_new and the "__new__" key in the type dictionary.
368+ // Use the Py_TPFLAGS_DISALLOW_INSTANTIATION flag.
369+ static int
370+ type_ready_set_new (PyTypeObject * type , PyObject * dict , PyTypeObject * base )
371+ {
372+ /* The condition below could use some explanation.
373+
374+ It appears that tp_new is not inherited for static types whose base
375+ class is 'object'; this seems to be a precaution so that old extension
376+ types don't suddenly become callable (object.__new__ wouldn't insure the
377+ invariants that the extension type's own factory function ensures).
378+
379+ Heap types, of course, are under our control, so they do inherit tp_new;
380+ static extension types that specify some other built-in type as the
381+ default also inherit object.__new__. */
382+ newfunc tp_new = PyTypeObject_tp_new (type );
383+ unsigned long tp_flags = PyTypeObject_tp_flags (type );
384+ if (tp_new == NULL
385+ && base == & PyBaseObject_Type
386+ && !(tp_flags & Py_TPFLAGS_HEAPTYPE ))
387+ {
388+ set_PyTypeObject_tp_flags (type , tp_flags |= Py_TPFLAGS_DISALLOW_INSTANTIATION );
389+ }
390+
391+ if (!(type -> tp_flags & Py_TPFLAGS_DISALLOW_INSTANTIATION )) {
392+ if (tp_new != NULL ) {
393+ // If "__new__" key does not exists in the type dictionary,
394+ // set it to tp_new_wrapper().
395+ add_slot (type , dict , "__new__" , tp_new , METH_KEYWORDS | METH_VARARGS , JWRAPPER_NEW , NULL );
396+ }
397+ else {
398+ // tp_new is NULL: inherit tp_new from base
399+ set_PyTypeObject_tp_new (type , PyTypeObject_tp_new (base )) ;
400+ }
401+ }
402+ else {
403+ // Py_TPFLAGS_DISALLOW_INSTANTIATION sets tp_new to NULL
404+ // not supported yet
405+ // set_PyTypeObject_tp_new(type, NULL) ;
406+ }
407+ return 0 ;
408+ }
382409
383410int PyType_Ready (PyTypeObject * cls ) {
384411#define RETURN_ERROR (__type__ ) \
@@ -388,7 +415,7 @@ int PyType_Ready(PyTypeObject* cls) {
388415 return -1; \
389416 } while(0)
390417
391- #define ADD_IF_MISSING (attr , def ) if (!(attr)) { attr = def ; }
418+ #define ADD_IF_MISSING (OBJ , SLOT , VAL ) if (!(PyTypeObject_##SLOT(OBJ))) { set_PyTypeObject_##SLOT((OBJ), (VAL)) ; }
392419#define ADD_SLOT_CONV (__name__ , __meth__ , __flags__ , __signature__ ) add_slot(cls, dict, (__name__), (__meth__), (__flags__), (__signature__), NULL)
393420
394421 Py_ssize_t n ;
@@ -507,9 +534,8 @@ int PyType_Ready(PyTypeObject* cls) {
507534 PyObject * mro = GraalPyTruffle_Compute_Mro (cls , truffleString (cls -> tp_name ));
508535 set_PyTypeObject_tp_mro (cls , mro );
509536
510- /* set new and alloc */
511- ADD_IF_MISSING (cls -> tp_alloc , PyType_GenericAlloc );
512- ADD_IF_MISSING (cls -> tp_new , PyType_GenericNew );
537+ /* set new */
538+ type_ready_set_new (cls , dict , base );
513539
514540 /* fill dict */
515541 // add special methods defined directly on the type structs
@@ -550,7 +576,9 @@ int PyType_Ready(PyTypeObject* cls) {
550576 ADD_SLOT_CONV ("__set__" , cls -> tp_descr_set , -3 , JWRAPPER_DESCR_SET );
551577 ADD_SLOT_CONV ("__init__" , cls -> tp_init , METH_KEYWORDS | METH_VARARGS , JWRAPPER_INITPROC );
552578 ADD_SLOT_CONV ("__alloc__" , cls -> tp_alloc , -2 , JWRAPPER_ALLOC );
553- ADD_SLOT_CONV ("__new__" , cls -> tp_new , METH_KEYWORDS | METH_VARARGS , JWRAPPER_NEW );
579+ /* Note: '__new__' was added here previously but we don't do it similar to CPython.
580+ They also skip it because the appropriate 'slotdef' doesn't have a wrapper.
581+ Adding '__new__' is done by function 'type_ready_set_new'. */
554582 ADD_SLOT_CONV ("__free__" , cls -> tp_free , -1 , JWRAPPER_DIRECT );
555583 ADD_SLOT_CONV ("__del__" , cls -> tp_del , -1 , JWRAPPER_DIRECT );
556584 ADD_SLOT_CONV ("__finalize__" , cls -> tp_finalize , -1 , JWRAPPER_DIRECT );
@@ -655,6 +683,9 @@ int PyType_Ready(PyTypeObject* cls) {
655683 inherit_slots (cls , (PyTypeObject * )b );
656684 }
657685
686+ ADD_IF_MISSING (cls , tp_alloc , PyType_GenericAlloc );
687+ ADD_IF_MISSING (cls , tp_new , PyType_GenericNew );
688+
658689 // process inherited slots
659690 // CPython doesn't do that in 'PyType_Ready' but we must because a native type can inherit
660691 // dynamic slots from a managed Python class. Since the managed Python class may be created
0 commit comments