WarpMonkey

tosh1 pts0 comments

SpiderMonkey — Firefox Source Docs documentation

SpiderMonkey

Report an issue<br>View page source

SpiderMonkey

SpiderMonkey is the JavaScript and WebAssembly implementation library of<br>the Mozilla Firefox web browser. The implementation behaviour is defined by<br>the ECMAScript and WebAssembly specifications.

Much of the internal technical documentation of the engine can be found<br>throughout the source files themselves by looking for comments labelled with<br>[SMDOC]. Information about the team, our processes, and about embedding<br>SpiderMonkey in your own projects can be found at https://spidermonkey.dev.

Specific documentation on a few topics is available at:

Building and testing SpiderMonkey

Running Automated JavaScript Tests

Hacking Tips

SavedFrame

JavaScript Language Feature Checklist

So You Want to Add a Bytecode Op

Adding Use Counter Telemetry to the JS Engine

How SpiderMonkey Optimizes

Inline caches / CacheIR

Debugger API

Components of SpiderMonkey

🧹 Garbage Collector

JavaScript is a garbage collected language and at the core of SpiderMonkey<br>we manage a garbage-collected memory heap. Elements of this heap have a base<br>C++ type of gc::Cell. Each round of garbage collection will free up any<br>Cell that is not referenced by a root or another live Cell in turn.

See GC overview for more details.

📦 JS::Value and JSObject

JavaScript values are divided into either objects or primitives<br>(Undefined, Null, Boolean, Number, BigInt, String, or Symbol).<br>Values are represented with the JS::Value type which may in turn point to<br>an object that extends from the JSObject type. Objects include both plain<br>JavaScript objects and exotic objects representing various things from<br>functions to ArrayBuffers to HTML Elements and more.

Most objects extend NativeObject (which is a subtype of JSObject)<br>which provides a way to store properties as key-value pairs similar to a hash<br>table. These objects hold their values and point to a Shape that<br>represents the set of keys. Similar objects point to the same Shape which<br>saves memory and allows the JITs to quickly work with objects similar to ones<br>it has seen before. See the [SMDOC] Shapes comment for more details.

C++ (and Rust) code may create and manipulate these objects using the<br>collection of interfaces we traditionally call the JSAPI .

🗃️ JavaScript Parser

In order to evaluate script text, we parse it using the Parser into an<br>Abstract Syntax Tree (AST) temporarily and then run the BytecodeEmitter<br>(BCE) to generate Bytecode and associated metadata. We refer to this<br>resulting format as Stencil and it has the helpful characteristic that it<br>does not utilize the Garbage Collector. The Stencil can then be<br>instantiated into a series of GC Cells that can be mutated and understood<br>by the execution engines described below.

Each function as well as the top-level itself generates a distinct script.<br>This is the unit of execution granularity since functions may be set as<br>callbacks that the host runs at a later time. There are both<br>ScriptStencil and js::BaseScript forms of scripts.

By default, the parser runs in a mode called syntax or lazy parsing where<br>we avoid generating full bytecode for functions within the source that we are<br>parsing. This lazy parsing is still required to check for all early errors<br>that the specification describes. When such a lazily compiled inner function<br>is first executed, we recompile just that function in a process called<br>delazification. Lazy parsing avoids allocating the AST and bytecode which<br>saves both CPU time and memory. In practice, many functions are never<br>executed during a given load of a webpage so this delayed parsing can be<br>quite beneficial.

⚙️ JavaScript Interpreter

The bytecode generated by the parser may be executed by an interpreter<br>written in C++ that manipulates objects in the GC heap and invokes native<br>code of the host (eg. web browser). See [SMDOC] Bytecode Definitions for<br>descriptions of each bytecode opcode and js/src/vm/Interpreter.cpp for<br>their implementation.

⚡ JavaScript JITs

In order to speed up execution of bytecode, we use a series of Just-In-Time<br>(JIT) compilers to generate specialized machine code (eg. x86, ARM, etc)<br>tailored to the JavaScript that is run and the data that is processed.

As an individual script runs more times (or has a loop that runs many times)<br>we describe it as getting hotter and at certain thresholds we tier-up by<br>JIT-compiling it. Each subsequent JIT tier spends more time compiling but<br>aims for better execution performance.

Baseline Interpreter

The Baseline Interpreter is a hybrid interpreter/JIT that interprets the<br>bytecode one opcode at a time, but attaches small fragments of code called<br>Inline Caches (ICs) that rapidly speed-up executing the same opcode the next<br>time (if the data is similar enough). See the [SMDOC] JIT Inline Caches<br>comment for more details.

Baseline Compiler

The Baseline Compiler use the same Inline Caches mechanism from the<br>Baseline Interpreter but additionally...

spidermonkey javascript objects bytecode interpreter time

Related Articles