Binary heap dump can't work under GC because the heap is a linked chunk list with typed block headers and a free list. Raw-byte serialization would lose structure. Rather than invent portal v2 with chunk tables and pointer relocation, the GC build uses the S-expression format that already works across all other tiers: # bi_portal_save in GC build: walk %r14 (env chain); for each non-builtin, non-closure binding, emit `(define <sym> (quote <val>))` to the opened file via scheme_print with output_fd redirected to that fd. # bi_portal_resume in GC build: jmp bi_load — read every form from the file, eval each in %r14. The quote wrapper makes data values round-trip cleanly: lists, vectors, strings, symbols, numbers, pairs all re-read as literals. Closures and builtins are explicitly skipped — closures can't faithfully re-read from their printed form; builtins reconstruct from the target's prelude. Same treatment the JSON portal gives. The no-GC build keeps the binary portal format unchanged (wrapped in .ifndef GC_NAIVE). Users get the fast format on the fast build, the portable format on the safe build. Same API, different wire format by build. Cross-tier verified: GC-asm producer -> Python consumer passes with `x=42`, `nums=(1 2 3 4 5)`. The §7.2 cross-impl matrix expands from 9 to 16 cells, all green. Whitepaper §7.4 now notes it's the no-GC format; new §7.4.1 documents the GC build's S-expression portal with the trade-off (slower than binary dump, stricter about what round-trips, but no architecture constraint and no "same binary" requirement). 137 asm no-GC + 137 asm GC + 189 shared functional tests pass. All four HTTP cells from §6.6.4 still bounded under sustained load (GC + no-snapshot at ~630 req/s peak, 1.1 MB steady state).
52 KiB
52 KiB