@@ -54,37 +54,71 @@ _PyObject_CheckConsistency(PyObject *op, int check_content)
5454
5555
5656#ifdef Py_REF_DEBUG
57+ /* We keep the legacy symbol around for backward compatibility. */
5758Py_ssize_t _Py_RefTotal ;
5859
60+ static inline Py_ssize_t
61+ get_legacy_reftotal (void )
62+ {
63+ return _Py_RefTotal ;
64+ }
65+ #endif
66+
67+ #ifdef Py_REF_DEBUG
68+
69+ # define REFTOTAL (runtime ) \
70+ (runtime)->object_state.reftotal
71+
72+ static inline void
73+ reftotal_increment (_PyRuntimeState * runtime )
74+ {
75+ REFTOTAL (runtime )++ ;
76+ }
77+
5978static inline void
60- reftotal_increment ( void )
79+ reftotal_decrement ( _PyRuntimeState * runtime )
6180{
62- _Py_RefTotal ++ ;
81+ REFTOTAL ( runtime ) -- ;
6382}
6483
6584static inline void
66- reftotal_decrement ( void )
85+ reftotal_add ( _PyRuntimeState * runtime , Py_ssize_t n )
6786{
68- _Py_RefTotal -- ;
87+ REFTOTAL ( runtime ) += n ;
6988}
7089
90+ static inline Py_ssize_t get_global_reftotal (_PyRuntimeState * );
91+
92+ /* We preserve the number of refs leaked during runtime finalization,
93+ so they can be reported if the runtime is initialized again. */
94+ // XXX We don't lose any information by dropping this,
95+ // so we should consider doing so.
96+ static Py_ssize_t last_final_reftotal = 0 ;
97+
7198void
72- _Py_AddRefTotal ( Py_ssize_t n )
99+ _Py_FinalizeRefTotal ( _PyRuntimeState * runtime )
73100{
74- _Py_RefTotal += n ;
101+ last_final_reftotal = get_global_reftotal (runtime );
102+ REFTOTAL (runtime ) = 0 ;
75103}
76104
77- Py_ssize_t
78- _Py_GetRefTotal ( void )
105+ static inline Py_ssize_t
106+ get_global_reftotal ( _PyRuntimeState * runtime )
79107{
80- return _Py_RefTotal ;
108+ /* For an update from _Py_RefTotal first. */
109+ Py_ssize_t legacy = get_legacy_reftotal ();
110+ return REFTOTAL (runtime ) + legacy + last_final_reftotal ;
81111}
82112
113+ #undef REFTOTAL
114+
83115void
84116_PyDebug_PrintTotalRefs (void ) {
117+ _PyRuntimeState * runtime = & _PyRuntime ;
85118 fprintf (stderr ,
86119 "[%zd refs, %zd blocks]\n" ,
87- _Py_GetRefTotal (), _Py_GetAllocatedBlocks ());
120+ get_global_reftotal (runtime ), _Py_GetAllocatedBlocks ());
121+ /* It may be helpful to also print the "legacy" reftotal separately. */
88122}
89123#endif /* Py_REF_DEBUG */
90124
@@ -139,30 +173,50 @@ _Py_NegativeRefcount(const char *filename, int lineno, PyObject *op)
139173 filename , lineno , __func__ );
140174}
141175
142- /* This is exposed strictly for use in Py_INCREF(). */
143- PyAPI_FUNC ( void )
176+ /* This is used strictly by Py_INCREF(). */
177+ void
144178_Py_IncRefTotal_DO_NOT_USE_THIS (void )
145179{
146- reftotal_increment ();
180+ reftotal_increment (& _PyRuntime );
147181}
148182
149- /* This is exposed strictly for use in Py_DECREF(). */
150- PyAPI_FUNC ( void )
183+ /* This is used strictly by Py_DECREF(). */
184+ void
151185_Py_DecRefTotal_DO_NOT_USE_THIS (void )
152186{
153- reftotal_decrement ();
187+ reftotal_decrement (& _PyRuntime );
154188}
155189
156190void
157191_Py_IncRefTotal (void )
158192{
159- reftotal_increment ();
193+ reftotal_increment (& _PyRuntime );
160194}
161195
162196void
163197_Py_DecRefTotal (void )
164198{
165- reftotal_decrement ();
199+ reftotal_decrement (& _PyRuntime );
200+ }
201+
202+ void
203+ _Py_AddRefTotal (Py_ssize_t n )
204+ {
205+ reftotal_add (& _PyRuntime , n );
206+ }
207+
208+ /* This includes the legacy total
209+ and any carried over from the last runtime init/fini cycle. */
210+ Py_ssize_t
211+ _Py_GetGlobalRefTotal (void )
212+ {
213+ return get_global_reftotal (& _PyRuntime );
214+ }
215+
216+ Py_ssize_t
217+ _Py_GetLegacyRefTotal (void )
218+ {
219+ return get_legacy_reftotal ();
166220}
167221
168222#endif /* Py_REF_DEBUG */
@@ -182,21 +236,18 @@ Py_DecRef(PyObject *o)
182236void
183237_Py_IncRef (PyObject * o )
184238{
185- #ifdef Py_REF_DEBUG
186- reftotal_increment ();
187- #endif
188239 Py_INCREF (o );
189240}
190241
191242void
192243_Py_DecRef (PyObject * o )
193244{
194- #ifdef Py_REF_DEBUG
195- reftotal_decrement ();
196- #endif
197245 Py_DECREF (o );
198246}
199247
248+
249+ /**************************************/
250+
200251PyObject *
201252PyObject_Init (PyObject * op , PyTypeObject * tp )
202253{
@@ -2077,7 +2128,7 @@ void
20772128_Py_NewReference (PyObject * op )
20782129{
20792130#ifdef Py_REF_DEBUG
2080- reftotal_increment ();
2131+ reftotal_increment (& _PyRuntime );
20812132#endif
20822133 new_reference (op );
20832134}
0 commit comments