System
LomentGC
When a Loment program frees memory, it does not hand the whole job to a collector. Every place that allocates is assigned, at compile time, to one of four strategies — and how much is left to the runtime collector is a number written into the binary rather than a claim in a document.
The ladder
From strongest to weakest: the compiler takes the strongest level it can prove. Prove more, pay less. Each level's price is written next to it rather than left in a footnote.
L0 — static
The allocation is a literal size, and the pointer is only ever passed whole as the first argument of a load, store or atomic. It never reaches the heap at all, so there is nothing to reclaim. The price: a larger stack frame.
L1 — last use
Same shape, declared at the top level of a function body, so the last use is
countable. The compiler inserts a free before the earliest
return after it. The price: on an early-return path the insert
point can be missed, and that path leaks once. A leak, not a bug.
L2 — block epochs
Inside a loop body, every allocation is a local that never leaves the body. The body's end returns the whole region at once, by winding the allocator front back — no list, no scan. The epoch is inferred from block structure and escape, not written by hand. The price: if one allocation in the body escapes, the whole block must stay.
L3 — runtime
Everything the compiler could not prove. The collector's full cost.
Three tiers
A program selects how far down the ladder it is willing to go, with one line in the file it starts from.
choose gc_manual
The default. Nothing is reclaimed automatically; the program manages its own memory. Writing no line at all gives you this — the default is the behaviour that was there before the setting existed, which is the rule every setting follows.
choose gc_auto
A runtime collector reclaims: mark-sweep with precise roots, triggered by the number of bytes allocated.
choose gc_auto_alpha
All four rungs are on, so the collector sees only what the compile-time rungs could not prove — and it is adaptive: the threshold follows the live set, with a space trigger, so the ceiling is not a fixed fraction of the arena.
A limit that is stated rather than discovered. Under
gc_auto the trigger is a fixed 32 KiB while the arena is 64 KiB, so a
program whose live set exceeds roughly 32 KB still runs out. Closing that gap
is what the adaptive collector, and the generational one under
gc_auto_alpha, are for.
Inside L3
The runtime level is not one algorithm either. It grew in three steps, each of which had to beat the one before it on a program the project could measure.
Mark and sweep
Roots are precise — the root table holds slot addresses — while a block's
interior is treated conservatively, because alloc is untyped and
nothing records what a block holds.
Adaptive triggering
A fixed threshold has to guess how large the live set will get. An adaptive one reads it: collect when the live set has doubled, or when space runs short.
Generational
Two generations, cut on address rather than object age — a non-moving collector promotes at the end of each minor collection by advancing a frontier. A card table and a write barrier catch old-to-young pointers. What it saves is the mark and propagate pass, which then covers only the young generation.
Why it lands in the binary
Each unit exports a machine-readable summary — a form object —
carrying gc_ladder: how many allocating sites each level took, plus the
total. The four counts must sum to the total, and two independent programs check
that arithmetic without reading a line of source. So "how is this program's
memory managed?" is a number in the build output rather than a claim in a document.
What is claimed, and what is not. The ladder is implemented twice — the reference compiler and the self-hosted one — and the two must agree byte for byte. The measurements behind the rungs come from the project's own criteria, which are small programs; the collector has not been run against a real workload, and that is worth knowing before reading any of this as a performance claim.