Skip to content

JS shell on WASI: add basic Wizer integration for standalone testing.#46

Merged
cfallin merged 1 commit intobytecodealliance:fastly/ff-124-0-2from
cfallin:cfallin/standalone-wizer-support
Jul 18, 2024
Merged

JS shell on WASI: add basic Wizer integration for standalone testing.#46
cfallin merged 1 commit intobytecodealliance:fastly/ff-124-0-2from
cfallin:cfallin/standalone-wizer-support

Conversation

@cfallin
Copy link
Member

@cfallin cfallin commented Jul 18, 2024

This patch allows the use of a JS shell binary, compiled to wasm32-wasi (WASI ABI on WebAssembly), to make use of the Wizer snapshotting tool to embed JavaScript source with SpiderMonkey to run in a standalone Wasm module.

If enabled with --enable-js-shell-wizer, the shell no longer provides an interactive REPL; instead, when invoked during the "initialization" phase of Wizer, it reads JS source on standard input, then saves JS state (the global, the context, etc) for later. When the execution is snapshotted and the snapshot is later executed as an ordinary WASI command, the resume entry-point invokes a JS function named main in the global scope, if any.

An example of how to use this follows:

$ echo "function main() { print('hello world'); }" | \
  wizer --allow-wasi --wasm-bulk-memory=true -r _start=wizer.resume obj-release/dist/bin/js \
  -o snapshotted.wasm

$ wasmtime snapshotted.wasm
hello world
$

Note that embedders of SpiderMonkey on Wasm can and do add their own Wizer integration; the purpose of this PR is to add a standalone mode that does not require building SpiderMonkey within another context in order to evaluate features (such as AOT compilation) that require snapshotting as a prerequisite. Followup PRs will include test results derived with this simple Wizer integration.

Copy link
Collaborator

@JakeChampion JakeChampion left a comment

Choose a reason for hiding this comment

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

Approved but I think we might need to include a copy of the Wizer license within third_party/wizer

This patch allows the use of a JS shell binary, compiled to
`wasm32-wasi` (WASI ABI on WebAssembly), to make use of the Wizer
snapshotting tool to embed JavaScript source with SpiderMonkey to run in
a standalone Wasm module.

If enabled with `--enable-js-shell-wizer`, the shell no longer provides
an interactive REPL; instead, when invoked during the "initialization"
phase of Wizer, it reads JS source on standard input, then
saves JS state (the global, the context, etc) for later. When the
execution is snapshotted and the snapshot is later executed as an
ordinary WASI command, the resume entry-point invokes a JS function
named `main` in the global scope, if any.

An example of how to use this follows:

```
$ echo "function main() { print('hello world'); }" | \
  wizer --allow-wasi -r _start=wizer.resume obj-release/dist/bin/js \
  -o snapshotted.wasm

$ wasmtime snapshotted.wasm
hello world
$
```

Note that embedders of SpiderMonkey on Wasm can and do add their own
Wizer integration; the purpose of this PR is to add a standalone mode
that does not require building SpiderMonkey within another context in
order to evaluate features (such as AOT compilation) that require
snapshotting as a prerequisite. Followup PRs will include test results
derived with this simple Wizer integration.
@cfallin cfallin force-pushed the cfallin/standalone-wizer-support branch from 04e60ff to 04939d8 Compare July 18, 2024 16:35
@cfallin cfallin merged commit 689415f into bytecodealliance:fastly/ff-124-0-2 Jul 18, 2024
@cfallin cfallin deleted the cfallin/standalone-wizer-support branch July 18, 2024 16:35
cfallin added a commit to cfallin/spidermonkey-wasi-embedding that referenced this pull request Jul 25, 2024
This pulls in work from

- bytecodealliance/gecko-dev#45 (Add ahead-of-time ICs.)
- bytecodealliance/gecko-dev#46 (JS shell on WASI: add basic Wizer
  integration for standalone testing.)
- bytecodealliance/gecko-dev#47 (Update PBL for performance and in
  preparation for applying weval.)
- bytecodealliance/gecko-dev#48 (Add weval support to PBL.)

as originally PR'd onto a SpiderMonkey v124.0.2 branch then rebased to
v127.0.2 in bytecodealliance/gecko-dev#51.
cfallin added a commit to cfallin/spidermonkey-wasi-embedding that referenced this pull request Jul 26, 2024
This pulls in work from

- bytecodealliance/gecko-dev#45 (Add ahead-of-time ICs.)
- bytecodealliance/gecko-dev#46 (JS shell on WASI: add basic Wizer
  integration for standalone testing.)
- bytecodealliance/gecko-dev#47 (Update PBL for performance and in
  preparation for applying weval.)
- bytecodealliance/gecko-dev#48 (Add weval support to PBL.)

