@@ -447,6 +447,23 @@ gc_visit_thread_stacks(PyInterpreterState *interp)
447
447
_Py_FOR_EACH_TSTATE_END (interp );
448
448
}
449
449
450
+ // Untrack objects that can never create reference cycles.
451
+ // Return true if the object was untracked.
452
+ static bool
453
+ gc_maybe_untrack (PyObject * op )
454
+ {
455
+ // Currently we only check for tuples containing only non-GC objects. In
456
+ // theory we could check other immutable objects that contain references
457
+ // to non-GC objects.
458
+ if (PyTuple_CheckExact (op )) {
459
+ _PyTuple_MaybeUntrack (op );
460
+ if (!_PyObject_GC_IS_TRACKED (op )) {
461
+ return true;
462
+ }
463
+ }
464
+ return false;
465
+ }
466
+
450
467
#ifdef GC_ENABLE_MARK_ALIVE
451
468
static int
452
469
mark_alive_stack_push (PyObject * op , _PyObjectStack * stack )
@@ -460,16 +477,12 @@ mark_alive_stack_push(PyObject *op, _PyObjectStack *stack)
460
477
if (gc_is_alive (op )) {
461
478
return 0 ; // already visited this object
462
479
}
463
- if (!_PyObject_HasDeferredRefcount (op )) {
464
- // Untrack objects that can never create reference cycles. Currently
465
- // we only check for tuples containing only non-GC objects.
466
- if (PyTuple_CheckExact (op )) {
467
- _PyTuple_MaybeUntrack (op );
468
- if (!_PyObject_GC_IS_TRACKED (op )) {
469
- return 0 ;
470
- }
471
- }
480
+ if (gc_maybe_untrack (op )) {
481
+ return 0 ; // was untracked, don't visit it
472
482
}
483
+
484
+ // Need to call tp_traverse on this object. Add to stack and mark it
485
+ // alive so we don't re-visit it a second time.
473
486
gc_set_alive (op );
474
487
if (_PyObjectStack_Push (stack , op ) < 0 ) {
475
488
_PyObjectStack_Clear (stack );
@@ -632,14 +645,9 @@ update_refs(const mi_heap_t *heap, const mi_heap_area_t *area,
632
645
_PyObject_ASSERT (op , refcount >= 0 );
633
646
634
647
if (refcount > 0 && !_PyObject_HasDeferredRefcount (op )) {
635
- // Untrack tuples and dicts as necessary in this pass, but not objects
636
- // with zero refcount, which we will want to collect.
637
- if (PyTuple_CheckExact (op )) {
638
- _PyTuple_MaybeUntrack (op );
639
- if (!_PyObject_GC_IS_TRACKED (op )) {
640
- gc_restore_refs (op );
641
- return true;
642
- }
648
+ if (gc_maybe_untrack (op )) {
649
+ gc_restore_refs (op );
650
+ return true;
643
651
}
644
652
}
645
653
0 commit comments