[JSC] Decommit a MarkedBlock's dead pages on its first sweep after a full collection, whichever collection finished last

Merged
JA
23d ago
+20-8

MarkedBlock::Handle::decommitUnusedPages() gives the pages of a block that hold no live cell back to the OS when the incremental sweeper reaches a block that a full collection left partly dead. Whether a sweep qualifies was decided by Heap::lastCollectionScope() at sweep time.

An embedder that requests an eden collection while a full one is finishing, or right after it, flips that to Eden before the sweeper's first timer slice, and then nothing the full collection left behind is decommitted until some later full collection happens not to be followed by an eden one. Measured in an application idling at a prompt whose embedder runs a 1 s GC timer: 12–14 MB of dead pages stayed committed after roughly one idle full collection in four (17 of 65 observed), for minutes.

Each block handle now remembers MarkedSpace::markingVersion() as of its last sweep. Only a full collection moves that version on, so "this is the block's first sweep since a full collection began" is a per-block fact that a later eden collection does not disturb. Same call sites (SweepOnly sweeps, i.e. the incremental sweeper; never the allocator's sweep-to-free-list), same exclusions (Structure spaces, shutdown, mostly-full blocks), same recommit path.

same application, MarkedBlock bytes committed while parked after activityanon RSS 60 s after activity
before, sweep raced by an eden request: 82–90 MB207–210 MB
before, not raced: 73–78 MB193–198 MB
after (6 sessions): 70–78 MB190–197 MB
decommit disabled: 86–89 MB205–209 MB

One HeapVersion per MarkedBlock::Handle.