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 102 and 103 Nightly release cycles.
👷🏽♀️ New features
- We’ve implemented the array
findLast
/findLastIndex
proposal (disabled by default). - We’ve added support for structured cloning of
Error
objects. - We’ve implemented WebAssembly relaxed SIMD dot-instructions.
⚙️ Modernizing JS modules
We’re working on improving our implementation of modules. This includes supporting modules in Workers, adding support for Import Maps, and ESMification (replacing the JSM module system for Firefox internal JS code with standard ECMAScript modules).
- See the ESMification update sent to dev-platform for the status of that project.
- We removed use of
globalThis
to prepare for moving to ESM. - We added support for ESMs in ChromeUtils.registerWindowActor.
- We added support for lazy loading ESMs.
- We added linting and cleaned up use of
this
for lazy getters. - We introduced a shim to make the transition to ESM as painless as possible.
- We removed use of
- We implemented a prototype of ImportMaps.
- We refactored both the representation of scripts and the loader itself.
⏱️ Profiler support
We’ve collaborated with the performance team to improve support for external profilers such as perf on Linux:
- The performance team has added support for perf’s jitdump format. This makes it possible to see JS functions in perf profiles. It also lets us annotate assembly code with LIR and CacheIR instruction names.
- We made changes to the JITs to preserve and use frame pointers for all JIT frames. Profilers such as perf (and other stack unwinders) are now able to reliably unwind through JIT frames by following frame pointers.
- We’ve simplified and optimized code in the JITs by taking advantage of frame pointers.
- We fixed an issue with the C++ interpreter’s profiler instrumentation for resumed async functions and generators. This could result in missing frames in the Firefox profiler.
🚀 JS Performance
- We’ve changed the bytecode we generate for
try-finally
to support functions withfinally
blocks in the optimizing JIT. This fixes an old performance cliff. - We’ve optimized the code we generate for test expressions.
- More typed array builtins that use a callback function are now marked as inlinable.
- We’ve optimized arguments-object allocation for inlined functions.
- We’ve implemented a new bytecode instruction for closing iterators, to reduce bytecode size for for-of loops.
- We’ve landed more optimizations for concurrent delazification (disabled by default).
🏎️ WebAssembly Performance
- We’ve re-enabled code caching with a new serialization system.
- We’ve landed more optimizations for SIMD instructions.
- We’ve replaced some uses of splay trees with AVL trees to improve compilation time.
- We’ve reduced the offset guard memory reservation from 2 GB to 32 MB. This shrinks the amount of virtual memory we reserve for Wasm code by 33%.
📚 Miscellaneous
- We’ve added a checklist for implementing new JS language features.
- We’ve imported the latest version of Test262.
- We’ve improved tracking and assertions for the GC retained heap size.
- We’ve migrated our string-to-double code to use the modern double-conversion library instead of our old dtoa.c fork.
- We’ve implemented support for
Rooted<Result<V,E>>
. - We’ve added a command-line argument to the JS shell for setting GC parameters.
- We’ve started to remove typedefs for various GC types. For example, we now use
Rooted<Shape*>
instead of the oldRootedShape
typedef. - We’ve improved telemetry for full GCs to be more useful.