Three colors. One marker pass.

This is how Go collects garbage: white objects have not been found yet, grey ones are found but their pointers are unread, black ones are fully scanned. Step through a cycle, switch the mutator on, then switch the write barrier off — and watch the GC lose a live object.

white grey · queued black
≈3.5 steps/s
STW · setupenable barrier, scan roots
Concurrent markgrey → black, program keeps running
STW · mark terminationa short finish
Concurrent sweepwhite is freed
click two objects — link / unlink click an arrow — drop the pointer double-click the canvas — new object drag — rearrange
ROOT SET GOROUTINE STACKS, GLOBALS HEAP OBJECTS
STW