Skip to content

Commit eea894c

Browse files
committed
wip: mark stack refs as alive
1 parent f509a13 commit eea894c

File tree

1 file changed

+51
-15
lines changed

1 file changed

+51
-15
lines changed

Python/gc_free_threading.c

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,56 @@ gc_visit_thread_stacks(PyInterpreterState *interp)
584584
_Py_FOR_EACH_TSTATE_END(interp);
585585
}
586586

587+
static bool
588+
mark_stack_push(_PyObjectStack *stack, PyObject *op)
589+
{
590+
if (op == NULL) {
591+
return true;
592+
}
593+
assert(!gc_is_alive(op));
594+
gc_set_alive(op);
595+
//gc_maybe_merge_refcount(op);
596+
if (_PyObjectStack_Push(stack, op) < 0) {
597+
return false;
598+
}
599+
return true;
600+
}
601+
602+
static inline void
603+
gc_visit_stackref_mark_alive(_PyObjectStack *stack, _PyStackRef stackref)
604+
{
605+
// Note: we MUST check that it is deferred before checking the rest.
606+
// Otherwise we might read into invalid memory due to non-deferred references
607+
// being dead already.
608+
if (PyStackRef_IsDeferred(stackref) && !PyStackRef_IsNull(stackref)) {
609+
PyObject *obj = PyStackRef_AsPyObjectBorrow(stackref);
610+
if (_PyObject_GC_IS_TRACKED(obj) && !gc_is_frozen(obj)) {
611+
mark_stack_push(stack, obj);
612+
}
613+
}
614+
}
615+
616+
static void
617+
gc_visit_thread_stacks_mark_alive(PyInterpreterState *interp, _PyObjectStack *stack)
618+
{
619+
_Py_FOR_EACH_TSTATE_BEGIN(interp, p) {
620+
for (_PyInterpreterFrame *f = p->current_frame; f != NULL; f = f->previous) {
621+
PyObject *executable = PyStackRef_AsPyObjectBorrow(f->f_executable);
622+
if (executable == NULL || !PyCode_Check(executable)) {
623+
continue;
624+
}
625+
626+
PyCodeObject *co = (PyCodeObject *)executable;
627+
int max_stack = co->co_nlocalsplus + co->co_stacksize;
628+
gc_visit_stackref(f->f_executable);
629+
for (int i = 0; i < max_stack; i++) {
630+
gc_visit_stackref_mark_alive(stack, f->localsplus[i]);
631+
}
632+
}
633+
}
634+
_Py_FOR_EACH_TSTATE_END(interp);
635+
}
636+
587637
static void
588638
queue_untracked_obj_decref(PyObject *op, struct collection_state *state)
589639
{
@@ -968,21 +1018,6 @@ propagate_alive_bits(_PyObjectStack *stack)
9681018
return 0;
9691019
}
9701020

971-
static bool
972-
mark_stack_push(_PyObjectStack *stack, PyObject *op)
973-
{
974-
if (op == NULL) {
975-
return true;
976-
}
977-
assert(!gc_is_alive(op));
978-
gc_set_alive(op);
979-
//gc_maybe_merge_refcount(op);
980-
if (_PyObjectStack_Push(stack, op) < 0) {
981-
return false;
982-
}
983-
return true;
984-
}
985-
9861021
static int
9871022
mark_root_reachable(PyInterpreterState *interp,
9881023
struct collection_state *state)
@@ -997,6 +1032,7 @@ mark_root_reachable(PyInterpreterState *interp,
9971032
gc_visit_heaps(interp, &validate_alive_bits, &state->base);
9981033
#endif
9991034
_PyObjectStack stack = { NULL };
1035+
gc_visit_thread_stacks_mark_alive(interp, &stack);
10001036
mark_stack_push(&stack, interp->sysdict);
10011037
mark_stack_push(&stack, interp->builtins);
10021038
mark_stack_push(&stack, interp->dict);

0 commit comments

Comments
 (0)