What’s inside of TurboFan?
Benedikt Meurer
@bmeurer
Overview
IGNITION
What is TurboFan?
launched in
and !
Unified code generation architecture
WASM
Compiler
TurboFan
Optimizing
Compiler
Built-in Operations
TurboFan code
generation
architecture
Instruction Selector
Code Generator
Register Allocator
Intel, ARM, PowerPC,
MIPS
Control flow graph
Scheduler
“Sea of nodes” graph
C++ DSL
CodeStubAssembler
Ignition Interpreter
Bytecodes
TurboFan Optimizing Compiler
Bytecode
Bytecode
GraphBuilder
“Sea of nodes” graph
Specialization
Inlining
Bytecode
Profiling Feedback
Frontend
Typed
Optimization
Redundancy Elimination
Escape Analysis
Representation Selection
Optimization
Machine-level Optimization
Scheduling
Control flow graph
Code Generation
Intel, ARM, PowerPC,
MIPS
Backend
Inlining
Inlining
function add(x, y) {
return x + y;�}
�function three() {� return add(1, 2);�}
function three_add_inlined() {� var x = 1;
var y = 2;� var add_return_value = x + y;� return add_return_value;�}
function three_add_const_folded() {� return 3;�}
Constant-
folding
Inlining
leaq rcx,[rip+0x0]�movq rcx,[rcx-0x37]�testb [rcx+0xf],0x1�jnz CompileLazyDeoptimizedCode�push rbp�movq rbp,rsp�push rsi�push rdi�cmpq rsp,[r13+0xdb0]�jna StackCheck�movq rax,[rbp+0x18]�test al,0x1�jnz Deoptimize�movq rbx,[rbp+0x10]�testb rbx,0x1�jnz Deoptimize�movq rdx,rbx�shrq rdx, 32�movq rcx,rax�shrq rcx, 32�addl rdx,rcx�jo Deoptimize�shlq rdx, 32�movq rax,rdx�movq rsp,rbp�pop rbp�ret 0x18
function add(x, y) {
return x + y;�}
�function three() {� return add(1, 2);�}
Inlining
leaq rcx,[rip+0x0]�movq rcx,[rcx-0x37]�testb [rcx+0xf],0x1�jnz CompileLazyDeoptimizedCode�push rbp�movq rbp,rsp�push rsi�push rdi�cmpq rsp,[r13+0xdb0]�jna StackCheck�movq rax,[rbp+0x18]�test al,0x1�jnz Deoptimize�movq rbx,[rbp+0x10]�testb rbx,0x1�jnz Deoptimize�movq rdx,rbx�shrq rdx, 32�movq rcx,rax�shrq rcx, 32�addl rdx,rcx�jo Deoptimize�shlq rdx, 32�movq rax,rdx�movq rsp,rbp�pop rbp�ret 0x18
function add(x, y) {
return x + y;�}
�function three() {� return add(1, 2);�}
Prologue
Inlining
leaq rcx,[rip+0x0]�movq rcx,[rcx-0x37]�testb [rcx+0xf],0x1�jnz CompileLazyDeoptimizedCode�push rbp�movq rbp,rsp�push rsi�push rdi�cmpq rsp,[r13+0xdb0]�jna StackCheck�movq rax,[rbp+0x18]�test al,0x1�jnz Deoptimize�movq rbx,[rbp+0x10]�testb rbx,0x1�jnz Deoptimize�movq rdx,rbx�shrq rdx, 32�movq rcx,rax�shrq rcx, 32�addl rdx,rcx�jo Deoptimize�shlq rdx, 32�movq rax,rdx�movq rsp,rbp�pop rbp�ret 0x18
function add(x, y) {
return x + y;�}
�function three() {� return add(1, 2);�}
Check x is a small integer
Prologue
Inlining
leaq rcx,[rip+0x0]�movq rcx,[rcx-0x37]�testb [rcx+0xf],0x1�jnz CompileLazyDeoptimizedCode�push rbp�movq rbp,rsp�push rsi�push rdi�cmpq rsp,[r13+0xdb0]�jna StackCheck�movq rax,[rbp+0x18]�test al,0x1�jnz Deoptimize�movq rbx,[rbp+0x10]�testb rbx,0x1�jnz Deoptimize�movq rdx,rbx�shrq rdx, 32�movq rcx,rax�shrq rcx, 32�addl rdx,rcx�jo Deoptimize�shlq rdx, 32�movq rax,rdx�movq rsp,rbp�pop rbp�ret 0x18
function add(x, y) {
return x + y;�}
�function three() {� return add(1, 2);�}
Check x is a small integer
Check y is a small integer
Prologue
Inlining
leaq rcx,[rip+0x0]�movq rcx,[rcx-0x37]�testb [rcx+0xf],0x1�jnz CompileLazyDeoptimizedCode�push rbp�movq rbp,rsp�push rsi�push rdi�cmpq rsp,[r13+0xdb0]�jna StackCheck�movq rax,[rbp+0x18]�test al,0x1�jnz Deoptimize�movq rbx,[rbp+0x10]�testb rbx,0x1�jnz Deoptimize�movq rdx,rbx�shrq rdx, 32�movq rcx,rax�shrq rcx, 32�addl rdx,rcx�jo Deoptimize�shlq rdx, 32�movq rax,rdx�movq rsp,rbp�pop rbp�ret 0x18
function add(x, y) {
return x + y;�}
�function three() {� return add(1, 2);�}
Check x is a small integer
Check y is a small integer
Convert y from tagged representation to word32
Prologue
Inlining
leaq rcx,[rip+0x0]�movq rcx,[rcx-0x37]�testb [rcx+0xf],0x1�jnz CompileLazyDeoptimizedCode�push rbp�movq rbp,rsp�push rsi�push rdi�cmpq rsp,[r13+0xdb0]�jna StackCheck�movq rax,[rbp+0x18]�test al,0x1�jnz Deoptimize�movq rbx,[rbp+0x10]�testb rbx,0x1�jnz Deoptimize�movq rdx,rbx�shrq rdx, 32�movq rcx,rax�shrq rcx, 32�addl rdx,rcx�jo Deoptimize�shlq rdx, 32�movq rax,rdx�movq rsp,rbp�pop rbp�ret 0x18
function add(x, y) {
return x + y;�}
�function three() {� return add(1, 2);�}
Check x is a small integer
Check y is a small integer
Convert y from tagged representation to word32
Convert x from tagged representation to word32
Prologue
Inlining
leaq rcx,[rip+0x0]�movq rcx,[rcx-0x37]�testb [rcx+0xf],0x1�jnz CompileLazyDeoptimizedCode�push rbp�movq rbp,rsp�push rsi�push rdi�cmpq rsp,[r13+0xdb0]�jna StackCheck�movq rax,[rbp+0x18]�test al,0x1�jnz Deoptimize�movq rbx,[rbp+0x10]�testb rbx,0x1�jnz Deoptimize�movq rdx,rbx�shrq rdx, 32�movq rcx,rax�shrq rcx, 32�addl rdx,rcx�jo Deoptimize�shlq rdx, 32�movq rax,rdx�movq rsp,rbp�pop rbp�ret 0x18
function add(x, y) {
return x + y;�}
�function three() {� return add(1, 2);�}
Check x is a small integer
Check y is a small integer
Convert y from tagged representation to word32
Convert x from tagged representation to word32
Add x and y (incl. overflow check)
Prologue
Inlining
leaq rcx,[rip+0x0]�movq rcx,[rcx-0x37]�testb [rcx+0xf],0x1�jnz CompileLazyDeoptimizedCode�push rbp�movq rbp,rsp�push rsi�push rdi�cmpq rsp,[r13+0xdb0]�jna StackCheck�movq rax,[rbp+0x18]�test al,0x1�jnz Deoptimize�movq rbx,[rbp+0x10]�testb rbx,0x1�jnz Deoptimize�movq rdx,rbx�shrq rdx, 32�movq rcx,rax�shrq rcx, 32�addl rdx,rcx�jo Deoptimize�shlq rdx, 32�movq rax,rdx�movq rsp,rbp�pop rbp�ret 0x18
function add(x, y) {
return x + y;�}
�function three() {� return add(1, 2);�}
Check x is a small integer
Check y is a small integer
Convert y from tagged representation to word32
Convert x from tagged representation to word32
Add x and y (incl. overflow check)
Convert result to tagged representation
Prologue
Inlining
leaq rcx,[rip+0x0]�movq rcx,[rcx-0x37]�testb [rcx+0xf],0x1�jnz CompileLazyDeoptimizedCode�push rbp�movq rbp,rsp�push rsi�push rdi�cmpq rsp,[r13+0xdb0]�jna StackCheck�movq rax,[rbp+0x18]�test al,0x1�jnz Deoptimize�movq rbx,[rbp+0x10]�testb rbx,0x1�jnz Deoptimize�movq rdx,rbx�shrq rdx, 32�movq rcx,rax�shrq rcx, 32�addl rdx,rcx�jo Deoptimize�shlq rdx, 32�movq rax,rdx�movq rsp,rbp�pop rbp�ret 0x18
function add(x, y) {
return x + y;�}
�function three() {� return add(1, 2);�}
Check x is a small integer
Check y is a small integer
Convert y from tagged representation to word32
Convert x from tagged representation to word32
Add x and y (incl. overflow check)
Convert result to tagged representation
Epilogue
Prologue
Inlining
leaq rcx,[rip+0x0]�movq rcx,[rcx-0x37]�testb [rcx+0xf],0x1�jnz CompileLazyDeoptimizedCode�push rbp�movq rbp,rsp�push rsi�push rdi�cmpq rsp,[r13+0xdb0]�jna StackCheck�movq rdi,<JSFunction add>�movq rsi,[rdi+0x1f]�movq rax,<JSGlobal Object>�push rax�movq rax,0x100000000�push rax�movq rax,0x200000000�push rax�movq rdx,[r13-0x60]�movl rax,0x2�movq rcx,[rdi+0x2f]�addq rcx,0x5f�call rcx�movq rsp,rbp�pop rbp�ret 0x8
function add(x, y) {
return x + y;�}
�function three() {� return add(1, 2);�}
Inlining
leaq rcx,[rip+0x0]�movq rcx,[rcx-0x37]�testb [rcx+0xf],0x1�jnz CompileLazyDeoptimizedCode�push rbp�movq rbp,rsp�push rsi�push rdi�cmpq rsp,[r13+0xdb0]�jna StackCheck�movq rdi,<JSFunction add>�movq rsi,[rdi+0x1f]�movq rax,<JSGlobal Object>�push rax�movq rax,0x100000000�push rax�movq rax,0x200000000�push rax�movq rdx,[r13-0x60]�movl rax,0x2�movq rcx,[rdi+0x2f]�addq rcx,0x5f�call rcx�movq rsp,rbp�pop rbp�ret 0x8
function add(x, y) {
return x + y;�}
�function three() {� return add(1, 2);�}
Prologue
Inlining
leaq rcx,[rip+0x0]�movq rcx,[rcx-0x37]�testb [rcx+0xf],0x1�jnz CompileLazyDeoptimizedCode�push rbp�movq rbp,rsp�push rsi�push rdi�cmpq rsp,[r13+0xdb0]�jna StackCheck�movq rdi,<JSFunction add>�movq rsi,[rdi+0x1f]�movq rax,<JSGlobal Object>�push rax�movq rax,0x100000000�push rax�movq rax,0x200000000�push rax�movq rdx,[r13-0x60]�movl rax,0x2�movq rcx,[rdi+0x2f]�addq rcx,0x5f�call rcx�movq rsp,rbp�pop rbp�ret 0x8
function add(x, y) {
return x + y;�}
�function three() {� return add(1, 2);�}
Load call target add
Prologue
Inlining
leaq rcx,[rip+0x0]�movq rcx,[rcx-0x37]�testb [rcx+0xf],0x1�jnz CompileLazyDeoptimizedCode�push rbp�movq rbp,rsp�push rsi�push rdi�cmpq rsp,[r13+0xdb0]�jna StackCheck�movq rdi,<JSFunction add>�movq rsi,[rdi+0x1f]�movq rax,<JSGlobal Object>�push rax�movq rax,0x100000000�push rax�movq rax,0x200000000�push rax�movq rdx,[r13-0x60]�movl rax,0x2�movq rcx,[rdi+0x2f]�addq rcx,0x5f�call rcx�movq rsp,rbp�pop rbp�ret 0x8
function add(x, y) {
return x + y;�}
�function three() {� return add(1, 2);�}
Load call target add
Load call parameters
Prologue
Inlining
leaq rcx,[rip+0x0]�movq rcx,[rcx-0x37]�testb [rcx+0xf],0x1�jnz CompileLazyDeoptimizedCode�push rbp�movq rbp,rsp�push rsi�push rdi�cmpq rsp,[r13+0xdb0]�jna StackCheck�movq rdi,<JSFunction add>�movq rsi,[rdi+0x1f]�movq rax,<JSGlobal Object>�push rax�movq rax,0x100000000�push rax�movq rax,0x200000000�push rax�movq rdx,[r13-0x60]�movl rax,0x2�movq rcx,[rdi+0x2f]�addq rcx,0x5f�call rcx�movq rsp,rbp�pop rbp�ret 0x8
function add(x, y) {
return x + y;�}
�function three() {� return add(1, 2);�}
Load call target add
Load call parameters
Call sequence
Prologue
Inlining
leaq rcx,[rip+0x0]�movq rcx,[rcx-0x37]�testb [rcx+0xf],0x1�jnz CompileLazyDeoptimizedCode�push rbp�movq rbp,rsp�push rsi�push rdi�cmpq rsp,[r13+0xdb0]�jna StackCheck�movq rdi,<JSFunction add>�movq rsi,[rdi+0x1f]�movq rax,<JSGlobal Object>�push rax�movq rax,0x100000000�push rax�movq rax,0x200000000�push rax�movq rdx,[r13-0x60]�movl rax,0x2�movq rcx,[rdi+0x2f]�addq rcx,0x5f�call rcx�movq rsp,rbp�pop rbp�ret 0x8
function add(x, y) {
return x + y;�}
�function three() {� return add(1, 2);�}
Load call target add
Load call parameters
Call sequence
Epilogue
Prologue
Inlining
function add(x, y) {
return x + y;�}
�function three() {� return add(1, 2);�}
leaq rcx,[rip+0x0]�movq rcx,[rcx-0x37]�testb [rcx+0xf],0x1�jnz CompileLazyDeoptimizedCode�push rbp�movq rbp,rsp�push rsi�push rdi�cmpq rsp,[r13+0xdb0]�jna StackCheck�movq rax,0x300000000�movq rsp,rbp�pop rbp�ret 0x8
Inlining
function add(x, y) {
return x + y;�}
�function three() {� return add(1, 2);�}
leaq rcx,[rip+0x0]�movq rcx,[rcx-0x37]�testb [rcx+0xf],0x1�jnz CompileLazyDeoptimizedCode�push rbp�movq rbp,rsp�push rsi�push rdi�cmpq rsp,[r13+0xdb0]�jna StackCheck�movq rax,0x300000000�movq rsp,rbp�pop rbp�ret 0x8
Prologue
Inlining
function add(x, y) {
return x + y;�}
�function three() {� return add(1, 2);�}
leaq rcx,[rip+0x0]�movq rcx,[rcx-0x37]�testb [rcx+0xf],0x1�jnz CompileLazyDeoptimizedCode�push rbp�movq rbp,rsp�push rsi�push rdi�cmpq rsp,[r13+0xdb0]�jna StackCheck�movq rax,0x300000000�movq rsp,rbp�pop rbp�ret 0x8
Load tagged value 3
Prologue
Inlining
function add(x, y) {
return x + y;�}
�function three() {� return add(1, 2);�}
leaq rcx,[rip+0x0]�movq rcx,[rcx-0x37]�testb [rcx+0xf],0x1�jnz CompileLazyDeoptimizedCode�push rbp�movq rbp,rsp�push rsi�push rdi�cmpq rsp,[r13+0xdb0]�jna StackCheck�movq rax,0x300000000�movq rsp,rbp�pop rbp�ret 0x8
Load tagged value 3
Epilogue
Prologue
Inlining
leaq rcx,[rip+0x0]�movq rcx,[rcx-0x37]�testb [rcx+0xf],0x1�jnz CompileLazyDeoptimizedCode�push rbp�movq rbp,rsp�push rsi�push rdi�cmpq rsp,[r13+0xdb0]�jna StackCheck�movq rax,0x300000000�movq rsp,rbp�pop rbp�ret 0x8
leaq rcx,[rip+0x0]�movq rcx,[rcx-0x37]�testb [rcx+0xf],0x1�jnz CompileLazyDeoptimizedCode�push rbp�movq rbp,rsp�push rsi�push rdi�cmpq rsp,[r13+0xdb0]�jna StackCheck�movq rdi,<JSFunction add>�movq rsi,[rdi+0x1f]�movq rax,<JSGlobal Object>�push rax�movq rax,0x100000000�push rax�movq rax,0x200000000�push rax�movq rdx,[r13-0x60]�movl rax,0x2�movq rcx,[rdi+0x2f]�addq rcx,0x5f�call rcx�movq rsp,rbp�pop rbp�ret 0x8
leaq rcx,[rip+0x0]�movq rcx,[rcx-0x37]�testb [rcx+0xf],0x1�jnz CompileLazyDeoptimizedCode�push rbp�movq rbp,rsp�push rsi�push rdi�cmpq rsp,[r13+0xdb0]�jna StackCheck�movq rax,[rbp+0x18]�test al,0x1�jnz Deoptimize�movq rbx,[rbp+0x10]�testb rbx,0x1�jnz Deoptimize�movq rdx,rbx�shrq rdx, 32�movq rcx,rax�shrq rcx, 32�addl rdx,rcx�jo Deoptimize�shlq rdx, 32�movq rax,rdx�movq rsp,rbp�pop rbp�ret 0x18
+
vs
Inlining
Builtin Inlining
Higher-order Array Builtins
function allPositive(a) {� return a.every(x => x >= 0);�}
allPositive([-1, 0, 1]);
// => false
allPositive([1, 2, 3, 4]);
// => true
Higher-order Array Builtins
function allPositive(a) {� return a.every(x => x >= 0);�}
function allPositiveManual(a) {� var l = a.length;� for (var i = 0; i < l; ++i) {� if (a[i] < 0) {
return false;� }� }� return true;�}
vs
Higher-order Array Builtins
function allPositive(a) {� return a.every(x => x >= 0);�}
Higher-order Array Builtins
function allPositive(a) {� return a.every(x => x >= 0);�}
function allPositive_every(a) {� var c = x => x >= 0;� var l = a.length;� if (typeof c !== "function") {� throw new TypeError();� }� for (var i = 0; i < l; ++i) {� if (i in a) {� if (!c(a[i])) {
return false;� }� }� }� return true;�}
Higher-order Array Builtins
function allPositive_every(a) {� var c = x => x >= 0;� var l = a.length;� if (typeof c !== "function") {� throw new TypeError();� }� for (var i = 0; i < l; ++i) {� if (i in a) {� if (!c(a[i])) {
return false;� }� }� }� return true;�}
Higher-order Array Builtins
function allPositive_every(a) {� var c = x => x >= 0;� var l = a.length;� if (typeof c !== "function") {� throw new TypeError();� }� for (var i = 0; i < l; ++i) {� if (i in a) {� if (!c(a[i])) {
return false;� }� }� }� return true;�}
Higher-order Array Builtins
function allPositive_every(a) {� var c = x => x >= 0;� var l = a.length;� if (typeof c !== "function") {� throw new TypeError();� }� for (var i = 0; i < l; ++i) {� if (i in a) {� if (!c(a[i])) {
return false;� }� }� }� return true;�}
Higher-order Array Builtins
function allPositive_every(a) {� var c = x => x >= 0;� var l = a.length;� if (typeof c !== "function") {� throw new TypeError();� }� for (var i = 0; i < l; ++i) {� if (i in a) {� if (!(a[i] >= 0)) {
return false;� }� }� }� return true;�}
Higher-order Array Builtins
function allPositive_every(a) {� var c = x => x >= 0;� var l = a.length;� if (typeof c !== "function") {� throw new TypeError();� }� for (var i = 0; i < l; ++i) {� if (i in a) {� if (!(a[i] >= 0)) {
return false;� }� }� }� return true;�}
Higher-order Array Builtins
function allPositive(a) {� return a.every(x => x >= 0);�}
function allPositive_every(a) {� var l = a.length;� for (var i = 0; i < l; ++i) {� if (!(a[i] >= 0)) {
return false;� }� }� return true;�}
Higher-order Array Builtins - Performance
Higher-order Array Builtins - Performance
Full support planned for Chrome 66 / Node 10
Higher-order Array Builtins - Performance
Not just Array builtins...
Function builtins
function dispatch(f, ...args) {� return f.apply(this, args);�}
args are forwarded to f
Function builtins
function dispatch(f, ...args) {� return f.apply(this, args);�}
leaq rcx,[rip+0x0]�movq rcx,[rcx-0x37]�testb [rcx+0xf],0x1�jnz CompileLazyDeoptimizedCode�push rbp�movq rbp,rsp�push rsi�push rdi�cmpq rsp,[r13+0xe60]�jna StackCheck�movq rbx,[rbp+0x10]�testb rbx,0x1�jz Deoptimize�movq rax,<JSFunction hidden class>�cmpq [rbx-0x1],rax�jnz Deoptimize�movq rdx,[rbp+0x18]�push rdx�xorl rax,rax�movl rcx,0x1�movq rdi,rbx�movq rsi,[rbp-0x8]�call CallForwardVarargs�movq rsp,rbp�pop rbp�ret 0x10
Function builtins
function dispatch(f, ...args) {� return f.apply(this, args);�}
leaq rcx,[rip+0x0]�movq rcx,[rcx-0x37]�testb [rcx+0xf],0x1�jnz CompileLazyDeoptimizedCode�push rbp�movq rbp,rsp�push rsi�push rdi�cmpq rsp,[r13+0xe60]�jna StackCheck�movq rbx,[rbp+0x10]�testb rbx,0x1�jz Deoptimize�movq rax,<JSFunction hidden class>�cmpq [rbx-0x1],rax�jnz Deoptimize�movq rdx,[rbp+0x18]�push rdx�xorl rax,rax�movl rcx,0x1�movq rdi,rbx�movq rsi,[rbp-0x8]�call CallForwardVarargs�movq rsp,rbp�pop rbp�ret 0x10
Prologue
Function builtins
function dispatch(f, ...args) {� return f.apply(this, args);�}
leaq rcx,[rip+0x0]�movq rcx,[rcx-0x37]�testb [rcx+0xf],0x1�jnz CompileLazyDeoptimizedCode�push rbp�movq rbp,rsp�push rsi�push rdi�cmpq rsp,[r13+0xe60]�jna StackCheck�movq rbx,[rbp+0x10]�testb rbx,0x1�jz Deoptimize�movq rax,<JSFunction hidden class>�cmpq [rbx-0x1],rax�jnz Deoptimize�movq rdx,[rbp+0x18]�push rdx�xorl rax,rax�movl rcx,0x1�movq rdi,rbx�movq rsi,[rbp-0x8]�call CallForwardVarargs�movq rsp,rbp�pop rbp�ret 0x10
Prologue
Check f is not a small integer
Function builtins
function dispatch(f, ...args) {� return f.apply(this, args);�}
leaq rcx,[rip+0x0]�movq rcx,[rcx-0x37]�testb [rcx+0xf],0x1�jnz CompileLazyDeoptimizedCode�push rbp�movq rbp,rsp�push rsi�push rdi�cmpq rsp,[r13+0xe60]�jna StackCheck�movq rbx,[rbp+0x10]�testb rbx,0x1�jz Deoptimize�movq rax,<JSFunction hidden class>�cmpq [rbx-0x1],rax�jnz Deoptimize�movq rdx,[rbp+0x18]�push rdx�xorl rax,rax�movl rcx,0x1�movq rdi,rbx�movq rsi,[rbp-0x8]�call CallForwardVarargs�movq rsp,rbp�pop rbp�ret 0x10
Prologue
Check f is not a small integer
Check f is a JSFunction
Function builtins
function dispatch(f, ...args) {� return f.apply(this, args);�}
leaq rcx,[rip+0x0]�movq rcx,[rcx-0x37]�testb [rcx+0xf],0x1�jnz CompileLazyDeoptimizedCode�push rbp�movq rbp,rsp�push rsi�push rdi�cmpq rsp,[r13+0xe60]�jna StackCheck�movq rbx,[rbp+0x10]�testb rbx,0x1�jz Deoptimize�movq rax,<JSFunction hidden class>�cmpq [rbx-0x1],rax�jnz Deoptimize�movq rdx,[rbp+0x18]�push rdx�xorl rax,rax�movl rcx,0x1�movq rdi,rbx�movq rsi,[rbp-0x8]�call CallForwardVarargs�movq rsp,rbp�pop rbp�ret 0x10
Prologue
Check f is not a small integer
Check f is a JSFunction
Call f with incoming parameters (skipping the first)
Function builtins
function dispatch(f, ...args) {� return f.apply(this, args);�}
leaq rcx,[rip+0x0]�movq rcx,[rcx-0x37]�testb [rcx+0xf],0x1�jnz CompileLazyDeoptimizedCode�push rbp�movq rbp,rsp�push rsi�push rdi�cmpq rsp,[r13+0xe60]�jna StackCheck�movq rbx,[rbp+0x10]�testb rbx,0x1�jz Deoptimize�movq rax,<JSFunction hidden class>�cmpq [rbx-0x1],rax�jnz Deoptimize�movq rdx,[rbp+0x18]�push rdx�xorl rax,rax�movl rcx,0x1�movq rdi,rbx�movq rsi,[rbp-0x8]�call CallForwardVarargs�movq rsp,rbp�pop rbp�ret 0x10
Prologue
Check f is not a small integer
Check f is a JSFunction
Call f with incoming parameters (skipping the first)
Epilogue
Function builtins
function dispatch(f, ...args) {� return f.apply(this, args);�}
function dispatchManual() {� var l = arguments.length;� var f = arguments[0];� switch (l) {� case 1: return f.call(this);� case 2: return f.call(this,
arguments[1]);� default: {� var a = new Array(l - 1);� for (var i = 1; i < l; ++i)
a[i - 1] = arguments[i];� return f.apply(this, a);� }� }�}
vs
Function builtins
Builtin Inlining
Predictable
Performance
Performance cliffs in Crankshaft
(function good() {� const start = Date.now();� for (var i = 0; i < 1e8; i++) {}� console.log(Date.now() - start);�})();
(function bad() {� const start = Date.now();� for (var i = 0; i < 1e8; i++) {}� console.log(Date.now() - start);� const whatever = 1;�})();
Runs ~80ms
Runs ~230ms
~3x slowdown�with Crankshaft
\o/
Optimization Killers
It’s not just�optimized code...
Octane/Crypto test
TypeScript 2.1.6 compiling itself
Octane/Crypto test
Loading www.nytimes.com
Octane/Crypto test
Performance Results
60% faster web developer tools
1.7× faster on ARES-6
What’s coming in 2018?
Follow us!
@v8js
Benedikt Meurer�@bmeurer
Thanks!