Skip to content

Merge train: #9647 #9648 #9649 (llhttp differential closes #9611) - #9653

Merged
proggeramlug merged 4 commits into
mainfrom
land-train99
Sep 3, 2026
Merged

Merge train: #9647 #9648 #9649 (llhttp differential closes #9611)#9653
proggeramlug merged 4 commits into
mainfrom
land-train99

Conversation

@proggeramlug

Copy link
Copy Markdown
Contributor

Lands three fixes, all cherry-picked clean:

Validation: run_lint_gates.sh all 62 gates pass; release build green; RUST_TEST_THREADS=1 perry-runtime 3060/0; issue_9611_llhttp_differential green (215s).

Rebase-merge preserving authorship.

Ralph Küpper added 4 commits September 3, 2026 21:13
…bits (#9611)

Closes the last open verification item on #9611 — the llhttp differential —
and fixes the bug that verification found.

THE DIFFERENTIAL. `crates/perry/tests/issue_9611_llhttp_differential.rs`
drives both WebAssembly builds of llhttp that undici ships, the way undici
drives them: a windowed `Uint8Array` over the engine's linear memory is filled
with the socket chunk, `llhttp_execute` runs, and the parser calls back into
JS. It covers whole-message, byte-at-a-time and 4 KiB chunkings of simple,
chunked, pipelined, 100-continue, many-header and 300 KiB-body responses, and
reads every callback span BOTH out of linear memory and through undici's own
trick of mapping the wasm pointer back into the source chunk — a span that is
right in one view and wrong in the other fails loudly instead of silently
agreeing with itself. node's trace is the checked-in oracle; both builds
reproduce it identically.

THE BUG IT FOUND. The wasm host held the imports object as raw NaN-boxed bits
(`perry_wasm_host_instance_set_import_context`), and nothing rooted or
rewrote them. A collection triggered INSIDE one import callback relocated the
object, so every later import in the same call resolved a stale pointer,
`call_wasm_import` returned 0, and the host substituted the import's default
result — wasm continued with no error reported anywhere. Through llhttp that
silently dropped `on_message_complete`: a truncated HTTP response reported as
a clean parse, on cc's network path.

It is not a regression from the zero-copy change. The same binary shape
reproduces on a perry built from `666481e27` (the commit before #9611
landed), and the minimiser isolates it to allocation volume inside the
callback, not to memory growth:

    big_nobuild body=307200 build=false pages=3->6  complete=1
    big_build   body=307200 build=true  pages=6->6  complete=0

and tenuring the imports object before instantiation — so a copying minor
cannot move it — restores complete=1 on every run. That is the diagnosis.

THE FIX. The host now holds an opaque token; the imports object stays on the
runtime side in `WASM_IMPORT_OBJECTS`, which a registered scanner rewrites
when a collection moves it. The token is assigned at instantiation, so the
start function is covered too, and the per-call
`perry_wasm_host_instance_set_import_context` store is gone — one less FFI
call on the export path.

The scanner is rewrite-only (`visit_metadata_nanbox_f64_slot`), matching the
memory binding beside it: every path that can reach an import already roots
the imports object on the stack, so this table is a lookup side table, not the
reference that keeps the object alive. Marking would instead pin the imports
object of every instance ever created.

Verified on Linux: byte-identical to node on both llhttp builds; the wasm ESM
suite, 14 wasm-host tests and 3,037 runtime tests pass; the root-holder and
file-size gates pass. Disabling only the rewrite fails the new test at exactly
the right line:

    node : message_complete
    perry: execute len=307243 ret=0 errpos=-76384

Claude-Session: https://claude.ai/code/session_01VxP3FEDgV4zUocSDBhD8qh
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Every wasm call copies the ENTIRE linear memory both ways: 44,163× node after the memory grows — one sync site; wasmi is innocent

1 participant