as originally PR'd onto a SpiderMonkey v124.0.2 branch then rebased to
v127.0.2 in bytecodealliance/gecko-dev#51.
cfallin added a commit to cfallin/js-compute-runtime that referenced this pull request Aug 1, 2024
This PR pulls in my work to use "weval", the WebAssembly partial
evaluator, to perform ahead-of-time compilation of JavaScript using the
PBL interpreter we previously contributed to SpiderMonkey. This work has
been merged into the BA fork of SpiderMonkey in
bytecodealliance/gecko-dev#45,  bytecodealliance/gecko-dev#46,
bytecodealliance/gecko-dev#47, bytecodealliance/gecko-dev#48,
bytecodealliance/gecko-dev#51, bytecodealliance/gecko-dev#52,
bytecodealliance/gecko-dev#53, bytecodealliance/gecko-dev#54,
bytecodealliance/gecko-dev#55, and then integrated into StarlingMonkey
in bytecodealliance/StarlingMonkey#91.

The feature is off by default; it requires a `--enable-experimental-aot`
flag to be passed to `js-compute-runtime-cli.js`. This requires a
separate build of the engine Wasm module to be used when the flag is
passed.

This should still be considered experimental until it is tested more
widely. The PBL+weval combination passes all jit-tests and jstests in
SpiderMonkey, and all integration tests in StarlingMonkey; however, it
has not yet been widely tested in real-world scenarios.

Initial speedups we are seeing on Octane (CPU-intensive JS benchmarks)
are in the 3x-5x range. This is roughly equivalent to the speedup that a
native JS engine's "baseline JIT" compiler tier gets over its
interpreter, and it uses the same basic techniques -- compiling all
polymorphic operations (all basic JS operators) to inline-cache sites
that dispatch to stubs depending on types. Further speedups can be
obtained eventually by inlining stubs from warmed-up IC chains, but that
requires warmup.

Important to note is that this compilation approach is *fully
ahead-of-time*: it requires no profiling or observation or warmup of
user code, and compiles the JS directly to Wasm that does not do any
further codegen/JIT at runtime. Thus, it is suitable for the per-request
isolation model (new Wasm instance for each request, with no shared
state).
cfallin added a commit to cfallin/js-compute-runtime that referenced this pull request Aug 1, 2024
This PR pulls in my work to use "weval", the WebAssembly partial
evaluator, to perform ahead-of-time compilation of JavaScript using the
PBL interpreter we previously contributed to SpiderMonkey. This work has
been merged into the BA fork of SpiderMonkey in
bytecodealliance/gecko-dev#45,  bytecodealliance/gecko-dev#46,
bytecodealliance/gecko-dev#47, bytecodealliance/gecko-dev#48,
bytecodealliance/gecko-dev#51, bytecodealliance/gecko-dev#52,
bytecodealliance/gecko-dev#53, bytecodealliance/gecko-dev#54,
bytecodealliance/gecko-dev#55, and then integrated into StarlingMonkey
in bytecodealliance/StarlingMonkey#91.

The feature is off by default; it requires a `--enable-experimental-aot`
flag to be passed to `js-compute-runtime-cli.js`. This requires a
separate build of the engine Wasm module to be used when the flag is
passed.

This should still be considered experimental until it is tested more
widely. The PBL+weval combination passes all jit-tests and jstests in
SpiderMonkey, and all integration tests in StarlingMonkey; however, it
has not yet been widely tested in real-world scenarios.

Initial speedups we are seeing on Octane (CPU-intensive JS benchmarks)
are in the 3x-5x range. This is roughly equivalent to the speedup that a
native JS engine's "baseline JIT" compiler tier gets over its
interpreter, and it uses the same basic techniques -- compiling all
polymorphic operations (all basic JS operators) to inline-cache sites
that dispatch to stubs depending on types. Further speedups can be
obtained eventually by inlining stubs from warmed-up IC chains, but that
requires warmup.

Important to note is that this compilation approach is *fully
ahead-of-time*: it requires no profiling or observation or warmup of
user code, and compiles the JS directly to Wasm that does not do any
further codegen/JIT at runtime. Thus, it is suitable for the per-request
isolation model (new Wasm instance for each request, with no shared
state).
cfallin added a commit to cfallin/js-compute-runtime that referenced this pull request Aug 1, 2024
This PR pulls in my work to use "weval", the WebAssembly partial
evaluator, to perform ahead-of-time compilation of JavaScript using the
PBL interpreter we previously contributed to SpiderMonkey. This work has
been merged into the BA fork of SpiderMonkey in
bytecodealliance/gecko-dev#45,  bytecodealliance/gecko-dev#46,
bytecodealliance/gecko-dev#47, bytecodealliance/gecko-dev#48,
bytecodealliance/gecko-dev#51, bytecodealliance/gecko-dev#52,
bytecodealliance/gecko-dev#53, bytecodealliance/gecko-dev#54,
bytecodealliance/gecko-dev#55, and then integrated into StarlingMonkey
in bytecodealliance/StarlingMonkey#91.

The feature is off by default; it requires a `--enable-experimental-aot`
flag to be passed to `js-compute-runtime-cli.js`. This requires a
separate build of the engine Wasm module to be used when the flag is
passed.

