Contents
Changes to the vendored rust-gc v0.5.1
Every modification to the files in gc/ and gc_derive/ relative to upstream
tag v0.5.1. Those files remain under the MPL-2.0 (LICENSE).
Iterative marking (gc/src/gc.rs)
Upstream GcBox::trace_inner marked a box and then traced its data, which
called trace_inner on each child Gc: one Rust frame per Gc edge. A
collection while a long chain was alive (every mino list is a chain of cons
cells) overflowed the stack: ~6,000 links on a 2 MB stack in a debug build,
~200,000 nested levels in a release build.
GcBoxHeadergainsthis: Cell<Option<NonNull<GcBox<dyn Trace>>>>, set byinsert_gcboxwhen the box joins the chain, so a box can be queued without knowing its concrete type.- A thread-local
MARK_STACKworklist exists only while a mark pass runs.collect_garbage’s mark phase calls the newmark_from(root)for each rooted box;mark_fromtraces queued boxes in a loop. - During a pass,
trace_innermarks the box and pushes it on the worklist instead of tracing into it. Outside a pass it behaves as upstream.
Stack use during a collection is now bounded by the nesting inside a single box’s data, not by the length of the object graph.
Tests (gc/tests/deep_chains.rs, new)
Collect with a 1,000,000-link live chain, collect a dead one, a 500,000-link
chain through GcCells, and a cycle is still freed; all on a 256 KB stack.
Against unmodified v0.5.1 these abort with a stack overflow.