So, we are adding a backend for the SpiderMonkey’s codegen to enable JIT
support for JavaScript running through Wasm. Sounds a bit cryptic so let’s
divide it into parts.
SpiderMonkey is a JavaScript engine which is used for running JavaScript inside
the Firefox browser. SpiderMonkey is written in C++ and supports compilation
into the Wasm module, see live demo -
https://mozilla-spidermonkey.github.io/sm-wasi-demo/. However, SpiderMonkey
compiled into the Wasm module supports execution of JavaScript only in the
interpreter-only mode and it doesn’t support just-in-time compilation because
there is no Wasm backend for that. There are backends for Arm, X86, X64 etc but
there is none for Wasm.
Why do we want to add support for JIT? Well, because we want speed. Right now
there is no solution to run JS scripts via Wasm fast, there are only
interpreters.
Why does JIT improve performance?
The reasons are the same for why an interpreter is slower than a compiler -
because it eliminates the interpreter loop, uses a more efficient ABI and, more
importantly, it can specialize polymorphic operations in JavaScript. So, we not
only enable the JIT tier in SpiderMonkey for Wasm but we also provide support
for inline caches.
Inline caches is a mechanism for specializing the behavior of particular
operations like plus or a call to specific arguments provided at runtime.
With all that we can generate Wasm modules on the fly, instantiate them, and
link them to provide from ~2x to ~11x speedup over the interpreter. In the
talks we will cover how the whole scheme works with SpiderMonkey: 1. How to
link modules on the fly into SpiderMonkey.wasm 2. How to add an exotic Wasm
backend into SpiderMonkey’s supported backend line - X64, X86, Arm, Wasm 3. How
to use the whole solution in the cloud instead of QuickJS 4. How to get a
speedup of your JS over wasm with test data.
Wasm I/O 2024
14 - 15 Mar, 2024
Barcelona
https://2024.wasmio.tech/
8. Wishful thinking
+ Better than interpreter throughput
+ Industrial support of new features of JS
+ Reasonable size
+ Preprocessing and/or AOT support
37. Resume of compilation
1. Recreate CFG from Masm
2. Use the structured property of SpiderMonkey to layout blocks
3. Represent registers as parameters
4. Import __stack_pointer to maintain the same stack structure
40. Code installation
How to use freshly compiled wasm code?
Solution:
● wasmtime is able to compile and instantiate new modules at runtime
● we will patch SpiderMonkey memory to “install” code
84. Sharing scheme
● SpiderMonkey code is shared
● One instance per client
● jit_module is used to install previously compiled code
85. Call compilation each time
● Emulation native SpiderMonkey
● Slow, because we don’t batch compilation calls and run compilation at runtime
● Used for tests
86. Resume
● Implemented new Wasm backend for SpiderMonkey
● Supported ICs and provided promising perf results - from 2x to 11x
● Passed most of the 83% of jit-tests
● Provided interesting modes of execution for embedding or cloud
● Unblocked higher JIT tiers like Warp or Ion
87. Thanks
● Thanks to all people from Shopify involved for sponsoring this work
○ Special thanks to Mike Shaver and Saúl Cabrera who patiently provides us
feedback for our work
● Thanks to SpiderMonkey team for reviewing our patches