sicp.io
5.3.2 · Maintaining the illusion of infinite memory

Copy live cells, forward repeated references, and leave garbage behind.

Move the graph reachable from an explicit root set into a fresh vector memory, installing forwarding pointers that preserve shared tails and cycles.

Guiding question

How can a collector compact live storage without duplicating shared objects or looping forever through a cycle?

  • Distinguish from-space from an initially empty to-space
  • Copy only pair pointers reachable from the supplied roots
  • Install a forwarding entry before recursively copying fields
  • Reuse one new pointer for every repeated reference to an old cell
  • Preserve a cycle by recognizing a forwarded pointer
  • Measure reclaimed cells and the advancing free pointer

copy-value returns atoms unchanged. For a pair pointer, it first consults forwarding by old index. A missing entry allocates one placeholder cell in to-space and records the new pointer before either field is followed. The car and cdr are then copied recursively into that placeholder. Recording first is what makes both sharing and cycles finite.

The first heap has five allocated cells but only three are reachable from the two roots. The copied left and right cells point to one copied shared tail, while both garbage cells retain false forwarding entries. The second heap contains a self-cycle; copying the cdr reaches the old pointer again and immediately reuses the already installed new pointer. This finite program performs one explicit collection within a fixed semispace capacity.

SICP code4,742 of 1,048,576 UTF-8 bytes
Examples
Result
Output
Value
Diagnostic
Execution trace0 / 0 events
    Programs run in the browser with their result and execution trace.
    Expected result

    The shared-graph collection returns (5 3 2 (a shared) (b shared) #t #f #f). The cyclic collection returns (1 node #t #f).

    Trace focus

    In the shared graph, follow the first old shared pointer into a new allocation and the second occurrence into the existing forwarding entry. Confirm that old indexes 3 and 4 are never visited. In the cycle, locate the forwarding write before the recursive cdr copy reaches the old node again.

    Try it yourself

    Change the program and compare the result.

    Add a third root that points directly to the shared tail, then mutate the copied tail. Predict the new allocation count and every root observation. Next swap the semispaces and allocate one additional cell.

    Show hint

    An extra root to an already forwarded object adds no copied cell. After collection, all clients must use the rewritten roots in to-space rather than stale from-space pointers.

    Complete this lesson

    0 of 23 lessons complete in this chapter0%