Skip to content

module: cache compiled WebAssembly modules in the compile cache - #66191

Open
guybedford wants to merge 1 commit into
nodejs:mainfrom
guybedford:wasm-compile-cache
Open

guybedford wants to merge 1 commit into
nodejs:mainfrom
guybedford:wasm-compile-cache

Conversation

@guybedford

@guybedford guybedford commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

This extends the module compile cache (module.enableCompileCache() / NODE_COMPILE_CACHE) to WebAssembly modules loaded through the ES module integration.

  • A new kWasm cache entry type, keyed on the module URL with the wire bytes as the hashed source, stores V8's CompiledWasmModule serialization.
  • On load, cached code is deserialized through v8::WasmModuleCompilation with the same compile options the wasm translator uses (js-string builtins and imported string constants), falling back to new WebAssembly.Module() when V8 rejects it.
  • CompileCacheHandler::GetOrInsert gains a raw-bytes overload used by the new entry type; the string overload delegates to it.

The WasmModuleObject::CompileOptions API this relies on is included in the V8 15.5 update now on main, so no V8 patch is needed.

As for JavaScript, the entry is captured right after compilation. V8 only serializes optimized-tier code, so with the default lazy baseline compilation there is nothing to cache and no entry is written. A complete cache requires --no-liftoff --no-wasm-lazy-compilation, which compiles everything with the optimizing tier at module creation; since V8 flags are part of the cache key, all processes sharing the cache must use the same flags. This is documented in a new section of module.md.

The test covers both the eager-compilation case (entry written, then deserialized and accepted on the second run) and the default case (nothing serialized, no entry written).

@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/gyp
  • @nodejs/loaders
  • @nodejs/security-wg
  • @nodejs/v8-update

@nodejs-github-bot nodejs-github-bot added lib / src Issues and PRs involving general changes in the lib/ or src/ directories. needs-ci PRs that need a full CI run. labels Sep 22, 2026
@codecov

codecov Bot commented Sep 22, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.54913% with 25 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.65%. Comparing base (ddba9a5) to head (f291da1).
⚠️ Report is 3 commits behind head on main.

Files with missing lines Patch % Lines
src/node_modules.cc 80.16% 5 Missing and 19 partials ⚠️
src/compile_cache.cc 96.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #66191      +/-   ##
==========================================
- Coverage   90.65%   90.65%   -0.01%     
==========================================
  Files         797      797              
  Lines      278268   278429     +161     
  Branches    53511    53536      +25     
==========================================
+ Hits       252258   252396     +138     
- Misses      16384    16394      +10     
- Partials     9626     9639      +13     
Files with missing lines Coverage Δ
lib/internal/modules/esm/translators.js 97.63% <100.00%> (+0.06%) ⬆️
src/compile_cache.h 100.00% <ø> (ø)
src/compile_cache.cc 80.95% <96.00%> (+0.89%) ⬆️
src/node_modules.cc 79.75% <80.16%> (+0.27%) ⬆️

... and 25 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@mcollina mcollina left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@mcollina mcollina added the request-ci Add this label to start a Jenkins CI on a PR. Only starts once the PR has an approving review. label Sep 22, 2026
@github-actions github-actions Bot removed the request-ci Add this label to start a Jenkins CI on a PR. Only starts once the PR has an approving review. label Sep 22, 2026
@nodejs-github-bot

This comment was marked as outdated.

@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

@guybedford guybedford added the author ready PRs with CI started, the required approvals, and no outstanding review comments. label Sep 26, 2026
@github-actions github-actions Bot removed the author ready PRs with CI started, the required approvals, and no outstanding review comments. label Sep 28, 2026
@github-actions

Copy link
Copy Markdown
Contributor

This pull request has conflicts with its base branch, removing the author ready label.
Please rebase your branch onto the latest base branch, resolve the conflicts locally, and force-push.
Afterwards the pull request needs a fresh collaborator approval, and a collaborator will add the label back once it is author ready again.

@GeoffreyBooth

Copy link
Copy Markdown
Member

This is very cool.

@guybedford

This comment was marked as outdated.

@guybedford

Copy link
Copy Markdown
Contributor Author

This is now rebased and no longer depends on the V8 patch. Will aim to land soon!

@guybedford guybedford added author ready PRs with CI started, the required approvals, and no outstanding review comments. request-ci Add this label to start a Jenkins CI on a PR. Only starts once the PR has an approving review. and removed request-ci Add this label to start a Jenkins CI on a PR. Only starts once the PR has an approving review. labels Oct 27, 2026
Extends the module compile cache to WebAssembly modules loaded through
the ES module integration. A new kWasm entry type is keyed on the module
URL with the wire bytes as the hashed source, and stores the serialized
CompiledWasmModule. On load, cached code is deserialized through
v8::WasmModuleCompilation with the same compile options the translator
uses (js-string builtins and imported string constants), falling back
to compilation when V8 rejects it.

As for JavaScript, the cache entry is generated right after compilation.
V8 only serializes optimized tier code, so with the default lazy
baseline compilation there is nothing to cache and no entry is written;
a complete cache requires --no-liftoff --no-wasm-lazy-compilation, which
is documented as the way to use the compile cache for WebAssembly.

Signed-off-by: Guy Bedford <guybedford@gmail.com>
Assisted-by: Claude Code
@guybedford guybedford added request-ci Add this label to start a Jenkins CI on a PR. Only starts once the PR has an approving review. and removed author ready PRs with CI started, the required approvals, and no outstanding review comments. labels Oct 27, 2026
@guybedford guybedford added the author ready PRs with CI started, the required approvals, and no outstanding review comments. label Oct 27, 2026
@github-actions github-actions Bot removed the request-ci Add this label to start a Jenkins CI on a PR. Only starts once the PR has an approving review. label Oct 27, 2026
@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

author ready PRs with CI started, the required approvals, and no outstanding review comments. lib / src Issues and PRs involving general changes in the lib/ or src/ directories. needs-ci PRs that need a full CI run.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants