@@ -308,17 +308,18 @@ disable_deferred_refcounting(PyObject *op)
308308 // should also be disabled when we turn off deferred refcounting.
309309 _PyObject_DisablePerThreadRefcounting (op );
310310 }
311-
312- // Generators and frame objects may contain deferred references to other
313- // objects. If the pointed-to objects are part of cyclic trash, we may
314- // have disabled deferred refcounting on them and need to ensure that we
315- // use strong references, in case the generator or frame object is
316- // resurrected by a finalizer.
317- if (PyGen_CheckExact (op ) || PyCoro_CheckExact (op ) || PyAsyncGen_CheckExact (op )) {
318- frame_disable_deferred_refcounting (& ((PyGenObject * )op )-> gi_iframe );
319- }
320- else if (PyFrame_Check (op )) {
321- frame_disable_deferred_refcounting (((PyFrameObject * )op )-> f_frame );
311+ if (_PyObject_GC_IS_TRACKED (op )) {
312+ // Generators and frame objects may contain deferred references to other
313+ // objects. If the pointed-to objects are part of cyclic trash, we may
314+ // have disabled deferred refcounting on them and need to ensure that we
315+ // use strong references, in case the generator or frame object is
316+ // resurrected by a finalizer.
317+ if (PyGen_CheckExact (op ) || PyCoro_CheckExact (op ) || PyAsyncGen_CheckExact (op )) {
318+ frame_disable_deferred_refcounting (& ((PyGenObject * )op )-> gi_iframe );
319+ }
320+ else if (PyFrame_Check (op )) {
321+ frame_disable_deferred_refcounting (((PyFrameObject * )op )-> f_frame );
322+ }
322323 }
323324}
324325
@@ -1240,25 +1241,16 @@ scan_heap_visitor(const mi_heap_t *heap, const mi_heap_area_t *area,
12401241 return true;
12411242 }
12421243
1243- if (state -> reason == _Py_GC_REASON_SHUTDOWN ) {
1244- // Disable deferred refcounting for reachable objects as well during
1245- // interpreter shutdown. This ensures that these objects are collected
1246- // immediately when their last reference is removed.
1247- disable_deferred_refcounting (op );
1248- }
1249-
12501244 // object is reachable, restore `ob_tid`; we're done with these objects
12511245 gc_restore_tid (op );
12521246 gc_clear_alive (op );
12531247 return true;
12541248}
12551249
1256- // Disables deferred refcounting for all GC objects during interpreter
1257- // shutdown. The scan_heap_visitor() skips untracked objects but those
1258- // could have deferred refcounts enabled as well. This is separated
1259- // into a separate scan pass since we only need to do it at shutdown.
1260- // Note that untracked GC objects are typically exact tuples but could
1261- // also be GC objects that were never tracked or manually untracked.
1250+ // Disable deferred refcounting for reachable objects during interpreter
1251+ // shutdown. This ensures that these objects are collected immediately when
1252+ // their last reference is removed. This needs to consider both tracked and
1253+ // untracked GC objects, since either might have deferred refcounts enabled.
12621254static bool
12631255scan_heap_disable_deferred (const mi_heap_t * heap , const mi_heap_area_t * area ,
12641256 void * block , size_t block_size , void * args )
@@ -1267,7 +1259,7 @@ scan_heap_disable_deferred(const mi_heap_t *heap, const mi_heap_area_t *area,
12671259 if (op == NULL ) {
12681260 return true;
12691261 }
1270- if (!_Py_IsImmortal (op ) && _PyObject_HasDeferredRefcount ( op ) ) {
1262+ if (!_Py_IsImmortal (op )) {
12711263 disable_deferred_refcounting (op );
12721264 }
12731265 return true;
0 commit comments