@@ -3343,7 +3343,7 @@ test_gc_visit_objects_basic(PyObject *Py_UNUSED(self),
33433343    }
33443344    state .target  =  obj ;
33453345    state .found  =  0 ;
3346-      
3346+ 
33473347    PyUnstable_GC_VisitObjects (gc_visit_callback_basic , & state );
33483348    Py_DECREF (obj );
33493349    if  (!state .found ) {
@@ -3380,6 +3380,94 @@ test_gc_visit_objects_exit_early(PyObject *Py_UNUSED(self),
33803380    Py_RETURN_NONE ;
33813381}
33823382
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+ };
33833471
33843472struct  atexit_data  {
33853473    int  called ;
@@ -4103,6 +4191,11 @@ PyInit__testcapi(void)
41034191    Py_INCREF (& MethStatic_Type );
41044192    PyModule_AddObject (m , "MethStatic" , (PyObject  * )& MethStatic_Type );
41054193
4194+     if  (PyType_Ready (& ObjExtraData_Type ) <  0 )
4195+         return  NULL ;
4196+     Py_INCREF (& ObjExtraData_Type );
4197+     PyModule_AddObject (m , "ObjExtraData" , (PyObject  * )& ObjExtraData_Type );
4198+ 
41064199    PyModule_AddObject (m , "CHAR_MAX" , PyLong_FromLong (CHAR_MAX ));
41074200    PyModule_AddObject (m , "CHAR_MIN" , PyLong_FromLong (CHAR_MIN ));
41084201    PyModule_AddObject (m , "UCHAR_MAX" , PyLong_FromLong (UCHAR_MAX ));
0 commit comments