@@ -891,7 +891,11 @@ move_unreachable(PyGC_Head *young, PyGC_Head *unreachable,
891891 // GraalPy change: this branch, else branch is original CPython code
892892 cycle .head = NULL ;
893893 cycle .n = 0 ;
894- // TODO: [GR-72218] assert (cycle.reachable == weak_candidates );
894+ /* GraalPy change: visit_collect_managed_referents forwards to
895+ * visit_reachable(cycle->reachable), and 'cycle' is initialized
896+ * with 'young'.
897+ */
898+ assert (cycle .reachable == young );
895899 /* visit_collect_managed_referents is visit_reachable + capture the references into "cycle" */
896900 CALL_TRAVERSE (traverse , op , visit_collect_managed_referents , (void * )& cycle );
897901
@@ -979,12 +983,25 @@ move_weak_reachable(PyGC_Head *young, PyGC_Head *weak_candidates)
979983 while (gc != young ) {
980984 Py_ssize_t gc_refcnt = gc_get_refs (gc );
981985
982- // TODO: [GR-72218] assert(gc_is_collecting(gc));
983-
986+ /* GraalPy change: unlike CPython's single-phase flow, objects moved to
987+ * 'weak_candidates' already had PREV_MASK_COLLECTING cleared in
988+ * move_unreachable() before this phase runs. visit_weak_reachable()
989+ * depends on that state so it can rescue weak candidates without
990+ * moving them through visit_reachable() again, so gc_is_collecting(gc)
991+ * is not a valid invariant here.
992+ */
993+ // assert(gc_is_collecting(gc));
984994 /* This phase is done after 'move_unreachable' and so all object
985995 * remaining in 'young' must have a non-zero gc_refcnt.
986996 */
987- // TODO: [GR-72218] assert(gc_refcnt);
997+ /* GraalPy change: gc_refcnt is also not a stable CPython-style
998+ * invariant here. During the weak-candidate flow we reuse '_gc_prev'
999+ * for list linkage, so native gc_refs information for rescued objects
1000+ * is recovered via update_refs()/subtract_refs() and
1001+ * is_referenced_from_managed(), not by requiring gc_refcnt != 0 for
1002+ * every object we encounter in this phase.
1003+ */
1004+ // assert(gc_refcnt);
9881005 /* If gc_refcnt s not MANAGED_REFCNT, then we know that this object is
9891006 * referenced from native (e.g. stored in a global field). In case that
9901007 * 'gc_refcnt == MANAGED_REFCNT' we don't know if the object is only
0 commit comments