SpiderMonkey Newsletter (Firefox 94-95)

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 94 and 95 Nightly release cycles.

👷🏽‍♀️ JS features

⚡ WebAssembly

  • We landed more changes for Wasm exception support.
  • Executable code for Wasm modules can now be cached in the network cache. We also added gzip compression for this.
  • The fuzzing team integrated the wasm-smith fuzzer in SpiderMonkey.
  • We prototyped various instructions that are part of the Relaxed SIMD proposal.
  • Code allocation failures are now reported to the console.
  • We fixed a performance cliff in the register allocator that caused hangs on certain large Wasm modules.
  • We landed the remaining functionality for Wasm64.
  • Type definitions for Wasm GC support are now properly collected.

❇️ 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’ve migrated Gecko’s ScriptPreloader to use the new Stencil XDR serialization format.
  • We were then able to remove the legacy, error-prone XDR code and replace the JSScript cloning mechanism with sharing stencils.
  • These changes also allowed us to tighten invariants for scripts with non-syntactic scopes, allowing us to move certain checks from the VM to the bytecode emitter.
  • We optimized string literals to not always require atomization because this can be slow.
  • With these changes, the new Stencil architecture is utilized for all existing scenarios and the error-prone legacy code is now all removed. This unified architecture allows us to continue improving caching and speculation techniques with far less risk of stability or correctness bugs. Congratulations to the team for passing this milestone. 🎉

🚿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 preliminary implementation of ReadableStreams (without integration into other browser specifications) has landed disabled, but it’s a bit too early for people to play with yet.

🧹Garbage Collection

  • We fixed a memory leak involving weak maps. This leak affected some popular websites.
  • We changed permanent atoms and symbols to always be marked, this let us remove checks for this from the marking path.
  • We optimized gray root marking to be incremental. This fixes a source of long GC slices.
  • We fixed the rooting hazard static analysis to handle virtual method calls better. We also parallelized the call graph generation step.
  • We removed some overhead from the gray unmarking code that showed up in hang stacks.
  • We fixed a performance issue where we could collect the nursery even if it’s empty or disabled.

🌍 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.

🗂 ReShape

ReShape is a project to optimize and simplify our object layout and property representation after removing TI. This will help us fix some long-standing issues related to performance, memory usage and code complexity.

  • We optimized object allocation by moving handling of TypedArrays and ArrayBuffers out of the generic allocation path
  • We were then able to remove the NewObjectCache, saving some memory.
  • We optimized property enumeration for for-in with null/undefined to reuse the same empty iterator.
  • We optimized the generic property enumeration code to do less work in most cases.

📚 Miscellaneous

  • We added a better JSAPI based on templates for Typed Arrays and ArrayBuffers.
  • We are experimenting with suppressing the lazy parser when parsing off-main-thread. This improves page load performance in a number of scenarios.
  • We optimized comparisons with small constant strings to generate specialized JIT code.
  • We optimized comparisons of the form typeof x === "y". This fixes an old bug that was filed almost 10 years ago!
  • We moved the documentation for running our test suites into firefox-source-docs.
  • We optimized some code in the register allocator to avoid iterating over many unrelated registers.
  • We added markers to JIT code generation debug output to make the output easier to read.
  • We started tidying up and enforcing invariants for the context’s exception state.
  • We fixed a performance issue where JS code throwing many exceptions was very slow due to collecting exception stacks.
  • Lukas.bernhard added shape information to our CacheIR Health Report tool.
  • TheIDInside updated the UI for CacheIR Health Report to add a filter for JS opcodes.