Loment
EN

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.

Read the paper

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.