TurboFan JIT Design
Ben L. Titzer
Google Munich
Google Proprietary
V8 Background
Google Proprietary
TurboFan Design Goals
Google Proprietary
TurboFan Program Representation (IR)
Google Proprietary
Do not get seasick!
3
x
+
All computations are expressed as nodes in the sea of nodes
Edges represent dependencies between computations
+
3
x
constant
parameter
addition operator
data flow edge
Google Proprietary
Dependencies constrain Ordering
+
3
x
+
3
x
+
3
x
legal
legal
illegal
Google Proprietary
Lack of Ordering means Compiler Freedom!
7
*
5
+
x
x
5
7
x
7
x
5
x
+
7
+
*
7
*
x
+
*
5
5
5
7
x
+
+
*
*
x
x
5
5
x
7
x
+
*
5
+
7
+
*
7
*
+
*
7
+
*
5
5
7
Google Proprietary
Larger class of equivalences
7
*
5
+
x
x
5
7
x
7
x
5
x
+
7
+
*
7
*
x
+
*
5
5
5
7
x
+
+
*
*
x
x
5
5
x
7
x
+
*
5
+
7
+
*
7
*
+
*
7
+
*
5
5
7
graph creation
Google Proprietary
The Sea is SSA
3
[x]
+
No such thing as local variables!
Graph building from source renames locals
3
+
x = 3 * 8
x + 3
*
8
SSA
renaming
Multiple incoming edges possible
Google Proprietary
Effect Edges
LoadField[f]
obj
effect
Read of mutable state obj.f
Read
potential write X
+
3
RAW: prevents X
moving after R
potential write Y
WAR: prevents Y moving before R
StoreField[f]
WAW: prevents X
moving after Y
Google Proprietary
Expressing Control
Google Proprietary
Control nodes and Control edges
Branch
IfTrue
IfFalse
Merge
Branch
IfTrue
IfFalse
Loop
Start
End
straightline program
branch
while loop
Google Proprietary
Our first complete graph
Start
End
3
x
+
function (x) { return x + 3; }
control edge
value edge
effect edge
Google Proprietary
Branch example
Start
End
function (x) { return x ? 1 : 2; }
Branch
IfTrue
IfFalse
Merge
phi
2
1
x
control edge
value edge
effect edge
Google Proprietary
Language Levels
Google Proprietary
Language Levels
JSAdd
JSSubtract
JSMultiply
JSDivide
JSModulus
JSEqual
JSToBoolean
JSToNumber
JSCall
JSStrictEqual
JSBitwiseOr
JSDivide
JSBitwiseAnd
JSBitwiseXor
JSShiftLeft
JSShiftRight
NumberAdd
NumberSub
NumberMul
NumberDiv
NumberMod
NumberEqual
StringEqual
NumberLessThan
StringAdd
LoadField
StoreField
ChangeTaggedToInt32
Int32Add
Int32Sub
Int32Mul
Float64Add
Float64Sub
Float64Mul
Load
Store
Call
ConvertFloat64ToInt32
Google Proprietary
Type and Range Analysis
Google Proprietary
Type and Range Analysis
typing
alone
x: Int
y: Int
x: Int in [0, 9]
y: Int in [11, 15]
+
+: Num
+
typing + range analysis
+: Int in [11, 26]
typing
alone
x: Int
y: Int
x: Int in [0, 9]
y: Int in [11, 15]
phi
phi: Int
phi
typing + range analysis
phi: Int in [0, 15]
Google Proprietary
Optimization
Google Proprietary
Reduction
3
5
+
x
0
+
x
4
*
x
2
<<
8
x
x
phi
x
7
+
5
+
x
x
12
+
constant
folding
strength
reduction
strength
reduction
phi
simplification
algebraic
reassociation
Google Proprietary
Typed Lowering as Reduction
typed lowering
y: Num
x: Num
JSAdd
y: Num
x: Num
NumAdd
y: String
x: Num
StringAdd
y: String
x: Num
JSAdd
ToString
y: Int
x: Int
JSAdd
JSBitwiseOr
0
y: Int
x: Int
Int32Add
typed lowering
typed lowering
generic lowering
y: Any
x: Any
JSAdd
y: Any
x: Any
BinopIC[+]
Google Proprietary
Global Value Numbering as Reduction
x
y
+
+
x
y
+
LoadField[f]
obj
LoadField[f]
effect
x
sin
sin
x
sin
LoadField[f]
obj
effect
GVN
GVN
GVN
Google Proprietary
Control Optimization as Reduction
C
Branch
true
IfTrue
IfFalse
C
Dead
x
y
x
y
branch folding
Google Proprietary
Control Optimization as Reduction
Merge
C1
Dead
C2
x
phi
y
z
Merge
C1
C2
x
phi
z
merge
reduction
Merge
C1
x
phi
merge
reduction
C1
x
Google Proprietary
Control Optimization as Reduction
Branch
x
IfTrue
IfFalse
Dead
x
y
x
y
control reduction
Dead
Google Proprietary
Reduction as Top-down Graph Rewriting
x
Node
y
z
fully reduced inputs
reduction rules
value uses
effect uses
control uses
x
y
z
value uses
effect uses
control uses
reduced
node(s)
Google Proprietary
Iterative Reduction (recursion with explicit stack)
n1
n2
n3
n4
n5
n6
n7
n8
n9
Reduce top of stack when all its inputs are reduced.
node stack
backwards DFS
end
Pop the stack after applying reduction rules.
Applies reduction to each node once in the optimal order.
Google Proprietary
Iterative Reduction (in the presence of cycles)
n1
n2
n3
n4
n5
n6
n7
n8
n9
Reduce top of stack when all its inputs are either reduced or are themselves on the stack.
node stack
backwards DFS
end
When a node is successfully reduced, revisit any uses that were partially reduced due to cycles.
Computes a fixpoint over reduction rules.
Google Proprietary
Iterative Reduction (in the presence of cycles)
n1
n2
n3
n4
n5
Reduce top of stack when all its inputs are either reduced or are themselves on the stack.
node stack
backwards DFS
end
When a node is successfully reduced, revisit any uses that were partially reduced due to cycles.
Computes a fixpoint over reduction rules.
n6
Google Proprietary
Iterative Reduction (in the presence of cycles)
n1
n2
n3
Reduce top of stack when all its inputs are either reduced or are themselves on the stack.
node stack
backwards DFS
end
When a node is successfully reduced, revisit any uses that were partially reduced due to cycles.
Computes a fixpoint over reduction rules.
n4
n6
Google Proprietary
Iterative Reduction (in the presence of cycles)
n1
n2
Reduce top of stack when all its inputs are either reduced or are themselves on the stack.
node stack
backwards DFS
end
When a node is successfully reduced, revisit any uses that were partially reduced due to cycles.
Computes a fixpoint over reduction rules.
n6
n7
n8
n9
n3
Google Proprietary
Lowering to Machine
JSAdd
JSSubtract
JSMultiply
JSDivide
JSModulus
JSEqual
JSToBoolean
JSToNumber
JSCall
JSStrictEqual
JSBitwiseOr
JSDivide
JSBitwiseAnd
JSBitwiseXor
JSShiftLeft
JSShiftRight
NumberAdd
NumberSub
NumberMul
NumberDiv
NumberMod
NumberEqual
StringEqual
NumberLessThan
StringAdd
LoadField
StoreField
ChangeTaggedToInt32
Int32Add
Int32Sub
Int32Mul
Float64Add
Float64Sub
Float64Mul
Load
Store
Call
ConvertFloat64ToInt32
Google Proprietary
Lowering to Machine
expand and optimize
JS* and Simplified*
nodes
Google Proprietary
Floating Control
StringEqual
x
y
Branch
IfTrue
IfFalse
Merge
phi
true
PtrEqual
x
y
Call
lower and
expand fast
case
Google Proprietary
Floating Control
StringEqual
x
y
Branch
IfTrue
IfFalse
Merge
phi
x
y
lower and
expand fast
case
floating control diamond
not connected to
“main” control
Google Proprietary
Scheduling the Sea of Nodes
Google Proprietary
Scheduling the Sea of Nodes (sketch)
A
B
C
D
F
E
G
H
Control Flow Graph
A
B
C
D
F
E
G
H
Dominator
Tree
Unscheduled
nodes
Google Proprietary
Scheduling the Sea of Nodes (sketch)
A
B
C
D
F
E
G
H
Control Flow Graph
A
B
C
D
F
E
G
H
Dominator
Tree
Unscheduled
nodes
Place fixed
nodes
(phis, params)
Google Proprietary
Scheduling the Sea of Nodes (sketch)
A
B
C
D
F
E
G
H
Control Flow Graph
A
B
C
D
F
E
G
H
Dominator
Tree
Unscheduled
nodes
Google Proprietary
Scheduling the Sea of Nodes (sketch)
A
B
C
D
F
E
G
H
Control Flow Graph
A
B
C
D
F
E
G
H
Dominator
Tree
Schedulable
nodes
Google Proprietary
Scheduling the Sea of Nodes (sketch)
A
B
C
D
F
E
G
H
Control Flow Graph
A
B
C
D
F
E
G
H
Dominator
Tree
scheduled uses
inputs
must dominate
eligible node
Google Proprietary
Scheduling the Sea of Nodes (sketch)
A
B
C
D
F
E
G
H
Control Flow Graph
A
B
C
D
F
E
G
H
Dominator
Tree
Schedulable
nodes
Google Proprietary
Scheduling the Sea of Nodes (sketch)
A
B
C
D
F
E
G
H
Control Flow Graph
A
B
C
D
F
E
G
H
Dominator
Tree
Schedulable
nodes
Google Proprietary
Scheduling the Sea of Nodes (sketch)
A
B
C
D
F
E
G
H
Control Flow Graph
A
B
C
D
F
E
G
H
Dominator
Tree
Schedulable
nodes
Google Proprietary
Scheduling the Sea of Nodes (sketch)
A
B
C
D
F
E
G
H
Control Flow Graph
A
B
C
D
F
E
G
H
Dominator
Tree
Schedulable
nodes
Google Proprietary
Scheduling the Sea of Nodes (sketch)
A
B
C
D
F
E
G
H
Control Flow Graph
A
B
C
D
F
E
G
H
Dominator
Tree
Schedulable
nodes
Google Proprietary
Scheduling the Sea of Nodes (sketch)
A
B
C
D
F
E
G
H
Control Flow Graph
A
B
C
D
F
E
G
H
Dominator
Tree
Schedulable
nodes
Google Proprietary
Scheduling the Sea of Nodes (sketch)
A
B
C
D
F
E
G
H
Dominator
Tree
A fully scheduled graph is exactly the same as a CFG.
A
B
C
D
F
E
G
H
Control Flow Graph
Google Proprietary
Scheduling the Sea of Nodes (sketch)
A
B
C
D
F
E
G
H
Dominator
Tree
Placement is important!
Hoist code out of loops if possible
Place code as late as possible
Minimize register pressure
Eliminate redundancy
A
B
C
D
F
E
G
H
Control Flow Graph
Google Proprietary
Where is Loop Invariant Code Motion?
A
B
C
D
F
E
G
H
Dominator
Tree
Nowhere!
Scheduling subsumes loop invariant code motion.
A
B
C
D
F
E
G
H
Control Flow Graph
Google Proprietary
Instruction Selection (theory)
Load
obj
effect
*
4
i
Load
obj
effect
*
4
i
maximal
munch
mov %r0, [%r1 + %r2 * 4]
%r0
%r1
%r2
Google Proprietary
Instruction Selection (practice)
obj
effect
*
4
i
call
Load
Call
basic block
instruction sequence
cursor
visit nodes in blocks
in reverse CFG
order
Google Proprietary
Instruction Selection (practice)
obj
*
4
i
call
Load
Call
basic block
instruction sequence
cursor
visit nodes in blocks
in reverse CFG
order
Google Proprietary
Instruction Selection (practice)
obj
effect
*
4
i
call
Load
Call
basic block
instruction sequence
cursor
visit nodes in blocks
in reverse CFG
order
mov %r0, [%r1 + %r2 * 4]
Google Proprietary
Instruction Selection (practice)
obj
*
4
i
call
Load
Call
basic block
instruction sequence
cursor
mov %r0, [%r1 + %r2 * 4]
[%r2 = code for i]
Google Proprietary
Instruction Selection (practice)
obj
*
4
i
call
Load
Call
basic block
instruction sequence
cursor
mov %r0, [%r1 + %r2 * 4]
[%r2 = code for i]
[%r1 = code for obj]
Google Proprietary
Register Allocation
call
instruction sequence
mov %r0, [%r1 + %r2 * 4]
[%r2 = code for i]
[%r1 = code for obj]
TurboFan uses a linear scan allocator with
live range splitting to assign registers and
insert spill code.
SSA form can be deconstructed before or
after register allocation with explicit moves.
Google Proprietary
Register Allocation
call
instruction sequence
mov %ecx, [%eax + %ebx * 4]
[%ebx = code for i]
[%eax = code for obj]
TurboFan uses a linear scan allocator with
live range splitting to assign registers and
insert spill code.
SSA form can be deconstructed before or
after register allocation with explicit moves.
The result of register allocation is to replace uses of virtual registers with real registers and to insert spill code between instructions.
mov [sp + 12], %eax
Google Proprietary
Testability
Google Proprietary
Status
Google Proprietary
Thank You!
Andreas Rossberg
Jaroslav Sevcik
Sven Panne
Ben L. Titzer
Michael Starzinger
Daniel Clifford
Benedikt Meurer
Dan Carney
Sigurd Schneider
Georg Neis
Google Proprietary