@@ -178,34 +178,19 @@ void PyType_Modified(PyTypeObject* type) {
178
178
static void inherit_special (PyTypeObject * type , PyTypeObject * base ) {
179
179
180
180
/* 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 );
183
183
if (!(flags & Py_TPFLAGS_HAVE_GC ) &&
184
184
(base_flags & Py_TPFLAGS_HAVE_GC ) &&
185
185
(!PyTypeObject_tp_traverse (type ) && !PyTypeObject_tp_clear (type ))) {
186
- flags |= Py_TPFLAGS_HAVE_GC ;
186
+
187
+ flags |= Py_TPFLAGS_HAVE_GC ;
187
188
if (PyTypeObject_tp_traverse (type ) == NULL )
188
189
set_PyTypeObject_tp_traverse (type , PyTypeObject_tp_traverse (base ));
189
190
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 ));
208
192
}
193
+
209
194
/* Copy other non-function slots */
210
195
211
196
#undef COPYVAL
@@ -238,7 +223,7 @@ static void inherit_special(PyTypeObject *type, PyTypeObject *base) {
238
223
flags |= _Py_TPFLAGS_MATCH_SELF ;
239
224
240
225
if (flags != PyTypeObject_tp_flags (type )) {
241
- set_PyTypeObject_tp_flags (type , flags );
226
+ set_PyTypeObject_tp_flags (type , flags );
242
227
}
243
228
}
244
229
@@ -372,13 +357,55 @@ static void add_slot(PyTypeObject* cls, PyObject* type_dict, char* name, void* m
372
357
}
373
358
}
374
359
375
- #define ADD_MEMBER (__javacls__ , __tpdict__ , __mname__ , __mtype__ , __moffset__ , __mflags__ , __mdoc__ ) \
360
+ #define ADD_MEMBER (__javacls__ , __tpdict__ , __mname__ , __mtype__ , __moffset__ , __mflags__ , __mdoc__ ) \
376
361
add_member((__javacls__), (__tpdict__), (__mname__), (__mtype__), (__moffset__), (__mflags__), (__mdoc__))
377
362
378
363
379
- #define ADD_GETSET (__javacls__ , __tpdict__ , __name__ , __getter__ , __setter__ , __doc__ , __closure__ ) \
364
+ #define ADD_GETSET (__javacls__ , __tpdict__ , __name__ , __getter__ , __setter__ , __doc__ , __closure__ ) \
380
365
add_getset((__javacls__), (__tpdict__), (__name__), (__getter__), (__setter__), (__doc__), (__closure__))
381
366
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
+ }
382
409
383
410
int PyType_Ready (PyTypeObject * cls ) {
384
411
#define RETURN_ERROR (__type__ ) \
@@ -388,7 +415,7 @@ int PyType_Ready(PyTypeObject* cls) {
388
415
return -1; \
389
416
} while(0)
390
417
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)) ; }
392
419
#define ADD_SLOT_CONV (__name__ , __meth__ , __flags__ , __signature__ ) add_slot(cls, dict, (__name__), (__meth__), (__flags__), (__signature__), NULL)
393
420
394
421
Py_ssize_t n ;
@@ -507,9 +534,8 @@ int PyType_Ready(PyTypeObject* cls) {
507
534
PyObject * mro = GraalPyTruffle_Compute_Mro (cls , truffleString (cls -> tp_name ));
508
535
set_PyTypeObject_tp_mro (cls , mro );
509
536
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 );
513
539
514
540
/* fill dict */
515
541
// add special methods defined directly on the type structs
@@ -550,7 +576,9 @@ int PyType_Ready(PyTypeObject* cls) {
550
576
ADD_SLOT_CONV ("__set__" , cls -> tp_descr_set , -3 , JWRAPPER_DESCR_SET );
551
577
ADD_SLOT_CONV ("__init__" , cls -> tp_init , METH_KEYWORDS | METH_VARARGS , JWRAPPER_INITPROC );
552
578
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'. */
554
582
ADD_SLOT_CONV ("__free__" , cls -> tp_free , -1 , JWRAPPER_DIRECT );
555
583
ADD_SLOT_CONV ("__del__" , cls -> tp_del , -1 , JWRAPPER_DIRECT );
556
584
ADD_SLOT_CONV ("__finalize__" , cls -> tp_finalize , -1 , JWRAPPER_DIRECT );
@@ -655,6 +683,9 @@ int PyType_Ready(PyTypeObject* cls) {
655
683
inherit_slots (cls , (PyTypeObject * )b );
656
684
}
657
685
686
+ ADD_IF_MISSING (cls , tp_alloc , PyType_GenericAlloc );
687
+ ADD_IF_MISSING (cls , tp_new , PyType_GenericNew );
688
+
658
689
// process inherited slots
659
690
// CPython doesn't do that in 'PyType_Ready' but we must because a native type can inherit
660
691
// dynamic slots from a managed Python class. Since the managed Python class may be created
0 commit comments