This should still be considered experimental until it is tested more
widely. The PBL+weval combination passes all jit-tests and jstests in
SpiderMonkey, and all integration tests in StarlingMonkey; however, it
has not yet been widely tested in real-world scenarios.

Initial speedups we are seeing on Octane (CPU-intensive JS benchmarks)
are in the 3x-5x range. This is roughly equivalent to the speedup that a
native JS engine's "baseline JIT" compiler tier gets over its
interpreter, and it uses the same basic techniques -- compiling all
polymorphic operations (all basic JS operators) to inline-cache sites
that dispatch to stubs depending on types. Further speedups can be
obtained eventually by inlining stubs from warmed-up IC chains, but that
requires warmup.

Important to note is that this compilation approach is *fully
ahead-of-time*: it requires no profiling or observation or warmup of
user code, and compiles the JS directly to Wasm that does not do any
further codegen/JIT at runtime. Thus, it is suitable for the per-request
isolation model (new Wasm instance for each request, with no shared
state).
cfallin added a commit to cfallin/js-compute-runtime that referenced this pull request Aug 1, 2024
This PR pulls in my work to use "weval", the WebAssembly partial
evaluator, to perform ahead-of-time compilation of JavaScript using the
PBL interpreter we previously contributed to SpiderMonkey. This work has
been merged into the BA fork of SpiderMonkey in
bytecodealliance/gecko-dev#45,  bytecodealliance/gecko-dev#46,
bytecodealliance/gecko-dev#47, bytecodealliance/gecko-dev#48,
bytecodealliance/gecko-dev#51, bytecodealliance/gecko-dev#52,
bytecodealliance/gecko-dev#53, bytecodealliance/gecko-dev#54,
bytecodealliance/gecko-dev#55, and then integrated into StarlingMonkey
in bytecodealliance/StarlingMonkey#91.

The feature is off by default; it requires a `--enable-experimental-aot`
flag to be passed to `js-compute-runtime-cli.js`. This requires a
separate build of the engine Wasm module to be used when the flag is
passed.

This should still be considered experimental until it is tested more
widely. The PBL+weval combination passes all jit-tests and jstests in
SpiderMonkey, and all integration tests in StarlingMonkey; however, it
has not yet been widely tested in real-world scenarios.

Initial speedups we are seeing on Octane (CPU-intensive JS benchmarks)
are in the 3x-5x range. This is roughly equivalent to the speedup that a
native JS engine's "baseline JIT" compiler tier gets over its
interpreter, and it uses the same basic techniques -- compiling all
polymorphic operations (all basic JS operators) to inline-cache sites
that dispatch to stubs depending on types. Further speedups can be
obtained eventually by inlining stubs from warmed-up IC chains, but that
requires warmup.

Important to note is that this compilation approach is *fully
ahead-of-time*: it requires no profiling or observation or warmup of
user code, and compiles the JS directly to Wasm that does not do any
further codegen/JIT at runtime. Thus, it is suitable for the per-request
isolation model (new Wasm instance for each request, with no shared
state).
cfallin added a commit to cfallin/js-compute-runtime that referenced this pull request Aug 1, 2024
This PR pulls in my work to use "weval", the WebAssembly partial
evaluator, to perform ahead-of-time compilation of JavaScript using the
PBL interpreter we previously contributed to SpiderMonkey. This work has
been merged into the BA fork of SpiderMonkey in
bytecodealliance/gecko-dev#45,  bytecodealliance/gecko-dev#46,
bytecodealliance/gecko-dev#47, bytecodealliance/gecko-dev#48,
bytecodealliance/gecko-dev#51, bytecodealliance/gecko-dev#52,
bytecodealliance/gecko-dev#53, bytecodealliance/gecko-dev#54,
bytecodealliance/gecko-dev#55, and then integrated into StarlingMonkey
in bytecodealliance/StarlingMonkey#91.

The feature is off by default; it requires a `--enable-experimental-aot`
flag to be passed to `js-compute-runtime-cli.js`. This requires a
separate build of the engine Wasm module to be used when the flag is
passed.

This should still be considered experimental until it is tested more
widely. The PBL+weval combination passes all jit-tests and jstests in
SpiderMonkey, and all integration tests in StarlingMonkey; however, it
has not yet been widely tested in real-world scenarios.

Initial speedups we are seeing on Octane (CPU-intensive JS benchmarks)
are in the 3x-5x range. This is roughly equivalent to the speedup that a
native JS engine's "baseline JIT" compiler tier gets over its
interpreter, and it uses the same basic techniques -- compiling all
polymorphic operations (all basic JS operators) to inline-cache sites
that dispatch to stubs depending on types. Further speedups can be
obtained eventually by inlining stubs from warmed-up IC chains, but that
requires warmup.

Important to note is that this compilation approach is *fully
ahead-of-time*: it requires no profiling or observation or warmup of
user code, and compiles the JS directly to Wasm that does not do any
further codegen/JIT at runtime. Thus, it is suitable for the per-request
isolation model (new Wasm instance for each request, with no shared
state).
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