Skip to content

feat: add WASM32 Ignition loop AOT tier - #3

Open
vickiegpt wants to merge 25 commits into
mainfrom
feature/wasm32-ignition-loop-aot
Open

feat: add WASM32 Ignition loop AOT tier#3
vickiegpt wants to merge 25 commits into
mainfrom
feature/wasm32-ignition-loop-aot

Conversation

@vickiegpt

Copy link
Copy Markdown
Collaborator

Summary

  • add a guarded AOT executor for the exact Smi/i32 accumulator-loop bytecode shape
  • retain semantic interpreter fallback for every unmatched or bailed-out loop
  • add focused verification, persistent Wasmer cache launcher, and measured performance record

Test Plan

  • tools/run-wasm32-ignition-loop-aot-test.sh
  • baseline: elapsed_ns=17620629966
  • AOT: elapsed_ns=1481681 (11892.3x focused-loop speedup)

vickiegpt and others added 23 commits July 12, 2026 05:00
Add comprehensive design document for implementing minimal V8 builtins
to enable basic JavaScript execution on wasm32 Node.js port.

Key components:
- Builtin dispatch table using __indirect_function_table
- 5 core builtins (JSEntry, CEntry, InterpreterEntryTrampoline, etc.)
- Minimal Ignition interpreter for basic bytecode execution
- Bootstrap fixes to avoid Map::SetPrototype crashes

Goal: Enable simple JavaScript CLI tools to run on wasm32 Node.js
without implementing full V8 compatibility.

Timeline: 5 weeks across 4 phases from foundation to integration testing.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Add detailed implementation plan for minimal V8 builtins to enable
basic JavaScript execution on wasm32 Node.js.

Plan breakdown:
- 10 bite-sized tasks with exact file paths and complete code
- Builtin dispatch table using __indirect_function_table
- 5 core builtins (JSEntry, CEntry, InterpreterEntryTrampoline, RecordWrite, EnterContext)
- Minimal bytecode execution for basic JavaScript operations
- Bootstrap fixes and integration testing

Each task includes:
- Exact file paths to create/modify
- Complete code implementations
- Testing steps with expected outputs
- Git commit commands

Follows TDD principles: test first, implement, verify, commit.
Estimated timeline: 10 tasks across development phases.

Ready for subagent-driven or inline execution.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings September 8, 2026 23:16

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

It introduces multiple build-breaking/operational issues (ICU stub entry-point type/size mismatch on WASI, unused-variable warnings, unconditional stderr logging, and dead-code guards) that should be fixed before merging.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR extends the WASM32/WASI build of Node+V8 with a guarded “Ignition loop AOT” execution tier (with interpreter fallback) and broadens the WASI compatibility surface across Node core, V8, libuv, ICU, OpenSSL, and Undici. It also adds scripts/tests to run and validate the focused loop-AOT path under Wasmer with caching.

Changes:

  • Add WASM32/WASI execution and bootstrap shims (V8 interpreter/entrypoints, microtasks, internal bindings, and API fallbacks) to keep Node functional under the wasm32 interpreter.
  • Add Wasmer-based runner + focused test to validate AOT loop planning/completion output and provide a benchmark harness.
  • Expand WASI build configuration in gyp files and adjust third-party deps (libuv polling, ICU tooling/stub data, OpenSSL WASI config).
