The SpiderMonkey team is experimenting with a newsletter at the end of each release cycle for status updates on ongoing projects, new features and contributor work. The format may change over time as we figure out what works best. This is our first newsletter and we’d love to hear your feedback!
Contributors
- Adam Holm converted more code to the bytecode iterator interface.
- André Bargull contributed many patches, for example JIT optimizations for BigInt, code cleanup and TypedArray index changes. He also implemented various new language features (see below).
- Rohit Awate improved error messages in the parser for numeric separators.
- Philip Chimento contributed fixes for embedding SpiderMonkey in other projects.
JavaScript
New features
- Yulia Startsev implemented the nullish coalescing (??) operator.
- André Bargull added String.prototype.replaceAll (Nightly-only for now).
- André also implemented Promise.any (Nightly-only for now).
- André also added support for many stage 3 Intl proposals. Many of them are Nightly-only because they depend on missing ICU functionality.
GC-free parsing
The JS engine is able to parse scripts on a background thread to improve page load performance. This currently requires support for off-thread GC allocation and collection, but this comes with a lot of complexity and performance cliffs. To address this, Matthew Gaudet is refactoring the frontend so all GC allocation will happen on the main thread.
This cycle Matthew has been working on moving an increasing number of GC allocations to after parsing or bytecode emission (this work currently requires a JS shell flag). Chris Fallin did the object literal part of this work. Next up is investigating doing the same for atoms.
Merging JSScript and LazyScript
SpiderMonkey can do full parsing (and bytecode generation) of JS functions lazily. This is great for performance and memory usage because most functions are never called. However, our representation of such ‘lazy functions’ came with a lot of complexity and limitations. Ted Campbell has been incrementally working towards merging the JSScript and LazyScript types to simplify this and improve performance and memory usage.
Regular Expression backend update
Our regular expression backend is a fork of V8’s irregexp engine. To support new regular expression features and to improve performance, Iain Ireland is working on a new import of the upstream irregexp code. The plan is to use a shim layer where possible so it will be much easier to do future updates.
WeakRefs
The GC team has started implementing the WeakRef/FinalizationGroup proposal. This is an advanced feature that can be used to keep track of objects without keeping them alive, and also get a callback when an object dies (is collected by the GC). This is not expected to be widely used by developers, but is essential for some use cases. For example it can be used to create a system of cross-worker proxies, whereby objects in different processes can refer to one another without leaking memory. A motivating use case is in supporting collection of acyclic references between WebAssembly and JS.
WritableStream
ReadableStream was implemented a few years ago, but we were still missing support for WritableStream. Jeff Walden has been working on landing WritableStream support (behind a pref for now).
Object representation investigation
Each JS object currently has both a Shape and ObjectGroup pointer. The shape and group distinction is subtle and we’d like to get this down to one pointer per object. We’ve discussed various strategies here, from Shypes to the more recent Shuples idea. Chris Fallin is leading this effort. As part of this project he noticed JS functions currently account for a large number of groups and has been prototyping ways to address this.
IonBuilder changes
IonBuilder is the ‘front-end’ of the Ion optimizing JIT, where MIR is generated from bytecode. We’re planning some large changes in this area in 2020 and this cycle Jan de Mooij landed the first part of this work, simplifying how control flow is handled. This ended up removing around 2500 lines of code, helps decoupling IonBuilder from the bytecode emitter, and unlocks future bytecode and IonBuilder changes.
Debugger
Logan Smyth and Jim Blandy are extending the Debugger API to include async/await calls in stack traces. When this work is complete, calls to async functions that are awaiting a promise of another async function’s return value will appear on the stack in the firefox JavaScript debugger. This requires Debugger API extensions to get the promise of the return value from a Debugger.Frame for an async call; to obtain a promise’s reaction records; and to access the script, bytecode offset, callee function, etc. of a suspended call.
Miscellaneous
- Anthony Ramine from the Servo team improved and slimmed down standalone SpiderMonkey tarballs.
- Jon Coppeard fixed an issue where the GC could block the main thread when all helper threads were busy. Telemetry infrastructure detected an improvement after this landed.
- Jan de Mooij changed the internal JS string representation so strings are no longer null-terminated. This removed a lot of complexity and saved a bit of memory.
- Caroline Cullen is working on landing XDR encoded modules. This will eventually allow caching standard modules instead of JSM in the browser frontend.
WebAssembly
Bulk memory operations
Ryan Hunt optimized the memory.copy
and memory.fill
operations for the bulk memory operations proposal.
Wasm/JS fast calls with references
Lars Hansen made calls between JS and wasm much faster when JS values are passed via anyref.
Wasm Cranelift
Cranelift is a code generator (written in Rust) that we want to use in Firefox as the next optimizing compiler for WebAssembly.
- There has been a lot of work on the Wasm SIMD implementation on x86-64 by @abrown.
- @nbp and @sstangl switched the control-flow layout representation from extended basic blocks (EBB) to basic blocks. (Extended blocks can have side-exits, i.e. conditional jumps within the block, and were supposed to reduce memory, but introduced more complexity for all optimization passes and algorithms.)
- Support for wasm multi-value has landed in Cranelift, thanks to @fitzgen. It’s not available in Cranelift-in-Spidermonkey yet.
- Support for more int128 opcodes has been landing, thanks to @krk, @bjorn3 and @ryzokuken. While not directly useful for wasm in Spidermonkey, it’s useful for the rustc Cranelift backend.
- Ongoing work on register allocation is happening, to replace the current graph coloring algorithm by the same backtracking algorithm as the one used in Spidermonkey’s high-end optimizing compiler IonMonkey.
- Many miscellaneous contributions from external contributors: @jyn514, @data-pup, @projal, @XAMPPRocky, @oli-cosmian, @joshtriplett, @yjhmelody (in no particular order). From Mozilla contributors too: @peterhuene, @sstangl, @bnjbvr, @alexcrichton, @sunfishcode.
Ongoing work
- The multi-value proposal allows WebAssembly functions and blocks to return multiple values. Andy Wingo from Igalia is making steady progress implementing this feature in SpiderMonkey.
- Igalia (Asumu Takikawa) is also working on the JS-BigInt-integration proposal, so i64 values in WebAssembly can be converted to/from JavaScript BigInt.
- Tom Tung, Anne van Kesteren and others are working on re-enabling SharedArrayBuffer by default.