cgen + memio: cgoutarena → memio.dynamic, grow → dynamicgrow (β-3)

Phase 0 last β-shape site. Two concerns in one commit because the
refactor surfaced the rename:

 - selfhost/cmd/wcc/cgen.ww  cgout buffer (cgoutbuf/cap/len + arena +
   cgout_grow + CGOUT_INIT_CAP) → memio.state + io.stream behind a
   one-shot lazy-init guard. cgout_enable drops its *arena param;
   memio.reset in cgout_flush keeps the buffer sticky across fns so
   the arena's amortisation survives — re-init per fn would abandon
   the buffer and re-grow from 0 via the 8→…→65536 ladder for every
   function (no io.close path → no os.free).

 - lib/memio/memio.ww  private fn grow → dynamicgrow. Symmetric with
   dynamicwrite / dynamicclose; required because cstage bundles all
   imported modules into a flat TU and resolves private fns by
   unqualified name, so the new `import memio;` in wcc's bundle
   collided with selfhost/cmd/wcc/mem.ww's arena `grow`. Module-aware
   private-fn scoping in cstage is task #9.

@test fn dynamicgrow in memiotest.ww (same package as memio.ww)
renamed to dynamicgrowcases to free the name; new suffix mirrors the
file's existing fixedwritecases / borrowedreadcases convention.

Lazy-init guard cgoutinit. memio.dynamic runs once on first
cgout_enable; subsequent enables just set cgoutmode. Mirrors
lib/log/log.ww:124 ensureinit. Without it, ~14 mmap syscalls per fn
and ~100 MiB+ cumulative leak on a typical bootstrap.

io.write bare discard in emitbytes mirrors lib/log/log.ww:169 —
memio.dynamicwrite never returns io.closed (memio.ww:166).

Verified 132/132 incl. 995_self_rebuild byte-identity.
This commit is contained in:
2026-05-21 10:11:40 +09:00
parent f07a032104
commit fd7dee985e
6 changed files with 633 additions and 123 deletions

View File

@@ -127,11 +127,14 @@ fn putstr(s: str, into: []u8, off: i32) i32 = {
match (c) { case void => {}; case io.closed => fail(); };
};
// ---- dynamicgrow: every cap doubling exercised --------------------------
// ---- dynamicgrowcases: every cap doubling exercised ---------------------
// Drive grow 0 → 8 → 16 → 32 by writing sized chunks. Verify
// accumulated `pos` after each step.
@test fn dynamicgrow() void = {
// accumulated `pos` after each step. Suffix `cases` mirrors
// `fixedwritecases` / `borrowedreadcases`; bare `dynamicgrow`
// would collide with memio.ww's private `dynamicgrow` in the same
// package.
@test fn dynamicgrowcases() void = {
let mem: memio.state;
let s: io.stream;
memio.dynamic(&mem, &s);
@@ -352,7 +355,7 @@ fn putstr(s: str, into: []u8, off: i32) i32 = {
export fn main() i32 = {
signalled = 1; fixedread();
signalled = 2; fixedwritecases();
signalled = 3; dynamicgrow();
signalled = 3; dynamicgrowcases();
signalled = 4; dynamicreset();
signalled = 5; borrowedreadcases();
signalled = 6; stringview();