File summaries
File Description
wasi-v8-essential-constants.h Reorders/guards minimal V8 constants for WASI builds.
tools/wasmer-aot-run.sh Adds a Wasmer runner with persistent cache + env passthrough.
tools/v8_gypfiles/toolchain.gypi Adds WASI shim defines for wasm32 target toolset.
tools/v8_gypfiles/features.gypi Disables leaptiering and enables DrumBrake under wasm32/WASI, plus defines.
tools/run-wasm32-ignition-loop-aot-test.sh Adds a focused runner + output verification for loop AOT stats.
tools/icu/icu-generic.gyp Uses real icupkg for host toolset builds.
tools/icu/genccode_wasi_stub.cpp Adjusts ICU stub symbol naming to align with generated symbol conventions.
test/wasm32/test-ignition-loop-aot.js Adds a correctness + benchmark harness for the loop AOT shape.
src/util.cc Optimizes string conversion path for WASI to avoid failing conversions.
src/util-inl.h Implements WASI FromV8Array instead of returning a stub false.
src/tty_wrap.cc Removes WASI-only tracing and adjusts SetRawMode behavior for ENOTSUP.
src/timers.cc Removes WASI tracing; adjusts formatting around timer scheduling code.
src/stream_base.cc Handles zero-length writes on WASI and removes trace logging.
src/pipe_wrap.cc Removes WASI-only tracing scaffolding.
src/node.cc Gates OpenSSL config init behind OPENSSL_NO_STDIO.
src/node_worker.cc Removes WASI debug prints during worker per-context init.
src/node_wasm_web_api.cc Removes debug prints around wasm web API implementation setup.
src/node_v8.cc Disables WASI init tracing macro body unconditionally.
src/node_util.cc Exposes slow guessHandleType method on WASI where fast API is unavailable.
src/node_url.cc Removes WASI debug prints and preserves realm fallback logic.
src/node_task_queue.cc Removes WASI debug prints during task queue initialization.
src/node_symbols.cc Removes WASI debug prints during symbols initialization.
src/node_sqlite.cc Disables SQLite extension loading on WASI with a clear error.
src/node_snapshotable.cc Removes WASI tracing and simplifies constructor path.
src/node_realm.cc Removes WASI tracing and simplifies bootstrap locals.
src/node_realm-inl.h Removes WASI tracing wrapper around MakeWeakBaseObject.
src/node_process_methods.cc Adds WASI stdout/stderr raw write helpers and registers references.
src/node_options.cc WASI-specific behavior for CLI options metadata/prototypes; retains dead debug block.
src/node_metadata.cc Makes OpenSSL version parsing more robust and adjusts arch/platform strings for WASI.
src/node_main_instance.cc Removes debug prints around environment creation.
src/node_http_parser.cc Avoids consuming broken callback return handles on wasm32 by short-circuiting.
src/node_file.cc Improves WASI return-value handling + validates path arg; removes debug prints.
src/node_file-inl.h Forces promise request wrappers on WASI to preserve promise semantics.
src/node_errors.cc Disables source decoration on WASI due to missing line-end metadata.
src/node_env_var.cc Removes debug prints around env proxy template creation.
src/node_config.cc Disables inspector flag on WASI and removes debug prints.
src/node_buffer.cc Removes WASI tracing; retains fallback prototype handling.
src/node_binding.cc Changes internal binding cache storage to heap-allocated map pointer.
src/handle_wrap.cc Removes WASI tracing from constructor template setup.
src/env.cc Removes WASI debug prints and tightens formatting in a few places.
src/encoding_binding.cc Removes WASI debug prints in binding setup/serialization.
src/crypto/crypto_context.cc Minor constructor change that currently introduces an unused variable.
src/cppgc_helpers-inl.h Skips Wrap/TrackCppgcWrapper integration on WASI.
src/cares_wrap.cc Removes WASI tracing from cares initialization.
src/base_object.cc Removes WASI tracing from BaseObject construction/template setup.
src/base_object-inl.h Removes WASI tracing from weak base object creation.
src/async_wrap.cc Removes WASI tracing from async wrap template setup.
src/api/embed_helpers.cc Adjusts event loop run formatting in the main loop.
src/aliased_buffer-inl.h Removes WASI debug prints around buffer allocation/view validation.
node.gyp Adds WASI ldflags (stack size, whole-archive OpenSSL) and uses Wasmer to run mksnapshot; tweaks snapshot/builtins linkage conditions.
lib/internal/webstreams/readablestream.js Uses reader.read() directly on WASI for async iteration reliability.
lib/internal/readline/utils.js Adjusts Enter key naming on WASI.
lib/internal/process/warning.js Disables emitWarning on WASI.
lib/internal/process/signal.js Disables signal watcher setup on WASI.
lib/internal/process/per_thread.js Fail-closed allowed flags set when CLI metadata is absent on WASI.
lib/internal/per_context/primordials.js Ensures early-return after resolving empty promise lists.
lib/internal/modules/helpers.js Uses BuiltinModule.get(); adjusts TextDecoder input on WASI.
lib/internal/modules/esm/resolve.js Resolves builtin modules without scheme on WASI.
lib/internal/modules/esm/module_job.js Avoids iterating a Set directly by also tracking an array list.
lib/internal/fs/promises.js Reworks writeFileHandle chunking and avoids unconditional Buffer.from conversion.
lib/internal/dns/utils.js Changes default DNS order on WASI.
lib/internal/child_process.js Early ENOSYS error path for spawn on WASI.
lib/internal/bootstrap/switches/is_main_thread.js Adds WASI stdout/stderr write overrides and disables SIGWINCH wiring on WASI.
lib/internal/async_hooks.js Handles undefined async IDs by returning 0 on wasm32/WASI.
lib/internal/assert/utils.js Avoids assuming a CallSite exists on WASI when formatting assertion messages.
lib/events.js Tracks listenerCount separately for controller cleanup.
lib/buffer.js Uses unsafe buffer allocation path on WASI instead of pool.
deps/v8/src/zone/zone-containers.h Fixes ZoneVector copy/move semantics and zone deletion logic.
deps/v8/src/wasm/wasm-js.cc WASI argument check adjustments and forces WebAssembly exposure on wasm32 host.
deps/v8/src/wasm/wasm-engine.cc Disables async compilation paths on WASI and adjusts streaming compilation gating.
deps/v8/src/wasm/wasm-code-manager.h Fixes BitField template parameters in non-DrumBrake builds.
deps/v8/src/wasm/interpreter/wasm-interpreter.h Enables bounds checks and calling-convention tweaks for wasm32.
deps/v8/src/wasm/interpreter/wasm-interpreter.cc Adds non-pointer-compression guard behavior and adjusts hashing/Smi creation.
deps/v8/src/wasm/interpreter/wasm-interpreter-inl.h Relaxes pointer-size static_assert for wasm32.
deps/v8/src/utils/allocation.h Switches to canonical platform header and reformats signatures.
deps/v8/src/roots/roots-inl.h Removes WASI debug prints.
deps/v8/src/parsing/preparse-data.cc Uses placement-new to rebuild ZoneVectors safely.
deps/v8/src/parsing/parsing.cc Minor include formatting change.
deps/v8/src/parsing/parser.cc Disables lazy compile for non-user JS on WASI.
deps/v8/src/parsing/parse-info.h Adds is_user_javascript flag bit.
deps/v8/src/parsing/parse-info.cc Populates is_user_javascript from Script.
deps/v8/src/objects/transitions.cc Gates WASI tracing behind V8_WASM32_TRACE_OBJECT_LAYOUT.
deps/v8/src/objects/shared-function-info.cc Gates WASI tracing behind V8_WASM32_TRACE_OBJECT_LAYOUT.
deps/v8/src/objects/prototype-inl.h Gates WASI tracing behind V8_WASM32_TRACE_OBJECT_LAYOUT.
deps/v8/src/objects/objects-body-descriptors-inl.h Skips visiting CppHeapPointer fields on WASI.
deps/v8/src/objects/module.cc Disables STACK_CHECK on WASI.
deps/v8/src/objects/map-updater.cc Removes WASI debug prints.
deps/v8/src/objects/map-inl.h Gates WASI tracing behind V8_WASM32_TRACE_OBJECT_LAYOUT and formats prints.
deps/v8/src/objects/js-function.cc Removes WASI debug prints.
deps/v8/src/objects/js-function-inl.h Removes WASI-specific prototype/map offset workaround.
deps/v8/src/objects/js-array-buffer.cc Removes WASI debug prints.
deps/v8/src/objects/elements.cc Removes WASI debug prints.
deps/v8/src/objects/descriptor-array.h Removes WASI-specific entry layout constants.
deps/v8/src/objects/descriptor-array-inl.h Gates WASI tracing behind V8_WASM32_TRACE_OBJECT_LAYOUT.
deps/v8/src/interpreter/interpreter.cc Adds WASI dispatch table barriers for call-like bytecodes.
deps/v8/src/init/setup-isolate-full.cc Removes unconditional WASI debug prints.
deps/v8/src/init/bootstrapper.cc Removes unconditional WASI debug prints.
deps/v8/src/heap/setup-heap-internal.cc Removes WASI debug prints.
deps/v8/src/heap/read-only-promotion.cc Adds WASI-only diagnostics during RO promotion.
deps/v8/src/heap/marking-visitor-inl.h Adds disabled (#if 0) diagnostics block for wasm32 heap issues.
deps/v8/src/heap/mark-compact.cc Removes wasm32 MC_CLEAR trace macro body.
deps/v8/src/heap/mark-compact-inl.h Adds disabled (#if 0) diagnostics block for root marking.
deps/v8/src/heap/live-object-range-inl.h Adds disabled diagnostics; currently introduces unused locals outside guard.
deps/v8/src/heap/factory-base.cc Adds WASI read-only size guard for internalized string allocation.
deps/v8/src/heap/cppgc-js/cppgc-stubs.cc Implements String::Utf8Value stub with allocation and proper cleanup.
deps/v8/src/flags/flag-definitions.h Forces jitless/wasm_jitless and adjusts heap sizing defaults for wasm32.
deps/v8/src/execution/tiering-manager.cc Gates WASI debug trace behind V8_WASM32_DEBUG_TRACE.
deps/v8/src/execution/microtask-queue.h Adds WASI-specific microtasks runner declaration.
deps/v8/src/execution/isolate.cc Removes debug prints; adjusts microtask callback recursion behavior on WASI; implements wasm async resolve.
deps/v8/src/execution/execution.cc Adds wasm32 JS entry hook and uses it for invocation + WASI microtasks path.
deps/v8/src/common/segmented-table-inl.h Adds WASI allocator/alignment handling and avoids stub layout mismatch.
deps/v8/src/builtins/wasm32/builtins-wasm32-registry.cc Adds bounds check for builtin ID lookups.
deps/v8/src/builtins/wasm32/builtins-wasm32-abi.h Reduces interpreter frame slots for wasm32.
deps/v8/src/builtins/setup-builtins-internal.cc Removes WASI debug prints during builtin compilation/registration.
deps/v8/src/builtins/builtins.h Forces builtin Code objects to be mutable RO-space behavior on wasm32; extends API.
deps/v8/src/builtins/builtins-api.cc Adds optional raw-result out parameter and preserves result in WASI paths.
deps/v8/src/builtins/accessors.cc Removes WASI debug prints in accessor getter.
deps/v8/src/base/wasi-platform-stubs.cc Minor formatting for endif comment.
deps/v8/src/ast/scopes.cc Minor refactor to store literal in local before using scope.
deps/v8/src/api/api-natives.cc Removes WASI debug prints in InstantiateObject path.
deps/v8/include/wasi/wasi-v8-essential-constants.h Reorders includes and removes duplicated constants block.
deps/v8/include/wasi/v8config-wasi.h Includes v8-api-constants-wasi.h.
deps/v8/include/wasi/v8-value-inline-impl.h Implements Smi-only numeric conversions instead of returning 0.
deps/v8/include/wasi/v8-platform-wasi.h Fixes formatting and forward declarations for WASI platform header.
deps/v8/include/wasi/v8-local-handle-fixes.h Uses ToInternalAddress(handle) instead of handle.ptr().
deps/v8/include/wasi/v8-isolate-wasi-stub.h Replaces exception/callback stubs with real declarations bridged in api.cc.
deps/v8/include/wasi/v8-fixed-array-stub.h Replaces inline stubs with declarations for bridging implementations.
deps/v8/include/wasi/v8-api-stubs.h Adjusts formatting and removes duplicated MemoryPressureLevel stub.
deps/v8/include/v8config.h Adds V8_WASI_USE_CANONICAL_PLATFORM_HEADER define under WASI.
deps/v8/include/v8-tracing-base.h Uses platform header on WASI and adjusts formatting.
deps/v8/include/v8-thread-isolated-allocator.h Includes canonical platform header for WASI.
deps/v8/include/v8-platform.h Always includes v8-platform-original.h.
deps/v8/include/v8-platform-original.h Adds WASI enums/permissions bridging and a new PostDelayedTaskOnWorkerThread overload.
deps/v8/include/v8-handle-base.h Adds WASI handle equality helpers and forward declarations.
deps/v8/include/v8-callbacks.h Cleans up include order and guards GC enums/types; formats WASI callback typedef.
deps/v8/include/libplatform/libplatform.h Switches WASI to use platform original header and exports.
deps/v8/include/libplatform/libplatform-backup.h Uses platform original header.
deps/v8/include/cppgc/platform.h Adds missing overrides for WASI JobHandle.
deps/uv/uv.gyp Expands WASI host/target conditions and adjusts sources/defines.
deps/uv/src/unix/wasi-stubs.c Implements poll-based io polling for WASI and adds readiness yielding.
deps/uv/src/unix/tcp.c Checks io_start errors and feeds watcher for WASI/WASIX connect completion.
deps/uv/src/unix/fs.c Adjusts cloexec handling for WASI and tweaks request cleanup/freeing conditions.
deps/uv/src/unix/core.c Formatting changes in uv_run.
deps/uv/src/threadpool.c Adds synchronous work submission path on WASI; formatting changes in work_done.
deps/undici/src/lib/web/fetch/request.js Preserves headersList explicitly on clone for WASM32 bridge.
deps/undici/src/lib/web/fetch/headers.js Avoids Map iterable constructor path; copies headers explicitly.
deps/undici/src/lib/dispatcher/client-h2.js Avoids for await by using explicit iterator.next loop.
deps/undici/src/index-fetch.js Avoids .catch wrapper on wasm32 to preserve receiver semantics.
deps/openssl/openssl/providers/implementations/rands/seeding/rand_unix.c Uses __wasi_random_get as entropy source on WASI.
deps/openssl/openssl/providers/common/include/prov/der_wrap.h Adds generated DER OID header.
deps/openssl/openssl/providers/common/include/prov/der_ecx.h Replaces stub with generated DER ECX header.
deps/openssl/openssl/providers/common/der/der_wrap_gen.c Adds generated DER OID source.
deps/openssl/openssl/providers/common/der/der_ecx_gen.c Adds generated DER ECX OID source.
deps/openssl/openssl/providers/common/der/der_dsa_gen.c Adds generated DER DSA OID source.
deps/openssl/openssl/include/openssl/configuration.h Adds extensive OPENSSL_NO_* WASI configuration defines.
deps/openssl/openssl/include/openssl/bn.h Forces 32-bit BN config on WASI.
deps/openssl/openssl/include/crypto/bn_conf.h Switches BN config to THIRTY_TWO_BIT.
deps/openssl/openssl/crypto/x509/v3_addr.c Adds missing internal ASN.1 include.
deps/openssl/openssl/crypto/buildinf.h Sets platform to wasi-wasm32 and makes dirs overridable.
deps/openssl/openssl/crypto/bn/bn_local.h Removes hardcoded BN_BITS2 define.
deps/openssl/openssl.gyp Adds WASI includes/sources/defines via openssl_wasi.gypi and config defines.
deps/ncrypto/ncrypto.cc Removes WASI crypto stubs and gates BIO stdio usage behind OPENSSL_NO_STDIO.
deps/icu-small/source/tools/toolutil/collationinfo.h Adds a minimal CollationInfo stub header.
deps/icu-small/source/tools/toolutil/collationinfo.cpp Provides minimal stub CollationInfo implementations.
deps/icu-small/source/stubdata/stubdata.cpp Uses real empty ICU header for non-WASI builds.
deps/icu-small/source/stubdata/stubdata-wasi.cpp Provides minimal ICU stub symbols for WASI.
deps/icu-small/source/stubdata/stubdata-minimal.cpp Retains compatibility translation unit comment-only stub.
deps/icu-small/source/common/udata.cpp Changes data entry point from definition to extern declaration.
common.gypi Adjusts wasm32/WASI toolset condition and sets C++20 for WASI builds.
Review details

Suppressed comments (2)

deps/uv/src/unix/core.c:443

  • The timer pre-loop block has multiple statements and the closing brace on a single line. Please restore standard formatting for readability and consistency.
    src/node_options.cc:1618
  • This if (false && ...) block is permanently dead code and leaves behind a large debugging fprintf chunk in a hot bootstrap path. It should be removed (or gated behind a real build/runtime flag) to keep the codebase clean.
  • Files reviewed: 207/210 changed files
  • Comments generated: 10
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines 1 to 7
// WASI-specific stubdata symbols to satisfy linker requirements
#ifdef __wasi__
extern "C" {
// Provide minimal stub symbols for WASI builds
const unsigned char icudt77_dat[1] = {0};
const unsigned int icudt77_dat_size = 0;
extern const unsigned char icudt77_dat[1] = {0};
extern const unsigned int icudt77_dat_size = 0;
}
Comment on lines +56 to +63
const Address previous_object_address =
current_object_.is_null() ? kNullAddress : current_object_.address();
const int previous_object_size = current_size_;
const Address previous_map =
current_object_.is_null() ? kNullAddress : current_map_.ptr();
const int previous_type =
current_object_.is_null() ? -1
: static_cast<int>(current_map_->instance_type());
Comment on lines +469 to +486
#ifdef __wasi__
for (auto [src, dst] : moves) {
if (!IsCode(dst)) continue;
Tagged<Code> code = Cast<Code>(dst);
Tagged<CodeWrapper> wrapper = code->wrapper();
if (!HeapLayout::InReadOnlySpace(wrapper)) {
std::fprintf(stderr,
"WASM32_RO_CODE_WRAPPER src=0x%x dst=0x%x builtin=%d "
"wrapper=0x%x wrapper_in_moves=%d\n",
static_cast<unsigned>(src.ptr()),
static_cast<unsigned>(dst.ptr()),
static_cast<int>(code->builtin_id()),
static_cast<unsigned>(wrapper.ptr()),
moves.find(wrapper) != moves.end() ? 1 : 0);
std::fflush(stderr);
}
}
#endif
void SecureContext::New(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
new SecureContext(env, args.This());
auto* sc = new SecureContext(env, args.This());
Comment thread deps/uv/src/threadpool.c
Comment on lines +331 to 333
loop = container_of(handle, uv_loop_t, wq_async); uv_mutex_lock(&loop->wq_mutex);
uv__queue_move(&loop->wq, &wq);
uv_mutex_unlock(&loop->wq_mutex);
Comment thread deps/uv/src/unix/core.c
Comment on lines +434 to 435
r = uv__loop_alive(loop); if (!r)
uv__update_time(loop);
Comment on lines +805 to +809
if (!v8_flags.wasm_async_compilation || v8_flags.wasm_jitless
#ifdef __wasi__
|| true
#endif
) {
Comment thread src/api/embed_helpers.cc
Comment on lines 47 to 49
do {
if (env->is_stopping()) break;
uv_run(env->event_loop(), UV_RUN_DEFAULT);
if (env->is_stopping()) break; uv_run(env->event_loop(), UV_RUN_DEFAULT);
if (env->is_stopping()) break;
Comment thread src/timers.cc
Comment on lines 46 to 57
void BindingData::SlowScheduleTimer(const FunctionCallbackInfo<Value>& args) {
int64_t duration;
if (args[0]
->IntegerValue(args.GetIsolate()->GetCurrentContext())
.To(&duration)) {
ScheduleTimerImpl(Realm::GetBindingData<BindingData>(args), duration);
.To(&duration)) { ScheduleTimerImpl(Realm::GetBindingData<BindingData>(args), duration);
}
}

void BindingData::FastScheduleTimer(Local<Object> unused,
Local<Object> receiver,
int64_t duration) {
ScheduleTimerImpl(FromJSObject<BindingData>(receiver), duration);
int64_t duration) { ScheduleTimerImpl(FromJSObject<BindingData>(receiver), duration);
}
Comment on lines +14 to +15
cat "$output"
rg -q '^WASM32_AOT_STATS plans=[1-9][0-9]* completed=[1-9][0-9]* bailouts=[0-9]+$' "$output"
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