@@ -26,7 +26,7 @@ typedef struct _functools_state {
2626 /* this object is used delimit args and keywords in the cache keys */
2727 PyObject * kwd_mark ;
2828 PyTypeObject * placeholder_type ;
29- PyObject * placeholder ;
29+ PyObject * placeholder ; // strong reference (singleton)
3030 PyTypeObject * partial_type ;
3131 PyTypeObject * keyobject_type ;
3232 PyTypeObject * lru_list_elem_type ;
@@ -76,13 +76,12 @@ static PyMethodDef placeholder_methods[] = {
7676};
7777
7878static void
79- placeholder_dealloc (PyObject * placeholder )
79+ placeholder_dealloc (PyObject * self )
8080{
81- /* This should never get called, but we also don't want to SEGV if
82- * we accidentally decref Placeholder out of existence. Instead,
83- * since Placeholder is an immortal object, re-set the reference count.
84- */
85- _Py_SetImmortal (placeholder );
81+ PyObject_GC_UnTrack (self );
82+ PyTypeObject * tp = Py_TYPE (self );
83+ tp -> tp_free ((PyObject * )self );
84+ Py_DECREF (tp );
8685}
8786
8887static PyObject *
@@ -93,10 +92,26 @@ placeholder_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
9392 return NULL ;
9493 }
9594 _functools_state * state = get_functools_state_by_type (type );
95+ if (state -> placeholder != NULL ) {
96+ return Py_NewRef (state -> placeholder );
97+ }
98+
99+ PyObject * placeholder = PyType_GenericNew (type , NULL , NULL );
100+ if (placeholder == NULL ) {
101+ return NULL ;
102+ }
103+
96104 if (state -> placeholder == NULL ) {
97- state -> placeholder = PyType_GenericNew ( type , NULL , NULL );
105+ state -> placeholder = Py_NewRef ( placeholder );
98106 }
99- return state -> placeholder ;
107+ return placeholder ;
108+ }
109+
110+ static int
111+ placeholder_traverse (PyObject * self , visitproc visit , void * arg )
112+ {
113+ Py_VISIT (Py_TYPE (self ));
114+ return 0 ;
100115}
101116
102117static PyType_Slot placeholder_type_slots [] = {
@@ -105,13 +120,14 @@ static PyType_Slot placeholder_type_slots[] = {
105120 {Py_tp_doc , (void * )placeholder_doc },
106121 {Py_tp_methods , placeholder_methods },
107122 {Py_tp_new , placeholder_new },
123+ {Py_tp_traverse , placeholder_traverse },
108124 {0 , 0 }
109125};
110126
111127static PyType_Spec placeholder_type_spec = {
112128 .name = "functools._PlaceholderType" ,
113129 .basicsize = sizeof (placeholderobject ),
114- .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE ,
130+ .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC ,
115131 .slots = placeholder_type_slots
116132};
117133
@@ -1717,13 +1733,17 @@ _functools_exec(PyObject *module)
17171733 if (PyModule_AddType (module , state -> placeholder_type ) < 0 ) {
17181734 return -1 ;
17191735 }
1720- state -> placeholder = PyObject_CallNoArgs ((PyObject * )state -> placeholder_type );
1721- if (state -> placeholder == NULL ) {
1736+
1737+ PyObject * placeholder = PyObject_CallNoArgs ((PyObject * )state -> placeholder_type );
1738+ if (placeholder == NULL ) {
17221739 return -1 ;
17231740 }
1724- if (PyModule_AddObject (module , "Placeholder" , state -> placeholder ) < 0 ) {
1741+ if (PyModule_AddObjectRef (module , "Placeholder" , placeholder ) < 0 ) {
1742+ Py_DECREF (placeholder );
17251743 return -1 ;
17261744 }
1745+ Py_DECREF (placeholder );
1746+
17271747 state -> partial_type = (PyTypeObject * )PyType_FromModuleAndSpec (module ,
17281748 & partial_type_spec , NULL );
17291749 if (state -> partial_type == NULL ) {
@@ -1769,6 +1789,7 @@ _functools_traverse(PyObject *module, visitproc visit, void *arg)
17691789 _functools_state * state = get_functools_state (module );
17701790 Py_VISIT (state -> kwd_mark );
17711791 Py_VISIT (state -> placeholder_type );
1792+ Py_VISIT (state -> placeholder );
17721793 Py_VISIT (state -> partial_type );
17731794 Py_VISIT (state -> keyobject_type );
17741795 Py_VISIT (state -> lru_list_elem_type );
@@ -1781,6 +1802,7 @@ _functools_clear(PyObject *module)
17811802 _functools_state * state = get_functools_state (module );
17821803 Py_CLEAR (state -> kwd_mark );
17831804 Py_CLEAR (state -> placeholder_type );
1805+ Py_CLEAR (state -> placeholder );
17841806 Py_CLEAR (state -> partial_type );
17851807 Py_CLEAR (state -> keyobject_type );
17861808 Py_CLEAR (state -> lru_list_elem_type );
0 commit comments