Skip to content

Commit 01d22fc

Browse files
committed
wip: add helper gc_maybe_untrack()
Reduces duplicate code.
1 parent 9c969b4 commit 01d22fc

File tree

1 file changed

+25
-17
lines changed

1 file changed

+25
-17
lines changed

Python/gc_free_threading.c

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,23 @@ gc_visit_thread_stacks(PyInterpreterState *interp)
447447
_Py_FOR_EACH_TSTATE_END(interp);
448448
}
449449

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+
450467
#ifdef GC_ENABLE_MARK_ALIVE
451468
static int
452469
mark_alive_stack_push(PyObject *op, _PyObjectStack *stack)
@@ -460,16 +477,12 @@ mark_alive_stack_push(PyObject *op, _PyObjectStack *stack)
460477
if (gc_is_alive(op)) {
461478
return 0; // already visited this object
462479
}
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
472482
}
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.
473486
gc_set_alive(op);
474487
if (_PyObjectStack_Push(stack, op) < 0) {
475488
_PyObjectStack_Clear(stack);
@@ -632,14 +645,9 @@ update_refs(const mi_heap_t *heap, const mi_heap_area_t *area,
632645
_PyObject_ASSERT(op, refcount >= 0);
633646

634647
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;
643651
}
644652
}
645653

0 commit comments

Comments
 (0)