Upgrade to Pro — share decks privately, control downloads, hide ads and more …

When Bits Hit the TurboFan

Avatar for Yarden Laifenfeld Yarden Laifenfeld
June 23, 2024
210

When Bits Hit the TurboFan

Avatar for Yarden Laifenfeld

Yarden Laifenfeld

June 23, 2024
Tweet

Transcript

  1. • Software Engineer & Dev Advocate at Dynatrace • Interested

    in compilers • And everything else software internals • Also debuggers Who Am I
  2. v8’s Parts (Pre-2021) • Parser - creates AST • Ignition

    - JavaScript interpreter • TurboFan - JavaScript bytecode compiler
  3. v8’s Parts - Parser function add(a, b) { return a

    + b; } { "type": "Program", "body": [ { "type": "FunctionDeclaration", "id": { "type": "Identifier", "name": "add" }, "params": [...], "body": {...}, "generator": false, "expression": false, "async": false } ], "sourceType": "script" } esprima.org
  4. v8’s Parts - Parser function add(a, b) { return a

    + b; } { "type": "Program", "body": [ { "type": "FunctionDeclaration", "id": { "type": "Identifier", "name": "add" }, "params": [...], "body": {...}, "generator": false, "expression": false, "async": false } ], "sourceType": "script" } esprima.org add
  5. v8’s Parts - Parser function add(a, b) { return a

    + b; } { "type": "Program", "body": [ { "type": "FunctionDeclaration", "id": { "type": "Identifier", "name": "add" }, "params": [...], "body": {...}, "generator": false, "expression": false, "async": false } ], "sourceType": "script" } esprima.org add params
  6. v8’s Parts - Parser function add(a, b) { return a

    + b; } "params": [ { "type": "Identifier", "name": "a" }, { "type": "Identifier", "name": "b" } ], esprima.org add a b params
  7. v8’s Parts - Parser function add(a, b) { return a

    + b; } { "type": "Program", "body": [ { "type": "FunctionDeclaration", "id": { "type": "Identifier", "name": "add" }, "params": [...], "body": {...}, "generator": false, "expression": false, "async": false } ], "sourceType": "script" } esprima.org add a b params body
  8. v8’s Parts - Parser function add(a, b) { return a

    + b; } "body": { "type": "BlockStatement", "body": [ { "type": "ReturnStatement", "argument": { "type": "BinaryExpression", "operator": "+", "left": { "type": "Identifier", "name": "a" }, "right": { "type": "Identifier", "name": "b" esprima.org add a b params body
  9. v8’s Parts - Parser function add(a, b) { return a

    + b; } "body": { "type": "BlockStatement", "body": [ { "type": "ReturnStatement", "argument": { "type": "BinaryExpression", "operator": "+", "left": { "type": "Identifier", "name": "a" }, "right": { "type": "Identifier", "name": "b" esprima.org add a b params body return
  10. v8’s Parts - Parser function add(a, b) { return a

    + b; } "body": { "type": "BlockStatement", "body": [ { "type": "ReturnStatement", "argument": { "type": "BinaryExpression", "operator": "+", "left": { "type": "Identifier", "name": "a" }, "right": { "type": "Identifier", "name": "b" esprima.org add a b params body return +
  11. v8’s Parts - Parser function add(a, b) { return a

    + b; } "body": { "type": "BlockStatement", "body": [ { "type": "ReturnStatement", "argument": { "type": "BinaryExpression", "operator": "+", "left": { "type": "Identifier", "name": "a" }, "right": { "type": "Identifier", "name": "b" esprima.org add a b params body return + a
  12. v8’s Parts - Parser function add(a, b) { return a

    + b; } "body": { "type": "BlockStatement", "body": [ { "type": "ReturnStatement", "argument": { "type": "BinaryExpression", "operator": "+", "left": { "type": "Identifier", "name": "a" }, "right": { "type": "Identifier", "name": "b" esprima.org add a b params body return + a b
  13. v8’s Parts (Pre-2021) • Parser - creates AST • Ignition

    - JavaScript interpreter • TurboFan - JavaScript bytecode compiler
  14. v8’s Parts - Ignition function add(a, b) { return a

    + b; } { "type": "Program", "body": [ { "type": "FunctionDeclaration", "id": { "type": "Identifier", "name": "add" }, "params": [...], "body": {...}, "generator": false, "expression": false, "async": false } ], "sourceType": "script" } Ldar a1 Add a0, [0] Return node --print-bytecode
  15. v8’s Parts - Ignition function add(a, b) { return a

    + b; } { "type": "Program", "body": [ { "type": "FunctionDeclaration", "id": { "type": "Identifier", "name": "add" }, "params": [...], "body": {...}, "generator": false, "expression": false, "async": false } ], "sourceType": "script" } Ldar a1 Add a0, [0] Return b node --print-bytecode
  16. v8’s Parts - Ignition function add(a, b) { return a

    + b; } { "type": "Program", "body": [ { "type": "FunctionDeclaration", "id": { "type": "Identifier", "name": "add" }, "params": [...], "body": {...}, "generator": false, "expression": false, "async": false } ], "sourceType": "script" } Ldar a1 Add a0, [0] Return b a, b node --print-bytecode
  17. Intermediate Representation (IR) • Data structure or code • Used

    by a compiler • Represents source code accurately • Better for optimization or translation
  18. v8’s Parts - Ignition function add(a, b) { return a

    + b; } { "type": "Program", "body": [ { "type": "FunctionDeclaration", "id": { "type": "Identifier", "name": "add" }, "params": [...], "body": {...}, "generator": false, "expression": false, "async": false } ], "sourceType": "script" } Ldar a1 Add a0, [0] Return b a, b node --print-bytecode
  19. v8’s Parts - Ignition • JavaScript “interpreter” • Maybe a

    compiler? • Also a virtual machine • A fast way to execute code slowly
  20. A Slow Way to Execute Code Fastly • CrankShaft ->

    TurboFan • Input: JavaScript bytecode Output: machine code • Optimize the code! ◦ Not all code
  21. TurboFan • Optimistic assumptions ◦ Type feedback from Ignition •

    Wrong assumptions lead to deoptimization function add(a, b) { return a + b; }
  22. TurboFan • Optimistic assumptions ◦ Type feedback from Ignition •

    Wrong assumptions lead to deoptimization function add(a, b) { return a + b; } add(1, 2)
  23. TurboFan • Optimistic assumptions ◦ Type feedback from Ignition •

    Wrong assumptions lead to deoptimization function add(a, b) { return a + b; } add(1, 2) add(1, 2)
  24. TurboFan • Optimistic assumptions ◦ Type feedback from Ignition •

    Wrong assumptions lead to deoptimization function add(a, b) { return a + b; } add(1, 2) add(1, 2) add(1, 2)
  25. TurboFan • Optimistic assumptions ◦ Type feedback from Ignition •

    Wrong assumptions lead to deoptimization function add(a, b) { return a + b; } add(1, 2) add(1, 2) add(1, 2) add(1, 2) optimization - a, b are Numbers
  26. TurboFan • Optimistic assumptions ◦ Type feedback from Ignition •

    Wrong assumptions lead to deoptimization function add(a, b) { return a + b; } add(1, 2) add(1, 2) add(1, 2) add(1, 2) add(1, 2) optimization - a, b are Numbers
  27. TurboFan • Optimistic assumptions ◦ Type feedback from Ignition •

    Wrong assumptions lead to deoptimization function add(a, b) { return a + b; } add(1, 2) add(1, 2) add(1, 2) add(1, 2) add(1, 2) add(1, 2) optimization - a, b are Numbers
  28. TurboFan • Optimistic assumptions ◦ Type feedback from Ignition •

    Wrong assumptions lead to deoptimization function add(a, b) { return a + b; } add(1, 2) add(1, 2) add(1, 2) add(1, 2) add(1, 2) add(1, 2) add(“abc”, “def”) optimization - a, b are Numbers deoptimization
  29. TurboFan - Sea of Nodes A sea of nodes is

    a graph representation of single-static assignment (SSA) representation of a program that combines data flow and control flow, and relaxes the control flow from a total order to a partial order, keeping only the orderings required by data flow.
  30. 01| let a = 1; 02| console.log(a); 03| a =

    2; 04| console.log(a); Single-Static Assignment (SSA)
  31. 01| let a0 = 1; 02| console.log(a0); 03| a1 =

    2; 04| console.log(a1); Single-Static Assignment (SSA)
  32. 01| let a = 1; 02| let b = a

    + 1; ... 04| let c = a + 1; Single-Static Assignment (SSA)
  33. 01| let a = 1; 02| let b = a

    + 1; 03| // Do nothing 04| let c = a + 1; Single-Static Assignment (SSA) 01| let a = 1; 02| let b = a + 1; 03| a = 2; 04| let c = a + 1;
  34. 01| let a0 = 1; 02| let b0 = a0

    + 1; 03| // Do nothing 04| let c0 = a0 + 1; Single-Static Assignment (SSA) 01| let a = 1; 02| let b = a + 1; 03| a = 2; 04| let c = a + 1;
  35. 01| let a0 = 1; 02| let b0 = a0

    + 1; 03| // Do nothing 04| let c0 = a0 + 1; Single-Static Assignment (SSA) 01| let a = 1; 02| let b = a + 1; 03| a = 2; 04| let c = a + 1; ✔ c0 = b0
  36. 01| let a0 = 1; 02| let b0 = a0

    + 1; 03| // Do nothing 04| let c0 = a0 + 1; Single-Static Assignment (SSA) 01| let a0 = 1; 02| let b0 = a0 + 1; 03| a1 = 2; 04| let c0 = a1 + 1; ✔ c0 = b0
  37. 01| let a0 = 1; 02| let b0 = a0

    + 1; 03| // Do nothing 04| let c0 = a0 + 1; Single-Static Assignment (SSA) 01| let a0 = 1; 02| let b0 = a0 + 1; 03| a1 = 2; 04| let c0 = a1 + 1; ✔ c0 = b0 ✘ c0 ≠ b0
  38. 01| if (a > 3) { 02| a = 2;

    03| } else { 04| a = 4; 05| } 06| console.log(a); Single-Static Assignment (SSA)
  39. 01| if (a0 > 3) { 02| a = 2;

    03| } else { 04| a = 4; 05| } 06| console.log(a); Single-Static Assignment (SSA)
  40. 01| if (a0 > 3) { 02| a1 = 2;

    03| } else { 04| a = 4; 05| } 06| console.log(a); Single-Static Assignment (SSA)
  41. 01| if (a0 > 3) { 02| a1 = 2;

    03| } else { 04| a2 = 4; 05| } 06| console.log(a); Single-Static Assignment (SSA)
  42. 01| if (a0 > 3) { 02| a1 = 2;

    03| } else { 04| a2 = 4; 05| } 06| console.log(a?); Single-Static Assignment (SSA)
  43. 01| if (a0 > 3) { 02| a1 = 2;

    03| } else { 04| a2 = 4; 05| } 06| console.log(a?); Single-Static Assignment (SSA)
  44. 01| if (a0 > 3) { 02| a1 = 2;

    03| } else { 04| a2 = 4; 05| } 06| console.log(a?); Single-Static Assignment (SSA)
  45. 01| if (a0 > 3) { 02| a1 = 2;

    03| } else { 04| a2 = 4; 05| } 06| console.log(a?); Single-Static Assignment (SSA) a0 > 3
  46. 01| if (a0 > 3) { 02| a1 = 2;

    03| } else { 04| a2 = 4; 05| } 06| console.log(a?); Single-Static Assignment (SSA) a0 > 3 a1 = 2 true
  47. 01| if (a0 > 3) { 02| a1 = 2;

    03| } else { 04| a2 = 4; 05| } 06| console.log(a?); Single-Static Assignment (SSA) a2 = 4 a0 > 3 a1 = 2 true false
  48. 01| if (a0 > 3) { 02| a1 = 2;

    03| } else { 04| a2 = 4; 05| } 06| console.log(a?); Single-Static Assignment (SSA) a2 = 4 a0 > 3 a1 = 2 true false
  49. • Used when different values can be assigned depending on

    which node we came from • Creates a new variable • Specify what the value options are Phi a2 = 4 a0 > 3 a1 = 2 true false a3 = ɸ(a1, a2)
  50. 01| if (a0 > 3) { 02| a1 = 2;

    03| } else { 04| a2 = 4; 05| } 06| console.log(a?); Single-Static Assignment (SSA) a2 = 4 a0 > 3 a1 = 2 true false a3 = ɸ(a1, a2)
  51. 01| if (a0 > 3) { 02| a1 = 2;

    03| } else { 04| a2 = 4; 05| } 06| console.log(a3); Single-Static Assignment (SSA) a2 = 4 a0 > 3 a1 = 2 true false a3 = ɸ(a1, a2) console.log(a3)
  52. 01| if (a0 > 3) { 02| a1 = 2;

    03| } else { 04| a2 = 4; 05| } 06| console.log(a3); Single-Static Assignment (SSA) a2 = 4 a0 > 3 a1 = 2 true false a3 = ɸ(a1, a2) console.log(a3)
  53. 01| if (a0 > 3) { 02| a1 = 2;

    03| } else { 04| a2 = 4; 05| } 06| console.log(a3); Control Flow Graph true false
  54. let a = 5; let b = 3; while (a

    < b) { b -= 1; a += 1; } Control Flow Graph • Basic Blocks ◦ Consecutive instructions • Control dependencies ◦ if, while, for, function, call, return • Doesn’t care about data
  55. func calcSum(arr) { let sum = 0; let i =

    0; while (i < arr.length) { sum += arr[i]; i += 1; } return sum; } Control Flow Graph
  56. func calcSum(arr) { let sum = 0; let i =

    0; while (i < arr.length) { sum += arr[i]; i += 1; } return sum; } Control Flow Graph Start
  57. func calcSum(arr) { let sum = 0; let i =

    0; while (i < arr.length) { sum += arr[i]; i += 1; } return sum; } Control Flow Graph Start let sum = 0 let i = 0
  58. func calcSum(arr) { let sum = 0; let i =

    0; while (i < arr.length) { sum += arr[i]; i += 1; } return sum; } Control Flow Graph Start i < arr.length let sum = 0 let i = 0 true false
  59. func calcSum(arr) { let sum = 0; let i =

    0; while (i < arr.length) { sum += arr[i]; i += 1; } return sum; } Control Flow Graph Start i < arr.length sum += arr[i] i += 1 let sum = 0 let i = 0 true false
  60. func calcSum(arr) { let sum = 0; let i =

    0; while (i < arr.length) { sum += arr[i]; i += 1; } return sum; } Control Flow Graph Start i < arr.length sum += arr[i] i += 1 return sum let sum = 0 let i = 0 true false
  61. func calcSum(arr) { let sum = 0; let i =

    0; while (i < arr.length) { sum += arr[i]; i += 1; } return sum; } Control Flow Graph Start i < arr.length sum += arr[i] i += 1 return sum End let sum = 0 let i = 0 true false
  62. func calcSum(arr) { let sum = 0; let i =

    0; while (i < arr.length) { sum += arr[i]; i += 1; } return sum; } Control Flow Graph Start End
  63. SSA & CFG func calcSum(arr) { let sum = 0;

    let i = 0; while (i < arr.length) { sum += arr[i]; i += 1; } return sum; } Start i < arr.length sum += arr[i] i += 1 return sum End var sum = 0 var i = 0 true false
  64. SSA & CFG func calcSum(arr) { let sum = 0;

    let i = 0; while (i < arr.length) { sum = sum + arr[i]; i = i + 1; } return sum; } Start i < arr.length sum = sum + arr[i] i = i + 1 return sum End var sum = 0 var i = 0 true false
  65. SSA & CFG func calcSum(arr) { let sum = 0;

    let i = 0; while (i < arr.length) { sum = sum + arr[i]; i = i + 1; } return sum; } Start i < arr.length sum = sum + arr[i] i = i + 1 return sum End var sum = 0 var i = 0 true false
  66. SSA & CFG func calcSum(arr) { let sum = 0;

    let i = 0; while (i < arr.length) { sum = sum + arr[i]; i = i + 1; } return sum; } Start i < arr.length sum = sum + arr[i] i = i + 1 return sum End var sum = 0 var i0 = 0 true false
  67. SSA & CFG func calcSum(arr) { let sum = 0;

    let i = 0; while (i < arr.length) { sum = sum + arr[i]; i = i + 1; } return sum; } Start i < arr.length sum = sum + arr[i] i1 = i + 1 return sum End var sum = 0 var i0 = 0 true false
  68. SSA & CFG func calcSum(arr) { let sum = 0;

    let i = 0; while (i < arr.length) { sum = sum + arr[i]; i = i + 1; } return sum; } Start i < arr.length return sum End var sum = 0 var i0 = 0 true sum = sum + arr[i] i1 = i + 1 false
  69. SSA & CFG func calcSum(arr) { let sum = 0;

    let i = 0; while (i < arr.length) { sum = sum + arr[i]; i = i + 1; } return sum; } Start i0 < arr.length return sum End var sum = 0 var i0 = 0 true sum = sum + arr[i] i1 = i1 + 1 false
  70. SSA & CFG func calcSum(arr) { let sum = 0;

    let i = 0; while (i < arr.length) { sum = sum + arr[i]; i = i + 1; } return sum; } Start i1 < arr.length return sum End var sum = 0 var i0 = 0 true sum = sum + arr[i] i1 = i + 1 false
  71. SSA & CFG func calcSum(arr) { let sum = 0;

    let i = 0; while (i < arr.length) { sum = sum + arr[i]; i = i + 1; } return sum; } Start i2 =ɸ(i0, i1) i < arr.length return sum End var sum = 0 var i0 = 0 true sum = sum + arr[i] i1 = i + 1 false
  72. SSA & CFG func calcSum(arr) { let sum = 0;

    let i = 0; while (i < arr.length) { sum = sum + arr[i]; i = i + 1; } return sum; } Start i2 =ɸ(i0, i1) i2 < arr.length return sum End var sum = 0 var i0 = 0 true sum = sum + arr[i] i1 = i + 1 false
  73. SSA & CFG func calcSum(arr) { let sum = 0;

    let i = 0; while (i < arr.length) { sum = sum + arr[i]; i = i + 1; } return sum; } Start i2 =ɸ(i0, i1) i2 < arr.length sum = sum + arr[i] i1 = i + 1 return sum End var sum = 0 var i0 = 0 true false
  74. SSA & CFG func calcSum(arr) { let sum = 0;

    let i = 0; while (i < arr.length) { sum = sum + arr[i]; i = i + 1; } return sum; } Start i2 =ɸ(i0, i1) i2 < arr.length sum = sum + arr[i] i1 = i + 1 return sum End var sum = 0 var i0 = 0 true false
  75. SSA & CFG func calcSum(arr) { let sum = 0;

    let i = 0; while (i < arr.length) { sum = sum + arr[i]; i = i + 1; } return sum; } Start i2 =ɸ(i0, i1) i2 < arr.length sum = sum + arr[i2] i1 = i2 + 1 return sum End var sum = 0 var i0 = 0 true false
  76. SSA & CFG func calcSum(arr) { let sum = 0;

    let i = 0; while (i < arr.length) { sum = sum + arr[i]; i = i + 1; } return sum; } Start i2 =ɸ(i0, i1) i2 < arr.length sum = sum + arr[i2] i1 = i2 + 1 return sum End var sum0 = 0 var i0 = 0 true false
  77. SSA & CFG func calcSum(arr) { let sum = 0;

    let i = 0; while (i < arr.length) { sum = sum + arr[i]; i = i + 1; } return sum; } Start i2 =ɸ(i0, i1) i2 < arr.length sum1 = sum + arr[i2] i1 = i2 + 1 return sum End var sum0 = 0 var i0 = 0 true false
  78. SSA & CFG func calcSum(arr) { let sum = 0;

    let i = 0; while (i < arr.length) { sum = sum + arr[i]; i = i + 1; } return sum; } Start i2 =ɸ(i0, i1) i2 < arr.length sum1 = sum + arr[i2] i1 = i2 + 1 return sum End var sum0 = 0 var i0 = 0 true false
  79. SSA & CFG func calcSum(arr) { let sum = 0;

    let i = 0; while (i < arr.length) { sum = sum + arr[i]; i = i + 1; } return sum; } Start i2 =ɸ(i0, i1) i2 < arr.length sum1 = sum + arr[i2] i1 = i2 + 1 return sum End var sum0 = 0 var i0 = 0 true false
  80. SSA & CFG func calcSum(arr) { let sum = 0;

    let i = 0; while (i < arr.length) { sum = sum + arr[i]; i = i + 1; } return sum; } Start i2 =ɸ(i0, i1) i2 < arr.length sum1 = sum + arr[i2] i1 = i2 + 1 return sum End var sum0 = 0 var i0 = 0 true false
  81. SSA & CFG func calcSum(arr) { let sum = 0;

    let i = 0; while (i < arr.length) { sum = sum + arr[i]; i = i + 1; } return sum; } Start sum2 = ɸ(sum0, sum1) i2 =ɸ(i0, i1) i2 < arr.length sum1 = sum + arr[i2] i1 = i2 + 1 return sum End var sum0 = 0 var i0 = 0 true false
  82. SSA & CFG func calcSum(arr) { let sum = 0;

    let i = 0; while (i < arr.length) { sum = sum + arr[i]; i = i + 1; } return sum; } Start sum2 = ɸ(sum0, sum1) i2 =ɸ(i0, i1) i2 < arr.length sum1 = sum + arr[i2] i1 = i2 + 1 return sum End var sum0 = 0 var i0 = 0 true false
  83. SSA & CFG func calcSum(arr) { let sum = 0;

    let i = 0; while (i < arr.length) { sum = sum + arr[i]; i = i + 1; } return sum; } Start sum2 = ɸ(sum0, sum1) i2 =ɸ(i0, i1) i2 < arr.length sum1 = sum2 + arr[i2] i1 = i2 + 1 return sum End var sum0 = 0 var i0 = 0 true false
  84. SSA & CFG func calcSum(arr) { let sum = 0;

    let i = 0; while (i < arr.length) { sum = sum + arr[i]; i = i + 1; } return sum; } Start sum2 = ɸ(sum0, sum1) i2 =ɸ(i0, i1) i2 < arr.length sum1 = sum2 + arr[i2] i1 = i2 + 1 return sum End var sum0 = 0 var i0 = 0 true false
  85. SSA & CFG func calcSum(arr) { let sum = 0;

    let i = 0; while (i < arr.length) { sum = sum + arr[i]; i = i + 1; } return sum; } Start sum2 = ɸ(sum0, sum1) i2 =ɸ(i0, i1) i2 < arr.length sum1 = sum2 + arr[i2] i1 = i2 + 1 return sum2 End var sum0 = 0 var i0 = 0 true false
  86. SSA & CFG func calcSum(arr) { let sum = 0;

    let i = 0; while (i < arr.length) { sum = sum + arr[i]; i = i + 1; } return sum; } Start sum2 = ɸ(sum0, sum1) i2 =ɸ(i0, i1) i2 < arr.length sum1 = sum2 + arr[i2] i1 = i2 + 1 return sum2 End var sum0 = 0 var i0 = 0 true false
  87. SSA & CFG func calcSum(arr) { let sum = 0;

    let i = 0; while (i < arr.length) { sum = sum + arr[i]; i = i + 1; } return sum; } Start sum2 = ɸ(sum0, sum1) i2 =ɸ(i0, i1) i2 < arr0.length sum1 = sum2 + arr0[i2] i1 = i2 + 1 return sum2 End var sum0 = 0 var i0 = 0 true false
  88. 01| let a = 3; 02| let b = a

    * 2; 03| let c = b + a; Data Flow Graph
  89. 01| let a = 3; 02| let b = a

    * 2; 03| let c = b + a; Data Flow Graph * a 2 b
  90. 01| let a = 3; 02| let b = a

    * 2; 03| let c = b + a; Data Flow Graph * + a 2 b a c
  91. func calcSum(arr) { let sum = 0; let i =

    0; while (i < arr.length) { sum += arr[i]; i += 1; } return sum; } Data Flow Graph
  92. while (i < arr.length) { sum += arr[i]; i +=

    1; } Data Flow Graph length arr
  93. while (i < arr.length) { sum += arr[i]; i +=

    1; } Data Flow Graph length arr < i
  94. while (i < arr.length) { sum += arr[i]; i +=

    1; } Data Flow Graph load arr i
  95. while (i < arr.length) { sum += arr[i]; i +=

    1; } Data Flow Graph load arr + sum i sum
  96. while (i < arr.length) { sum += arr[i]; i +=

    1; } + i 1 i Data Flow Graph
  97. while (i < arr.length) { sum += arr[i]; i +=

    1; } Data Flow Graph length arr < i + i 1 i load arr + sum i sum
  98. Sea of Nodes • SSA • CFG • DFG let

    a = 5; let b = 3; while (a < b) { b -= 1; a += 1; }
  99. • SSA • CFG • DFG Sea of Nodes let

    a = 5; let b = 3; while (a < b) { b -= 1; a += 1; }
  100. Sea of Nodes Source: https://darksi.de/d.sea-of-nodes/ arr.length: func calcSum(arr) { let

    sum = 0; let i = 0; while (i < arr.length) { sum = sum + arr[i]; i = i + 1; } return sum; }
  101. Sea of Nodes Source: https://darksi.de/d.sea-of-nodes/ arr.length: func calcSum(arr) { let

    sum = 0; let i = 0; let arrLen = arr.length; while (i < arrLen) { sum = sum + arr[i]; i = i + 1; } return sum;
  102. Sea of Nodes Source: https://darksi.de/d.sea-of-nodes/ • Allows less compiler passes

    • Removes unnecessary dependencies • Not cache-friendly • Slow
  103. • Be consistent with the types you pass to functions

    ◦ Avoids deoptimization • Declare properties in the constructor ◦ Avoids deoptimization • Declare classes in the global scope • Avoid arrays with holes ◦ const arr = [0]; arr[5] = 3; ◦ [ 0, <4 empty items>, 3 ] • Don’t be afraid to use builtins ◦ Array.prototype.forEach() How Can We Help TurboFan?
  104. v8’s Parts (Pre-2021) • Parser - creates AST • Ignition

    - JavaScript interpreter • TurboFan - JavaScript bytecode compiler
  105. v8’s Parts (Pre-2023) • Parser - creates AST • Ignition

    - JavaScript interpreter • Sparkplug - non-optimizing JavaScript bytecode compiler (no IR!) • TurboFan - JavaScript bytecode compiler
  106. v8’s Parts (Now) • Parser - creates AST • Ignition

    - JavaScript interpreter • Sparkplug - non-optimizing JavaScript bytecode compiler (no IR!) • Maglev - simple SSA compiler • TurboFan - JavaScript bytecode compiler
  107. Resources • https://v8.dev/docs - Official documentation, a lot of good

    stuff • https://www.youtube.com/watch?v=cvybnv79Sek - Talk by Benedikt Meurer about TurboFan • https://darksi.de/d.sea-of-nodes/ - Good explanation of Sea of Nodes • https://github.com/pranayga/expl0ring_V8/blob/master/docs/ Turbofan.md - Interesting doc about TurboFan • https://github.com/SeaOfNodes/Simple - Showcase of Sea of Nodes • https://www.youtube.com/watch?v=98lt45Aj8mo&t=1591s - Talk by Cliff Click (creator of Sea of Nodes) on Sea of Nodes