The half the shadow stack was built for. A slot's entry in the frame is its address, null until the binding that fills it has run, so "not bound yet at this point" is a null and needs no liveness analysis. The daemon compiles a thunk that renders the types it already knows -- Tast.fn.slots, with snames beside them -- at the addresses the stopped program supplies, and reads the text back the way C-x C-e does. Nothing is copied out, because a value with no header is bytes with no meaning anywhere but in the program that holds it. That is render.ml's walk with its root changed, which is the pointer-rooted thunk NEXT.md said this needed, and one new arm in the backend: a cast from one pointer type to another, which emits nothing. Only named slots are recorded. A recorded slot escapes and stops being promotable, and the slots that would cost most are the ones with nothing to show -- dotimes' bound, the temporaries min and max use, the walk's own scratch. They are refused by name rather than shown under an invented one. Recording every slot was built and timed and is inside the noise, so the rule stands on what it shows. Four refusals, each by name and with its reason: a slot nobody named, a slot the program has not reached, a type the printer has no arm for, and two whole frames -- an evaluation's thunk, and a frame running a body that has been redefined since, where every slot index would be a guess. Measured, minimum of nine runs: +61% on call-heavy code over globals against +33% for the frames alone, 0.06% of a frame at 60fps.
Description
Languages
OCaml
67.2%
Emacs Lisp
15.2%
C
10.4%
HTML
2.9%
Standard ML
2.8%
Other
1.5%