@@ -3343,7 +3343,7 @@ test_gc_visit_objects_basic(PyObject *Py_UNUSED(self),
3343
3343
}
3344
3344
state .target = obj ;
3345
3345
state .found = 0 ;
3346
-
3346
+
3347
3347
PyUnstable_GC_VisitObjects (gc_visit_callback_basic , & state );
3348
3348
Py_DECREF (obj );
3349
3349
if (!state .found ) {
@@ -3380,6 +3380,94 @@ test_gc_visit_objects_exit_early(PyObject *Py_UNUSED(self),
3380
3380
Py_RETURN_NONE ;
3381
3381
}
3382
3382
3383
+ typedef struct {
3384
+ PyObject_HEAD
3385
+ } ObjExtraData ;
3386
+
3387
+ static PyObject *
3388
+ obj_extra_data_new (PyTypeObject * type , PyObject * args , PyObject * kwds )
3389
+ {
3390
+ size_t extra_size = sizeof (PyObject * );
3391
+ PyObject * obj = PyUnstable_Object_GC_NewWithExtraData (type , extra_size );
3392
+ if (obj == NULL )
3393
+ return PyErr_NoMemory ();
3394
+ memset (obj , '\0' , type -> tp_basicsize + extra_size );
3395
+ PyObject_Init (obj , type );
3396
+ PyObject_GC_Track (obj );
3397
+ return obj ;
3398
+ }
3399
+
3400
+ static PyObject * *
3401
+ obj_extra_data_get_extra_storage (PyObject * self )
3402
+ {
3403
+ return (PyObject * * )((char * )self + Py_TYPE (self )-> tp_basicsize );
3404
+ }
3405
+
3406
+ static PyObject *
3407
+ obj_extra_data_get (PyObject * self , void * Py_UNUSED (ignored ))
3408
+ {
3409
+ PyObject * * extra_storage = obj_extra_data_get_extra_storage (self );
3410
+ PyObject * value = * extra_storage ;
3411
+ if (!value )
3412
+ Py_RETURN_NONE ;
3413
+ Py_INCREF (value );
3414
+ return value ;
3415
+ }
3416
+
3417
+ static int
3418
+ obj_extra_data_set (PyObject * self , PyObject * newval , void * Py_UNUSED (ignored ))
3419
+ {
3420
+ PyObject * * extra_storage = obj_extra_data_get_extra_storage (self );
3421
+ Py_CLEAR (* extra_storage );
3422
+ if (newval ) {
3423
+ Py_INCREF (newval );
3424
+ * extra_storage = newval ;
3425
+ }
3426
+ return 0 ;
3427
+ }
3428
+
3429
+ static PyGetSetDef obj_extra_data_getset [] = {
3430
+ {"extra" , (getter )obj_extra_data_get , (setter )obj_extra_data_set , NULL },
3431
+ };
3432
+
3433
+ static int
3434
+ obj_extra_data_traverse (PyObject * self , visitproc visit , void * arg )
3435
+ {
3436
+ PyObject * * extra_storage = obj_extra_data_get_extra_storage (self );
3437
+ PyObject * value = * extra_storage ;
3438
+ Py_VISIT (value );
3439
+ return 0 ;
3440
+ }
3441
+
3442
+ static int
3443
+ obj_extra_data_clear (PyObject * self )
3444
+ {
3445
+ PyObject * * extra_storage = obj_extra_data_get_extra_storage (self );
3446
+ Py_CLEAR (* extra_storage );
3447
+ return 0 ;
3448
+ }
3449
+
3450
+ static void
3451
+ obj_extra_data_dealloc (PyObject * self )
3452
+ {
3453
+ PyObject_GC_UnTrack (self );
3454
+ obj_extra_data_clear (self );
3455
+ Py_TYPE (self )-> tp_free (self );
3456
+ }
3457
+
3458
+ static PyTypeObject ObjExtraData_Type = {
3459
+ PyVarObject_HEAD_INIT (NULL , 0 )
3460
+ "obj_with_extra_data" ,
3461
+ sizeof (ObjExtraData ),
3462
+ 0 ,
3463
+ .tp_getset = obj_extra_data_getset ,
3464
+ .tp_dealloc = obj_extra_data_dealloc ,
3465
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC ,
3466
+ .tp_traverse = (traverseproc )obj_extra_data_traverse ,
3467
+ .tp_clear = (inquiry )obj_extra_data_clear ,
3468
+ .tp_new = obj_extra_data_new ,
3469
+ .tp_free = PyObject_GC_Del ,
3470
+ };
3383
3471
3384
3472
struct atexit_data {
3385
3473
int called ;
@@ -4103,6 +4191,11 @@ PyInit__testcapi(void)
4103
4191
Py_INCREF (& MethStatic_Type );
4104
4192
PyModule_AddObject (m , "MethStatic" , (PyObject * )& MethStatic_Type );
4105
4193
4194
+ if (PyType_Ready (& ObjExtraData_Type ) < 0 )
4195
+ return NULL ;
4196
+ Py_INCREF (& ObjExtraData_Type );
4197
+ PyModule_AddObject (m , "ObjExtraData" , (PyObject * )& ObjExtraData_Type );
4198
+
4106
4199
PyModule_AddObject (m , "CHAR_MAX" , PyLong_FromLong (CHAR_MAX ));
4107
4200
PyModule_AddObject (m , "CHAR_MIN" , PyLong_FromLong (CHAR_MIN ));
4108
4201
PyModule_AddObject (m , "UCHAR_MAX" , PyLong_FromLong (UCHAR_MAX ));
0 commit comments