SpiderMonkey Newsletter (Firefox 108-109)

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 108 and 109 Nightly release cycles.

The SpiderMonkey team is proud of everything we accomplished this year. Happy Holidays!

👷🏽‍♀️ New features

  • We’ve shipped Import Maps in Firefox 108.
  • We implemented Array.fromAsync (disabled by default).
  • We added support for more Wasm GC instructions (disabled by default).
  • We implemented more parts of the decorators proposal (disabled by default).

⚙️ 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 AreWeESMifiedYet website for the status of ESMification.
  • We modernized the module implementation to use more native C++ data structures instead of JS objects.

💾 Robust Caching

We’re working on better (in-memory) caching of JS scripts based on the new Stencil format. This will let us integrate better with other resource caches used in Gecko and might also allow us to potentially cache JIT-related hints.

The team is currently working on removing the dependency on JSContext for off-thread parsing. This will make it easier to integrate with browser background threads and will further simplify the JS engine.

  • We converted more code to use ErrorContext for allocations.
  • We changed some data structures to use global singletons instead of JSContext.

🚀 Performance

We continue to look for performance wins in a variety of areas to improve Speedometer and related benchmarks, as well as websites that are utilizing a lot of JavaScript code.

  • We inlined the megamorphic has-property cache lookup directly in JIT code.
  • We added an optimization to fold multiple IC stubs if they’re all identical except for a single shape guard. This improves performance for polymorphic property accesses.
  • We removed a lot of unnecessary C++ heap allocations in the IC code.
  • We changed the Cell header word to be non-atomic, to improve C++ code generation.
  • We added JIT inlining for new Object().
  • We added a fast path for plain objects to OrdinaryToPrimitive.
  • We optimized shape guards for objects on the prototype to have fewer memory loads.
  • We added JIT inlining for the .size getter on Map and Set.
  • We added an optimization to cache for-in iterators on the shape.
  • We improved charAt and charCodeAt JIT optimizations to support rope strings and out-of-bounds indexes.
  • We added JIT inlining for parseInt.
  • We improved string-to-atom performance by caching recently atomized strings.
  • We added JIT inlining for Number.prototype.toString when called with a base argument.
  • We eliminated redundant guards when adding multiple properties to an object.
  • We made a lot of changes to implement parallel marking in our GC (disabled by default).
  • We used signal handlers to optimize null checks in Wasm GC code.
  • We implemented support for FMA3 instructions for Wasm Relaxed SIMD.
  • We improved performance for growing Wasm tables by small amounts.

📚 Miscellaneous

  • We removed the Streams implementation from SpiderMonkey, now that it’s implemented outside the JS engine.
  • The fuzzing team landed some code to improve differential testing with the Fuzzilli JS fuzzer.
  • We simplified the profiler’s global JIT code table by reusing our AvlTree data structure instead of using a custom skip list implementation.
  • We improved our Shape data structures to use derived classes more to improve type safety and to simplify future changes.