Skip to content

Add wasm_memory_discard compatibility flag - #6999

Merged
guybedford merged 2 commits into
mainfrom
gbedford/wasm-memory-discard
Aug 17, 2026
Merged

Add wasm_memory_discard compatibility flag#6999
guybedford merged 2 commits into
mainfrom
gbedford/wasm-memory-discard

Conversation

@guybedford

Copy link
Copy Markdown
Contributor

Adds a wasm_memory_discard compatibility flag gating the experimental WebAssembly memory.discard sub-proposal, exposing WebAssembly.Memory.prototype.discard(byteOffset, byteLength) and the memory.discard opcode per-worker.

Wired through V8's per-context conditional-feature mechanism: a per-isolate enabled callback (SetWasmMemoryDiscardEnabledCallback) reports the flag state, consulted both when installing the JS API (InstallConditionalFeatures) and when compiling wasm modules using the opcode. The flag stays set for the isolate lifetime since V8 re-queries it at compile time.

Floats the V8 prototype as patch 0039, a port of CL 4300676 updated to the memory.discard semantics prototyped in SpiderMonkey, behind --experimental-wasm-memory-discard.

Includes a wd-test covering the API and opcode, and as a drive-by removes the now-obsolete jspiEnabledCallback declaration.

Page release goes through one funnel, and the right allocator

memory.discard returns physical pages to the OS, so where it releases them from matters. The patch routes all three entry points — the JS API, the jitted memory_discard_wrapper, and the interpreter — through BackingStore::DiscardWasmMemory rather than discarding raw addresses:

trusted_data->memory_object(mem_index)->backing_store()->DiscardWasmMemory(dst, size);

That single point then resolves the allocator the reservation actually came from, mirroring what the free path already does:

#ifdef V8_ENABLE_SANDBOX
  if (page_allocator_.expired()) return;
  auto page_allocator = page_allocator_.lock();
  DiscardWasmMemoryPages(page_allocator.get(), address, size);
#else
  DiscardWasmMemoryPages(GetPlatformPageAllocator(), address, size);
#endif

Under V8_ENABLE_SANDBOX, wasm memory is reserved from the isolate group's backing-store allocator in TryAllocateAndPartiallyCommitMemory, not the platform allocator. Reaching for GetPlatformPageAllocator() therefore decommitted through an allocator that does not own the region. That is benign on Linux — DiscardSystemPages is madvise(MADV_DONTNEED), keyed on address — but wrong on the DecommitPages + SetPermissions path used elsewhere, which mutates allocator bookkeeping.

Verification

Measured against a patched d8 with the sandbox enabled: a 64 MB discard releases exactly 67108864 bytes of RSS, and the region reads back as zeroes and stays writable. Release is precise at page granularity — discarding a single 64 KB wasm page frees exactly 64 KB, re-discarding it frees nothing, and a subsequent overlapping 32 MB discard frees exactly 32 MB − 64 KB.

One note for anyone testing this at the V8 level: d8 enables the wasm trap handler by default, which requires an 8 GB kFullGuardSize32 reservation per memory and so cannot allocate any wasm memory inside a smaller sandbox. --no-wasm-trap-handler is needed to match an embedder that does not install the handler

@guybedford
guybedford requested review from a team as code owners August 14, 2026 01:03
@ask-bonk

ask-bonk Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

APIError: Invalid Anthropic API Key

github run

2 similar comments
@ask-bonk

ask-bonk Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

APIError: Invalid Anthropic API Key

github run

@ask-bonk

ask-bonk Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

APIError: Invalid Anthropic API Key

github run

@ask-bonk

ask-bonk Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

@guybedford Bonk workflow failed. Check the logs for details.

View workflow run · To retry, trigger Bonk again.

@codspeed-hq

codspeed-hq Bot commented Aug 14, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 72 untouched benchmarks
⏩ 129 skipped benchmarks1


Comparing gbedford/wasm-memory-discard (727e68f) with main (482c2be)

Open in CodSpeed

Footnotes

  1. 129 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@guybedford
guybedford force-pushed the gbedford/wasm-memory-discard branch 2 times, most recently from 526325e to 205518d Compare August 15, 2026 04:11
Gates the experimental WebAssembly memory.discard proposal, exposing
WebAssembly.Memory.prototype.discard(byteOffset, byteLength) and the
memory.discard opcode on a per-worker basis.

The feature is wired through V8's per-context conditional-feature
mechanism: a per-isolate enabled callback (SetWasmMemoryDiscardEnabledCallback)
reports the flag state, which V8 consults both when installing the JS API
(InstallConditionalFeatures) and when compiling wasm modules that use the
memory.discard opcode. Lock::installWasmMemoryDiscard() enables the feature
once per context, based on the flag, via NewContextOptions.

Floats the memory.discard V8 patch (0039) into workerd's V8 patch set so the
feature is present in workerd's own V8 build.

The patch routes the JS API, the jitted memory.discard wrapper and the
interpreter through BackingStore::DiscardWasmMemory rather than discarding
raw addresses, so page release happens at a single point, and that point
discards through the page allocator the reservation actually came from. Under
V8_ENABLE_SANDBOX wasm memory is reserved from the isolate group's
backing-store allocator, not the platform allocator, so reaching for
GetPlatformPageAllocator() decommitted through an allocator that does not own
the region -- benign on Linux, where DiscardSystemPages is madvise(MADV_DONTNEED)
keyed on address, but wrong on the DecommitPages/SetPermissions path used
elsewhere.

Also removes the obsolete jspiEnabledCallback declaration left behind when
JSPI was stabilized.
@guybedford
guybedford force-pushed the gbedford/wasm-memory-discard branch from 3d2b6fb to 54f23ed Compare August 17, 2026 18:30
@guybedford
guybedford enabled auto-merge (squash) August 17, 2026 18:31
@guybedford
guybedford merged commit bd568a9 into main Aug 17, 2026
23 of 24 checks passed
@guybedford
guybedford deleted the gbedford/wasm-memory-discard branch August 17, 2026 19:57
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.

2 participants