SpiderMonkey is the JavaScript engine used in Mozilla Firefox. This newsletter gives an overview of the JavaScript and WebAssembly work we’ve done as part of the Firefox 96 and 97 Nightly release cycles.
👷🏽♀️ JS features
- Contributor Nicolò Ribaudo implemented the Records/tuples proposal (disabled by default).
- Contributor Jake Champion implemented the New Set methods proposal (disabled by default).
- Contributor Jonatan Klemets finished the implementation of Import Assertions.
⚡ WebAssembly
- We landed the last bits of exception handling
- We enabled support for Memory64 by default in Nightly.
- We improved compiler optimizations for certain Int64 operations in the JIT backend.
- We’re experimenting with AVX2 support to optimize SIMD code better.
- We landed various optimizations to speed up indirect calls.
- We randomized stub placement to avoid icache thrashing.
- We fixed a performance cliff in the instruction reordering pass that slowed down compilation of certain modules.
❇️ Stencil
Stencil is our project to create an explicit interface between the frontend (parser, bytecode emitter) and the rest of the VM, decoupling those components. This lets us improve web-browsing performance, simplify a lot of code and improve bytecode caching.
- We changed the off-thread compilation APIs to work with stencils instead of scripts.
- Now that all off-thread parsing works with Stencils, we were able to remove a lot of complicated code: the off-thread parse global, the atom table lock, support for off-thread GC allocations, and parts of the XDR code. This is a significant milestone for the team.
- We added a mechanism to compile lazy functions based on a Stencil. This will let us delazify functions off-thread which is a new capability for the engine.
- We optimized and simplified the creation of permanent atoms on startup.
With these changes, we have completed our overhaul of the parser to the Stencil format. This included removing tricky off-thread GC allocations, replacing our bytecode format, decoupling the parser output from specific globals/documents, redesigning self-hosted JS, cleaning up internal representations of scripts, and cleaning up how script delazification works. Overall this has reduced memory usage (particularly for browser-internal JS), removed a lot of complexity and made the parser architecture more robust. This unlocks interesting future opportunities for better caching, scheduling, and speculation within the browser’s script-loader.
🚿DOM Streams
We’re moving our implementation of the Streams specification out of SpiderMonkey into the DOM. This lets us take advantage of Gecko’s WebIDL machinery, making it much easier for us to implement this complex specification in a standards-compliant way and stay up-to-date.
A complete implementation of ReadableStreams is under review, and we are working on making sure that the transition between the JS implementation and DOM implementation goes smoothly and invisibly. In parallel, contributor Tom Schuster has contributed an implementation of WritableStreams and is working on the pipeTo algorithm.
🌍 Unified Intl implementation
Work is underway to unify the Intl (Internalization) code in SpiderMonkey and the rest of Gecko as a shared mozilla::intl
component. This results in less code duplication and will make it easier to migrate from the ICU library to ICU4X in the future.
- We unified the implementation of DisplayNames.
🚀 JIT optimizations
- We added IC support for adding properties to objects with an addProperty hook. This speeds up adding properties to DOM objects.
- We added support for out-of-bounds accesses on optimized-out
arguments
objects. - We optimized code generation for derived class constructors by improving code folding.
- We added array and arguments scalar replacement for spread calls.
- We also added scalar replacement support for rest-parameters.
- We added Warp transpiler support for spread-new and spread-super calls.
- We optimized the in-operator for
arguments
objects.
🏎️ Performance
- We improved helper thread task scheduling by deprioritizing JIT compilation tasks when no JS is running.
- We fixed some issues that caused us to underestimate the nursery promotion rate.
- We removed some unnecessary checks from GC barriers.
- We optimized arena unmarking to avoid locking overhead.
- We added support for interruptible GC slice budgets.
- We changed the nursery’s fixup list to add items to the front instead of the back, to improve cache locality for nursery collections.
- We improved heuristics for decommitting memory to decommit less when allocating a lot of memory.
📚 Miscellaneous
- We updated ICU to version 70.
- We updated our implementation of async generators to reflect the latest spec changes.
- We cleaned up the VMFunction type definitions and templates.
- We fixed a lot of header file includes to improve compilation times.