Ignition: Jump-starting an Interpreter for V8
Ross McIlroy
Google London
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Agenda
Why we all love JavaScript...
JavaScript
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
JavaScript
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
JavaScript
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
JavaScript
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
JavaScript
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
JavaScript
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Something Simple
function add(a, b) {
return a + b;
}
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Something Simple
Integer addition
function add(a, b) {
return a + b;
}
add(1, 2); // 3
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Something Simple
Integer addition
Floating point addition
function add(a, b) {
return a + b;
}
add(1, 2); // 3
add(1.2, 3.14); // 4.34
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Something Simple
Integer addition
Floating point addition
String addition
function add(a, b) {
return a + b;
}
add(1, 2); // 3
add(1.2, 3.14); // 4.34
add(“hello”, “world”); // “helloworld”
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Something Simple
Integer addition
Floating point addition
String addition
Type coercion
function add(a, b) {
return a + b;
}
add(1, 2); // 3
add(1.2, 3.14); // 4.34
add(“hello”, “world”); // “helloworld”
add(1, true); // 2
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Something Simple
Integer addition
Floating point addition
String addition
Type coercion
function add(a, b) {
return a + b;
}
add(1, 2); // 3
add(1.2, 3.14); // 4.34
add(“hello”, “world”); // “helloworld”
add(1, true); // 2
add(“foo”, true); // “footrue”
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Something Simple
function add(a, b) {
return a + b;
}
add(1, 2); // 3
add(1.2, 3.14); // 4.34
add(“hello”, “world”); // “helloworld”
add(1, true); // 2
add(“foo”, true); // “footrue”
var bar = {toString:() => “bar”};�add(“foo”, bar); // “foobar”
Integer addition
Floating point addition
String addition
Type coercion
toString() / valueOf()
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
A Glance at Semantics
operator +
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
A Glance at Semantics
operator +
ToPrimitive
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
A Glance at Semantics
operator +
ToString
ToPrimitive
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
A Glance at Semantics
ToPrimitive
ToString
ToNumber
operator +
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
A Glance at Semantics
operator +
ToNumber
ToString
ToPrimitive
GetMethod
GetV
ToObject
Call
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
A Glance at Semantics
operator +
ToNumber
ToString
ToPrimitive
GetMethod
GetV
ToObject
Call
Arbitrary Javascript
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
A Glance at Semantics
operator +
ToNumber
ToString
ToPrimitive
GetMethod
GetV
ToObject
Call
Arbitrary Javascript
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Everything’s a Function
function Person(name) {
this.name = name;
}
An object’s constructor is just a function
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Everything’s a Function
function Person(name) {
this.name = name;
}
Person.prototype.toString = function() { return this.name; }
Method’s are installed on the prototype of an object
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Everything’s a Function
function Person(name) {
this.name = name;
}
Person.prototype.toString = function() { return this.name; }
var jill = new Person(“Jill”);
print(jill); // “Jill”
Objects are instantiated
by “new <Function>(...)”
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Everything’s a Function
function Person(name) {
this.name = name;
}
Person.prototype.toString = function() { return this.name; }
function Student(name, grade) {
Person.call(this, name);
this.grade = grade;
}
Student.prototype.__proto__ = Person.prototype;
�var tom = new Student(“Tom”, 72);
print(tom); // “Tom”
Inheritance emulated by prototype chaining
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Everything’s a Function
function Person(name) {
this.name = name;
}
Person.prototype.toString = function() { return this.name; }
function Student(name, grade) {
Person.call(this, name);
this.grade = grade;
}
Student.prototype.__proto__ = Person.prototype;
�var tom = new Student(“Tom”, 72);
tom.__proto__ = Object.prototype;
print(tom); // “[object Object]”
Which is completely dynamic....
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Except when it’s a Closure
function Counter(start) {
var count = 0;
return {
next: function() { return start + count++; }
}
}
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Except when it’s a Closure
function Counter(start) {
var count = 0;
return {
next: function() { return start + count++; }
}
}
var counter = Counter(5);
print(counter.next() + “ -> ” + counter.next()); // 5 -> 6
Closures over parameters, and mutable local variables
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Fun with eval()
function func(a, b) {
return eval(a) + (b == 0 ? 0 : func(a, --b));
}
func(“1”, 3); // 4
Executes string within the context of the calling function
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Fun with eval()
function func(a, b) {
return eval(a) + (b == 0 ? 0 : func(a, --b));
}
func(“1”, 3); // 4
func(“b = 0”, 200); // 0
Executes string within the context of the calling function
Can modify locals or introduce new ones
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Fun with eval()
function func(a, b) {
return eval(a) + (b == 0 ? 0 : func(a, --b));
}
func(“1”, 3); // 4
func(“b = 0”, 200); // 0
func("func = function() {
return 'bar'
}; 'foo'", 50); // “foobar”
Executes string within the context of the calling function
Can modify locals or introduce new ones
Or do crazy things...
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
The V8 Approach
V8 History
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Compiler Pipeline (2008)
Source
Parser
Full- codegen
Unoptimized Code
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Full-Codegen in a nutshell
function Sum(point) = {
return point.x + point.y;
};
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Full-Codegen in a nutshell
function Sum(point) = {
return point.x + point.y;
};
return
+
Load�Property
Load�Property
“x”
point
Parser
“y”
point
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Full-Codegen in a nutshell
return
+
Load�Property
Load�Property
“x”
point
“y”
point
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Full-Codegen in a nutshell
... ; prologue
mov eax, [ebp + 0x10] ; point
return
+
Load�Property
Load�Property
“x”
point
“y”
point
Full-Codegen
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Full-Codegen in a nutshell
... ; prologue
mov eax, [ebp + 0x10] ; point
mov ecx, 0x56a79431 ; “x”
return
+
Load�Property
Load�Property
“x”
point
“y”
point
Full-Codegen
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Full-Codegen in a nutshell
... ; prologue
mov eax, [ebp + 0x10] ; point
mov ecx, 0x56a79431 ; “x”
call $LoadNamedProperty
push eax
return
+
Load�Property
Load�Property
“x”
point
“y”
point
Full-Codegen
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Full-Codegen in a nutshell
... ; prologue
mov eax, [ebp + 0x10] ; point
mov ecx, 0x56a79431 ; “x”
call $LoadNamedProperty
push eax
mov eax, [ebp + 0x10] ; point
mov ecx, 0x56a71251 ; “y”
call $LoadNamedProperty
return
+
Load�Property
Load�Property
“x”
point
“y”
point
Full-Codegen
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Full-Codegen in a nutshell
... ; prologue
mov eax, [ebp + 0x10] ; point
mov ecx, 0x56a79431 ; “x”
call $LoadNamedProperty
push eax
mov eax, [ebp + 0x10] ; point
mov ecx, 0x56a71251 ; “y”
call $LoadNamedProperty
pop edx
call $BinaryOpAdd
...
return
+
Load�Property
Load�Property
“x”
point
“y”
point
Full-Codegen
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Full-Codegen in a nutshell
... ; prologue
mov eax, [ebp + 0x10] ; point
mov ecx, 0x56a79431 ; “x”
call $LoadNamedProperty
push eax
mov eax, [ebp + 0x10] ; point
mov ecx, 0x56a71251 ; “y”
call $LoadNamedProperty
pop edx
call $BinaryOpAdd
...
UNINITIALIZED_LOAD_IC
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Hidden Classes
function Point(x, y) = {
this.x = x;
this.y = y;
};
Hidden classes was a technique from Self VM
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Hidden Classes
function Point(x, y) {
this.x = x;
this.y = y;
};
var point = new Point(3, 5);
map[Point]
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Hidden Classes
function Point(x, y) {
this.x = x;
this.y = y;
};
var point = new Point(3, 5);
3
map[Point]
map[Point1]
0x4: “x”
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Hidden Classes
function Point(x, y) {
this.x = x;
this.y = y;
};
var point = new Point(3, 5);
3
map[Point]
map[Point1]
0x4: “x”
“x”
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Hidden Classes
function Point(x, y) {
this.x = x;
this.y = y;
};
var point = new Point(3, 5);
3
5
map[Point]
map[Point1]
0x4: “x”
map[Point2]
0x4: “x”
0x8: “y”
“x”
“y”
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Inline Caches (ICs)
... ; prologue
mov eax, [ebp + 0x10] ; point
mov ecx, 0x56a79431 ; “x”
call $LoadNamedProperty
push eax
mov eax, [ebp + 0x10] ; point
mov ecx, 0x56a71251 ; “y”
call $LoadNamedProperty
pop edx
call $BinaryOpAdd
...
UNINITIALIZED_LOAD_IC
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Inline Caches (ICs)
... ; prologue
mov eax, [ebp + 0x10] ; point
mov ecx, 0x56a79431 ; “x”
call $LoadNamedProperty
push eax
mov eax, [ebp + 0x10] ; point
mov ecx, 0x56a71251 ; “y”
call $LoadNamedProperty
pop edx
call $BinaryOpAdd
...
UNINITIALIZED_LOAD_IC
… ; Check object’s map is
… ; Point type, or bailout
mov eax, [eax + 0x4]
ret
MONOMORPHIC_LOAD_IC_X
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Inline Caches (ICs)
... ; prologue
mov eax, [ebp + 0x10] ; point
mov ecx, 0x56a79431 ; “x”
call $LoadNamedProperty
push eax
mov eax, [ebp + 0x10] ; point
mov ecx, 0x56a71251 ; “y”
call $LoadNamedProperty
pop edx
call $BinaryOpAdd
...
… ; Check object’s map is
… ; Point type, or bailout
mov eax, [eax + 0x4]
ret
MONOMORPHIC_LOAD_IC_X
… ; Check object’s map is
… ; Point type, or bailout
mov eax, [eax + 0x8]
ret
MONOMORPHIC_LOAD_IC_Y
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Inline Caches (ICs)
... ; prologue
mov eax, [ebp + 0x10] ; point
mov ecx, 0x56a79431 ; “x”
call $LoadNamedProperty
push eax
mov eax, [ebp + 0x10] ; point
mov ecx, 0x56a71251 ; “y”
call $LoadNamedProperty
pop edx
call $BinaryOpAdd
...
…
… ; Check object’s map is
… ; Point type, or bailout
mov eax, [eax + 0x4]
ret
MONOMORPHIC_LOAD_IC_X
… ; Check object’s map is
… ; Point type, or bailout
mov eax, [eax + 0x8]
ret
MONOMORPHIC_LOAD_IC_Y
BINARY_OP_ADD_IC
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Compiler Pipeline (2010)
Source
Parser
Full- codegen
Crankshaft
Optimized Code
Unoptimized Code
Parser
Baseline
Optimized
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
A Little on Crankshaft
function Sum(point) {
return point.x + point.y;
};
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
A Little on Crankshaft
function Sum(point) {
return point.x + point.y;
};
Sum(new Point(1, 2));
Sum(new Point(100, 6));
Sum(new Point(0.5, 30));
Sum(new Point(0.5, 30));
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
A Little on Crankshaft
function Sum(point) {
return point.x + point.y;
};
Sum(new Point(1, 2));
Sum(new Point(100, 6));
Sum(new Point(0.5, 30));
Sum(new Point(0.5, 30));
Always a number
Always Point
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
A Little on Crankshaft
function Sum(point) {
return point.x + point.y;
};
Sum(new Point(1, 2));
Sum(new Point(100, 6));
Sum(new Point(0.5, 30));
Sum(new Point(0.5, 30));
Always a number
Always Point
Inline FP addition
Inline property load
Elide map checks
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
A Little on Crankshaft
function Sum(point) {
return point.x + point.y;
};
Sum(new Point(1, 2));
Sum(new Point(100, 6));
Sum(new Point(0.5, 30));
Sum(new Point(0.5, 30));
Always a number
Always Point
Inline FP addition
Inline property load
Elide map checks
GVN
Inlining
Escape analysis
Type analysis
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
A Little on Crankshaft
function Sum(point) {
return point.x + point.y;
};
Sum(new Point(1, 2));
Sum(new Point(100, 6));
Sum(new Point(0.5, 30));
Sum(new Point(0.5, 30));
Sum(new StringPair(“foo”, “bar”);
Always a number
Always Point
Inline FP addition
Inline property load
Elide map checks
GVN
Inlining
Escape analysis
Type analysis
❌
❌
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Deoptimization - Always Have a Backup Plan
Optimized Code
Baseline Code
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Compiler Pipeline (2015)
Source
Parser
Full- codegen
Crankshaft
Optimized Code
Unoptimized Code
Parser
TurboFan
Baseline
Optimized
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Another Optimizing Compiler?
Crankshaft served us well, but has various shortcomings:
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Another Optimizing Compiler?
Crankshaft served us well, but has various shortcomings:
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Another Optimizing Compiler?
Crankshaft served us well, but has various shortcomings:
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Another Optimizing Compiler?
Crankshaft served us well, but has various shortcomings:
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Another Optimizing Compiler?
Crankshaft served us well, but has various shortcomings:
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
TurboFan
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
TurboFan
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
TurboFan
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Sea of Nodes
Start
End
Branch
IfTrue
IfFalse
Merge
phi
2
1
x
Control edge
Value edge
Effect edge
function (x) {
return x ? 1 : 2;
}
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Retrofitting an Interpreter into
a Moving Engine
Why Interpret?
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Why Interpret?
�
33% of time spent parsing + compiling
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Why Interpret?
�
�
Full- codegen
Crankshaft
TurboFan
Unoptimized Code
Optimized Code
Optimized Code
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition - Goals
�
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition - Goals
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition - Goals
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition - Challenges
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition - Challenges
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition - Challenges
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition - Challenges
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition - Challenges
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Compiler Pipeline (2015)
Crankshaft
Optimized Code
TurboFan
Optimized
Full- codegen
Unoptimized Code
Baseline
Optimize
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Compiler Pipeline (2015)
Crankshaft
Optimized Code
TurboFan
Optimized
Full- codegen
Unoptimized Code
Baseline
Optimize
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Compiler Pipeline (2016)
Crankshaft
Optimized Code
TurboFan
Optimized
Full- codegen
Unoptimized Code
Baseline
Optimize
Ignition
Bytecode
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Compiler Pipeline (2016)
Crankshaft
Optimized Code
TurboFan
Optimized
Full- codegen
Unoptimized Code
Baseline
Optimize
Ignition
Bytecode
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Compiler Pipeline (early 2017 ?)
Crankshaft
Optimized Code
TurboFan
Optimized
Full- codegen
Unoptimized Code
Baseline
Optimize
Ignition
Bytecode
Interpreted
Optimize
Baseline
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Compiler Pipeline (early 2017 ?)
Crankshaft
Optimized Code
TurboFan
Optimized
Full- codegen
Unoptimized Code
Baseline
Optimize
Ignition
Bytecode
Interpreted
Optimize
Baseline
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Compiler Pipeline (2017 ?)
Optimized Code
TurboFan
Optimized
Ignition
Bytecode
Interpreted
Optimize
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition Design Decisions
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition Design Decisions
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition Design Decisions
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition Bytecode
function f(a, b, c) {
var local = c - 100;
return a + local * b;
}
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition Bytecode
LdaSmi #100
Sub a2
Star r0
Ldar a1
Mul r0
Add a0
Return
function f(a, b, c) {
var local = c - 100;
return a + local * b;
}
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition Bytecode
r0 [local] | undefined |
function f(a, b, c) {
var local = c - 100;
return a + local * b;
}
LdaSmi #100
Sub a2
Star r0
Ldar a1
Mul r0
Add a0
Return
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition Bytecode
a0 [a] | 5 |
a1 [b] | 2 |
a2 [c] | 150 |
r0 [local] | undefined |
LdaSmi #100
Sub a2
Star r0
Ldar a1
Mul r0
Add a0
Return
function f(a, b, c) {
var local = c - 100;
return a + local * b;
}
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition Bytecode
a0 [a] | 5 |
a1 [b] | 2 |
a2 [c] | 150 |
r0 [local] | undefined |
accumulator | undefined |
LdaSmi #100
Sub a2
Star r0
Ldar a1
Mul r0
Add a0
Return
function f(a, b, c) {
var local = c - 100;
return a + local * b;
}
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition Bytecode
function f(a, b, c) {
var local = c - 100;
return a + local * b;
}
a0 [a] | 5 |
a1 [b] | 2 |
a2 [c] | 150 |
r0 [local] | undefined |
accumulator | 100 |
LdaSmi #100
Sub a2
Star r0
Ldar a1
Mul r0
Add a0
Return
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition Bytecode
function f(a, b, c) {
var local = c - 100;
return a + local * b;
}
a0 [a] | 5 |
a1 [b] | 2 |
a2 [c] | 150 |
r0 [local] | undefined |
accumulator | 50 |
LdaSmi #100
Sub a2
Star r0
Ldar a1
Mul r0
Add a0
Return
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition Bytecode
function f(a, b, c) {
var local = c - 100;
return a + local * b;
}
a0 [a] | 5 |
a1 [b] | 2 |
a2 [c] | 150 |
r0 [local] | 50 |
accumulator | 50 |
LdaSmi #100
Sub a2
Star r0
Ldar a1
Mul r0
Add a0
Return
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition Bytecode
function f(a, b, c) {
var local = c - 100;
return a + local * b;
}
a0 [a] | 5 |
a1 [b] | 2 |
a2 [c] | 150 |
r0 [local] | 50 |
accumulator | 2 |
LdaSmi #100
Sub a2
Star r0
Ldar a1
Mul r0
Add a0
Return
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition Bytecode
function f(a, b, c) {
var local = c - 100;
return a + local * b;
}
a0 [a] | 5 |
a1 [b] | 2 |
a2 [c] | 150 |
r0 [local] | 50 |
accumulator | 100 |
LdaSmi #100
Sub a2
Star r0
Ldar a1
Mul r0
Add a0
Return
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition Bytecode
a0 [a] | 5 |
a1 [b] | 2 |
a2 [c] | 150 |
r0 [local] | 50 |
accumulator | 105 |
LdaSmi #100
Sub a2
Star r0
Ldar a1
Mul r0
Add a0
Return
function f(a, b, c) {
var local = c - 100;
return a + local * b;
}
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition Bytecode
a0 [a] | 5 |
a1 [b] | 2 |
a2 [c] | 150 |
r0 [local] | 50 |
accumulator | 105 |
LdaSmi #100
Sub a2
Star r0
Ldar a1
Mul r0
Add a0
Return
function f(a, b, c) {
var local = c - 100;
return a + local * b;
}
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition Bytecode Pipeline
Parser
Bytecode Generator
Abstract Syntax Tree
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition Bytecode Pipeline
Parser
Bytecode Generator
Abstract Syntax Tree
void BytecodeGenerator::VisitAddExpression(
BinaryOperation* expr) {
Register lhs =
VisitForRegisterValue(expr->left());
VisitForAccumulatorValue(expr->right());
builder()->AddOperation(lhs);
}
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition Bytecode Pipeline
Parser
Bytecode Generator
Abstract Syntax Tree
void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
// Copy the literal boilerplate.
int fast_clone_properties_count = 0;
if (FastCloneShallowObjectStub::IsSupported(expr)) {
STATIC_ASSERT(
FastCloneShallowObjectStub::kMaximumClonedProperties <=
1 << CreateObjectLiteralFlags::FastClonePropertiesCountBits::kShift);
fast_clone_properties_count =
FastCloneShallowObjectStub::PropertiesCount(expr->properties_count());
}
uint8_t flags =
CreateObjectLiteralFlags::FlagsBits::encode(expr->ComputeFlags()) |
CreateObjectLiteralFlags::FastClonePropertiesCountBits::encode(
fast_clone_properties_count);
builder()->CreateObjectLiteral(expr->constant_properties(),
expr->literal_index(), flags);
// Allocate in the outer scope since this register is used to return the
// expression's results to the caller.
Register literal = register_allocator()->outer()->NewRegister();
builder()->StoreAccumulatorInRegister(literal);
// Store computed values into the literal.
int property_index = 0;
AccessorTable accessor_table(zone());
for (; property_index < expr->properties()->length(); property_index++) {
ObjectLiteral::Property* property = expr->properties()->at(property_index);
if (property->is_computed_name()) break;
if (property->IsCompileTimeValue()) continue;
RegisterAllocationScope inner_register_scope(this);
Literal* literal_key = property->key()->AsLiteral();
switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT:
UNREACHABLE();
case ObjectLiteral::Property::MATERIALIZED_LITERAL:
DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value()));
// Fall through.
case ObjectLiteral::Property::COMPUTED: {
// It is safe to use [[Put]] here because the boilerplate already
// contains computed properties with an uninitialized value.
if (literal_key->value()->IsInternalizedString()) {
if (property->emit_store()) {
VisitForAccumulatorValue(property->value());
if (FunctionLiteral::NeedsHomeObject(property->value())) {
RegisterAllocationScope register_scope(this);
Register value = register_allocator()->NewRegister();
builder()->StoreAccumulatorInRegister(value);
builder()->StoreNamedProperty(
literal, literal_key->AsPropertyName(),
feedback_index(property->GetSlot(0)), language_mode());
VisitSetHomeObject(value, literal, property, 1);
} else {
builder()->StoreNamedProperty(
literal, literal_key->AsPropertyName(),
feedback_index(property->GetSlot(0)), language_mode());
}
} else {
VisitForEffect(property->value());
}
register_allocator()->PrepareForConsecutiveAllocations(4);
Register literal_argument =
register_allocator()->NextConsecutiveRegister();
Register key = register_allocator()->NextConsecutiveRegister();
Register value = register_allocator()->NextConsecutiveRegister();
Register language = register_allocator()->NextConsecutiveRegister();
builder()->MoveRegister(literal, literal_argument);
VisitForAccumulatorValue(property->key());
builder()->StoreAccumulatorInRegister(key);
VisitForAccumulatorValue(property->value());
builder()->StoreAccumulatorInRegister(value);
if (property->emit_store()) {
builder()
->LoadLiteral(Smi::FromInt(SLOPPY))
.StoreAccumulatorInRegister(language)
.CallRuntime(Runtime::kSetProperty, literal_argument, 4);
VisitSetHomeObject(value, literal, property);
}
}
break;
}
case ObjectLiteral::Property::PROTOTYPE: {
DCHECK(property->emit_store());
register_allocator()->PrepareForConsecutiveAllocations(2);
Register literal_argument =
register_allocator()->NextConsecutiveRegister();
Register value = register_allocator()->NextConsecutiveRegister();
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition Bytecode Pipeline
Parser
Bytecode Generator
Abstract Syntax Tree
builder()->MoveRegister(literal, literal_argument);
VisitForAccumulatorValue(property->value());
builder()->StoreAccumulatorInRegister(value).CallRuntime(
Runtime::kInternalSetPrototype, literal_argument, 2);
break;
}
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
accessor_table.lookup(literal_key)->second->getter = property;
}
break;
case ObjectLiteral::Property::SETTER:
if (property->emit_store()) {
accessor_table.lookup(literal_key)->second->setter = property;
}
break;
}
}
// Define accessors, using only a single call to the runtime for each pair of
// corresponding getters and setters.
for (AccessorTable::Iterator it = accessor_table.begin();
it != accessor_table.end(); ++it) {
RegisterAllocationScope inner_register_scope(this);
register_allocator()->PrepareForConsecutiveAllocations(5);
Register literal_argument = register_allocator()->NextConsecutiveRegister();
Register name = register_allocator()->NextConsecutiveRegister();
Register getter = register_allocator()->NextConsecutiveRegister();
Register setter = register_allocator()->NextConsecutiveRegister();
Register attr = register_allocator()->NextConsecutiveRegister();
builder()->MoveRegister(literal, literal_argument);
VisitForAccumulatorValue(it->first);
builder()->StoreAccumulatorInRegister(name);
VisitObjectLiteralAccessor(literal, it->second->getter, getter);
VisitObjectLiteralAccessor(literal, it->second->setter, setter);
builder()
->LoadLiteral(Smi::FromInt(NONE))
.StoreAccumulatorInRegister(attr)
.CallRuntime(Runtime::kDefineAccessorPropertyUnchecked,
literal_argument, 5);
}
for (; property_index < expr->properties()->length(); property_index++) {
ObjectLiteral::Property* property = expr->properties()->at(property_index);
RegisterAllocationScope inner_register_scope(this);
if (property->kind() == ObjectLiteral::Property::PROTOTYPE) {
DCHECK(property->emit_store());
register_allocator()->PrepareForConsecutiveAllocations(2);
Register literal_argument =
register_allocator()->NextConsecutiveRegister();
Register value = register_allocator()->NextConsecutiveRegister();
builder()->MoveRegister(literal, literal_argument);
VisitForAccumulatorValue(property->value());
builder()->StoreAccumulatorInRegister(value).CallRuntime(
Runtime::kInternalSetPrototype, literal_argument, 2);
continue;
}
register_allocator()->PrepareForConsecutiveAllocations(5);
Register literal_argument = register_allocator()->NextConsecutiveRegister();
Register key = register_allocator()->NextConsecutiveRegister();
Register value = register_allocator()->NextConsecutiveRegister();
Register attr = register_allocator()->NextConsecutiveRegister();
DCHECK(Register::AreContiguous(literal_argument, key, value, attr));
Register set_function_name =
register_allocator()->NextConsecutiveRegister();
builder()->MoveRegister(literal, literal_argument);
VisitForAccumulatorValue(property->key());
builder()->CastAccumulatorToName().StoreAccumulatorInRegister(key);
VisitForAccumulatorValue(property->value());
builder()->StoreAccumulatorInRegister(value);
VisitSetHomeObject(value, literal, property);
builder()->LoadLiteral(Smi::FromInt(NONE)).StoreAccumulatorInRegister(attr);
switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT:
case ObjectLiteral::Property::COMPUTED:
case ObjectLiteral::Property::MATERIALIZED_LITERAL:
builder()
->LoadLiteral(Smi::FromInt(property->NeedsSetFunctionName()))
.StoreAccumulatorInRegister(set_function_name);
builder()->CallRuntime(Runtime::kDefineDataPropertyInLiteral,
literal_argument, 5);
break;
case ObjectLiteral::Property::PROTOTYPE:
UNREACHABLE(); // Handled specially above.
break;
case ObjectLiteral::Property::GETTER:
builder()->CallRuntime(Runtime::kDefineGetterPropertyUnchecked,
literal_argument, 4);
break;
case ObjectLiteral::Property::SETTER:
builder()->CallRuntime(Runtime::kDefineSetterPropertyUnchecked,
literal_argument, 4);
break;
}
}
execution_result()->SetResultInRegister(literal);
}
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition Bytecode Pipeline
Parser
Bytecode Generator
Abstract Syntax Tree
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition Bytecode Pipeline
Parser
Bytecode Generator
Abstract Syntax Tree
Register Optimizer
Peephole Optimizer
Dead-code Elimination
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition Bytecode Pipeline
Parser
Bytecode Generator
Abstract Syntax Tree
Register Optimizer
Peephole Optimizer
Dead-code Elimination
Bytecode Array Writer
Bytecode
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition Bytecode Pipeline
Parser
Bytecode Generator
Abstract Syntax Tree
Register Optimizer
Peephole Optimizer
Dead-code Elimination
Bytecode Array Writer
Bytecode
Interpreter
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Building the Ignition Interpreter
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Building the Ignition Interpreter
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Building the Ignition Interpreter
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Building the Ignition Interpreter
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Building the Ignition Interpreter
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Building the Ignition Interpreter
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
TurboFan Pipeline
JavaScript
Simple
Machine
Scheduler
CodeGen
JavaScript Source
Machine Code
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
TurboFan Pipeline
JavaScript
Simple
Machine
Scheduler
CodeGen
Machine Code
Interpreter Assembler
JavaScript Source
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
TurboFan Pipeline
JavaScript
Simple
Machine
Scheduler
CodeGen
JavaScript Source
Machine Code
WebAssembly
Interpreter Assembler
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Building an Interpreter using TurboFan
void Interpreter::DoAdd(InterpreterAssembler* assembler) {
Node* reg_index = assembler->BytecodeOperandReg(0);
Node* lhs = assembler->LoadRegister(reg_index);
Node* rhs = assembler->GetAccumulator();
Node* result = AddStub::Generate(assembler, lhs, rhs);
assembler->SetAccumulator(result);
assembler->Dispatch();
}
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Building an Interpreter using TurboFan
void Interpreter::DoAdd(InterpreterAssembler* assembler) {
Node* reg_index = assembler->BytecodeOperandReg(0);
Node* lhs = assembler->LoadRegister(reg_index);
Node* rhs = assembler->GetAccumulator();
Node* result = AddStub::Generate(assembler, lhs, rhs);
assembler->SetAccumulator(result);
assembler->Dispatch();
}
~375 LOC for number addition
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Building an Interpreter using TurboFan
void Interpreter::DoAdd(InterpreterAssembler* assembler) {
Node* reg_index = assembler->BytecodeOperandReg(0);
Node* lhs = assembler->LoadRegister(reg_index);
Node* rhs = assembler->GetAccumulator();
Node* result = AddStub::Generate(assembler, lhs, rhs);
assembler->SetAccumulator(result);
assembler->Dispatch();
}
~375 LOC for number addition
~250 LOC for string addition
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Building an Interpreter using TurboFan
void Interpreter::DoAdd(InterpreterAssembler* assembler) {
Node* reg_index = assembler->BytecodeOperandReg(0);
Node* lhs = assembler->LoadRegister(reg_index);
Node* rhs = assembler->GetAccumulator();
Node* result = AddStub::Generate(assembler, lhs, rhs);
assembler->SetAccumulator(result);
assembler->Dispatch();
}
~375 LOC for number addition
~250 LOC for string addition
… for type conversions
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Indirect Threaded Bytecode Dispatch
...
Ldar:
Star:
Add:
Sub:
0x32e3e920
0x32e3e9a0
0x32e400e0
0x32e401e0
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Indirect Threaded Bytecode Dispatch
...
Ldar:
Star:
Add:
Sub:
movsxbq rax,[r14+r12*1+0x1]
movq rax,[rbp+rax*8]
leaq r12,[r12+0x2]
movzxbl rbx,[r12+r14*1]
movq rbx,[r15+rbx*8]
jmp rbx
0x32e3e920
0x32e3e9a0
0x32e400e0
0x32e401e0
Ldar
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Indirect Threaded Bytecode Dispatch
...
Ldar:
Star:
Add:
Sub:
movsxbq rax,[r14+r12*1+0x1]
movq rax,[rbp+rax*8]
leaq r12,[r12+0x2]
movzxbl rbx,[r12+r14*1]
movq rbx,[r15+rbx*8]
jmp rbx
0x32e3e920
0x32e3e9a0
0x32e400e0
0x32e401e0
Load operand #0
Ldar
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Indirect Threaded Bytecode Dispatch
...
Ldar:
Star:
Add:
Sub:
movsxbq rax,[r14+r12*1+0x1]
movq rax,[rbp+rax*8]
leaq r12,[r12+0x2]
movzxbl rbx,[r12+r14*1]
movq rbx,[r15+rbx*8]
jmp rbx
0x32e3e920
0x32e3e9a0
0x32e400e0
0x32e401e0
Load operand #0
Ldar
Load register to accumulator
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Indirect Threaded Bytecode Dispatch
...
Ldar:
Star:
Add:
Sub:
movsxbq rax,[r14+r12*1+0x1]
movq rax,[rbp+rax*8]
leaq r12,[r12+0x2]
movzxbl rbx,[r12+r14*1]
movq rbx,[r15+rbx*8]
jmp rbx
0x32e3e920
0x32e3e9a0
0x32e400e0
0x32e401e0
Load operand #0
Ldar
Load register to accumulator
Advance to next bytecode
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Indirect Threaded Bytecode Dispatch
...
Ldar:
Star:
Add:
Sub:
movsxbq rax,[r14+r12*1+0x1]
movq rax,[rbp+rax*8]
leaq r12,[r12+0x2]
movzxbl rbx,[r12+r14*1]
movq rbx,[r15+rbx*8]
jmp rbx
0x32e3e920
0x32e3e9a0
0x32e400e0
0x32e401e0
Load operand #0
Ldar
Load register to accumulator
Advance to next bytecode
Load next bytecode
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Indirect Threaded Bytecode Dispatch
...
Ldar:
Star:
Add:
Sub:
movsxbq rax,[r14+r12*1+0x1]
movq rax,[rbp+rax*8]
leaq r12,[r12+0x2]
movzxbl rbx,[r12+r14*1]
movq rbx,[r15+rbx*8]
jmp rbx
0x32e3e920
0x32e3e9a0
0x32e400e0
0x32e401e0
Load operand #0
Ldar
Load register to accumulator
Advance to next bytecode
Load next bytecode
Dispatch
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Inline Caches with Code Patching
Machine Code
IC Stubs
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Inline Caches with Code Patching
Machine Code
IC Stubs
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Inline Caches with Type Feedback Vector
Machine Code
IC Stubs
Feedback Vector
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Inline Caches with Type Feedback Vector
Bytecode
IC Stubs
Feedback Vector
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Inline Caches with Type Feedback Vector
Bytecode
IC Stubs
Feedback Vector
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition vs Full-Codegen
Octane (Nexus 5)�Crankshaft and TurboFan disabled
Score
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition vs Full-Codegen
Octane (Nexus 5)�Crankshaft and TurboFan disabled
Score
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition vs Default
Octane Score (x64)
Score
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition vs Default
Octane Score (x64)
40% slower
5% slower
Score
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition vs Default
Octane Score (x64)
40% slower
5% slower
Tune Tiering up
Score
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition vs Default
Octane Score (x64)
40% slower
5% slower
Tune Tiering up
OSR
Score
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition vs Default
Octane Score (x64)
40% slower
5% slower
Tune Tiering up
OSR
BinaryOp Feedback
Score
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition vs Default
Octane Score (x64)
40% slower
5% slower
Tune Tiering up
OSR
BinaryOp Feedback
CS / TF adaption
Score
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Real Websites
Google Maps
Default
Default
Default
Ignition
Ignition
Ignition
Page Load (ms)
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Real Websites
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Real Websites
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Summary
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Summary
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Summary
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Summary
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Summary
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Ignition Bytecodes
Loading the accumulator LdaZero LdaSmi8 LdaUndefined LdrUndefined LdaNull LdaTheHole LdaTrue LdaFalse LdaConstant Binary Operators Add Sub Mul Div Mod BitwiseOr BitwiseXor BitwiseAnd ShiftLeft ShiftRight ShiftRightLogical Closure Allocation CreateClosure | Globals LdaGlobal LdrGlobal LdaGlobalInsideTypeof StaGlobalSloppy StaGlobalStrict Unary Operators Inc Dec LogicalNot TypeOf DeletePropertyStrict DeletePropertySloppy Call Operations Call TailCall CallRuntime CallRuntimeForPair CallJsRuntime InvokeIntrinsic New Operator New | Test Operators TestEqual TestNotEqual TestEqualStrict TestLessThan TestGreaterThan TestLessThanOrEqual TestGreaterThanOrEqual TestInstanceOf TestIn Context Operations PushContext PopContext LdaContextSlot LdrContextSlot StaContextSlot Cast Operators ToName ToNumber ToObject Arguments Allocation CreateMappedArguments CreateUnmappedArguments CreateRestParameter | Register Transfers Ldar Star Mov Control Flow Jump JumpConstant JumpIfTrue JumpIfTrueConstant JumpIfFalse JumpIfFalseConstant JumpIfToBooleanTrue JumpIfToBooleanTrueConstant JumpIfToBooleanFalse JumpIfToBooleanFalseConstant JumpIfNull JumpIfNullConstant JumpIfUndefined JumpIfUndefinedConstant JumpIfNotHole JumpIfNotHoleConstant Non-Local Flow Control Throw ReThrow Return | Literals CreateRegExpLiteral CreateArrayLiteral CreateObjectLiteral Load Property Operations LdaNamedProperty LdaKeyedProperty KeyedLoadICStrict Store Property Operations StoreICSloppy StoreICStrict KeyedStoreICSloppy KeyedStoreICStrict Complex Flow Control ForInPrepare ForInNext ForInDone ForInStep Generators SuspendGenerator ResumeGenerator |
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem