How the engine works: a recap
How V8 prepares code, executes functions, and manages memory.
We will recap the JavaScript Engine section: how the engine prepares and executes code, stores objects, and releases memory.
V8 receives JavaScript source text and prepares instructions to execute it. Consider a function that creates an enemy object:
function spawnEnemy() {
return { hp: 100 };
}
From source text to execution
An interactive diagram for the example above. Each stage passes its result to the next. V8's parser receives tokens from the scanner as it parses; these actions are separated here. The tree and bytecode are simplified.
-
The scanner recognizes tokens
Splits the text into parts: the word
return, the property namehp, the number100, braces, and other symbols.Text → tokensWaiting for source text.
Tokens → parserfunctionspawnEnemy(){return{hp:100};} -
The parser builds the AST
Builds a tree from the tokens to describe the program's structure. Here, the tree shows that the function returns an object with the property
hp: 100.Tokens → program treeWaiting for tokens from the scanner.
AST → bytecode generator- Function
spawnEnemy- Function body
- Return
return- Object
- Property
hp- Number
100
- Number
- Property
- Object
- Return
- Function body
- Function
-
The bytecode generator creates instructions
Walks the AST and writes operations for the interpreter. In this example, their meaning is: create an object, then return it.
AST → bytecodeWaiting for an AST from the parser.
Bytecode → IgnitionCREATE_OBJECT { hp: 100 }Create an objectRETURNReturn itTeaching pseudobytecode: the instruction names are illustrative. The object will be created when the function is called.
-
Ignition executes the bytecode
Reads the instructions and performs the corresponding operations. The CPU executes the machine code of the interpreter itself.
Bytecode → operationsWaiting for bytecode from the generator.
Result of spawnEnemy(){ hp: 100 }Ignition executed the instructions: the object was created and returned from the function.
V8 can also use a JIT compiler to generate machine code for the function. The CPU then executes that version directly. Both execution paths must produce the same program result.
What happens to the call and the object
When the program executes const enemy = spawnEnemy(), the following happens:
- The call begins. The engine saves the call’s data on the stack: which function is running and where to return afterwards.
- The object is created. V8 allocates heap memory for it and stores
hp: 100. - The function returns its result. The call finishes, and the variable
enemyreceives a reference to the new object.
The program continues after the call.
enemy → { hp: 100 }The object is accessible through the variable's reference.
If the object is also stored in an enemies array, it remains accessible through that array. Once no path from the roots leads to it, the garbage collector can release its memory.