O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.

V8 by example: A journey through the compilation pipeline by Ujjwas Sharma at FrontCon 2019

435 visualizações

Publicada em

V8 is complicated. Things change way too fast and it’s really hard to keep track of what’s the fastest way of doing every specific action.
But not anymore. Join me, a V8 contributor, on a journey through the compilation pipeline of V8 and understand how it all works under the hood. We’ll take the example of a popular JavaScript builtin method and find that what does and does not trigger de-optimization.
By the end of the talk, you will have a fairly decent idea of how builtins are written inside the V8 compilation pipeline, and how to make sure you always take the fast path, no matter what.

Publicada em: Tecnologia
  • Seja o primeiro a comentar

V8 by example: A journey through the compilation pipeline by Ujjwas Sharma at FrontCon 2019

  1. 1. @ryzokuken V8 by Example A journey through the compilation pipeline 1
  2. 2. @ryzokuken Ujjwal Sharma (@ryzokuken) ● Node.js – Core Collaborator ● Electron.js – Maintainer ● Contribute to the JS/Node.js ecosystem ○ V8 ○ TC39 ○ libuv ○ … ● Student ● Google Summer of Code ● Speaker 2
  3. 3. @ryzokuken@ryzokuken What is V8? 3
  4. 4. @ryzokuken@ryzokuken4
  5. 5. @ryzokuken@ryzokuken How does V8 work? 5
  6. 6. @ryzokuken@ryzokuken6 Source
  7. 7. @ryzokuken@ryzokuken7 Source Parser
  8. 8. @ryzokuken@ryzokuken8 Source Parser
  9. 9. @ryzokuken@ryzokuken9 Source IIFE?
  10. 10. @ryzokuken@ryzokuken10 Source IIFE? Eager
  11. 11. @ryzokuken@ryzokuken11 Source IIFE? Lazy Eager
  12. 12. @ryzokuken@ryzokuken12 Source IIFE? * Eventually Eager Lazy
  13. 13. @ryzokuken@ryzokuken13 Source IIFE? Eager Lazy AST + Scopes
  14. 14. @ryzokuken@ryzokuken14 Source Parser AST + Scopes
  15. 15. @ryzokuken@ryzokuken15 Source Parser AST + Scopes Ignition
  16. 16. @ryzokuken@ryzokuken16 Source Parser AST + Scopes Ignition Bytecode
  17. 17. @ryzokuken@ryzokuken17 Source Parser AST + Scopes Ignition Bytecode
  18. 18. @ryzokuken@ryzokuken18 But interpreters are so slow! Idea: Let’s not be slow. Let’s use a JIT compiler.
  19. 19. @ryzokuken@ryzokuken19
  20. 20. @ryzokuken@ryzokuken20 Source Parser AST + Scopes Ignition Bytecode Turbofan + profiling data OPTIMIZE!
  21. 21. @ryzokuken@ryzokuken21 Source Parser AST + Scopes Ignition Bytecode Turbofan Optimized Code DEOPTIMIZE!
  22. 22. @ryzokuken@ryzokuken22 Source Parser AST + Scopes Ignition Bytecode Turbofan Optimized Code
  23. 23. @ryzokuken@ryzokuken How you feel about everything. Let’s take a couple steps back.23
  24. 24. @ryzokuken@ryzokuken How does V8 work? 24
  25. 25. @ryzokuken@ryzokuken How does V8 work? a compiler 25
  26. 26. @ryzokuken@ryzokuken Source Code Parser Abstract Syntax Tree Assembler Machine Code (R) Compiler Assembly Program Linker Machine Code (T) 26
  27. 27. @ryzokuken@ryzokuken Is it simple enough yet? 27
  28. 28. @ryzokuken@ryzokuken Source Code Parser Abstract Syntax Tree Assembler Machine Code (R) Compiler Assembly Program Linker Machine Code (T) 28
  29. 29. @ryzokuken@ryzokuken Source Code Parser Abstract Syntax Tree Compiler Machine Code (T) 29
  30. 30. @ryzokuken@ryzokuken30 BAD NEWS: V8 isn’t this simple
  31. 31. @ryzokuken@ryzokuken Because ECMAScript is slow by default, that’s why. 31
  32. 32. @ryzokuken@ryzokuken Idea: Let’s not be slow. BUT HOW? Speculative Optimization 32
  33. 33. @ryzokuken@ryzokuken But wait… What even is Speculative Optimization? 33
  34. 34. @ryzokuken@ryzokuken Speculative Optimization [spek-yuh-ley-tiv, -luh-tiv][op-tuh-muh-zey-shuh n] Noun. Guessing what is about to happen based on what has happened. 34
  35. 35. @ryzokuken@ryzokuken Speculative Optimization [spek-yuh-ley-tiv, -luh-tiv][op-tuh-muh-zey-shuh n] Noun. Guessing what is about to happen based on what has happened. Making assumptions about possible future inputs based on previous inputs. 35
  36. 36. @ryzokuken@ryzokuken Top three reasons why a JavaScript function might need optimization: 1. Dynamic Types 2. Dynamic Types 3. Dynamic Types Alright, but how does it help? 36
  37. 37. @ryzokuken@ryzokuken Source Code Parser Abstract Syntax Tree Compiler Machine Code (T) 37
  38. 38. @ryzokuken@ryzokuken Source Code Parser Abstract Syntax Tree 1. Baseline Interpreter 2. Optimizing Compiler Machine Code (T) 38
  39. 39. @ryzokuken@ryzokuken AST Baseline Interpreter Optimizing Compiler Bytecode Optimized Code optimize deoptimize 39
  40. 40. @ryzokuken@ryzokuken Compiler Baseline Interpreter Optimizing Compiler 40
  41. 41. @ryzokuken@ryzokuken AST Baseline Interpreter Optimizing Compiler Bytecode Optimized Code optimize deoptimize 41
  42. 42. @ryzokuken@ryzokuken AST Bytecode Optimized Code optimize deoptimize 42
  43. 43. @ryzokuken@ryzokuken43 Okay, that’s great. But how does it even work? Let’s consider an example.
  44. 44. @ryzokuken@ryzokuken44 function add(x, y) { return x + y; } console.log(add(1, 2));
  45. 45. @ryzokuken@ryzokuken45 Not too intuitive? I’ve got you covered, fam. Let’s see how the Abstract Syntax Tree actually looks.
  46. 46. @ryzokuken@ryzokuken46 [generating bytecode for function: add] --- AST --- FUNC at 12 . KIND 0 . SUSPEND COUNT 0 . NAME "add" . PARAMS . . VAR (...) (mode = VAR) "x" . . VAR (...) (mode = VAR) "y" . RETURN at 22 . . ADD at 31 . . . VAR PROXY parameter[0] (...) (mode = VAR) "x" . . . VAR PROXY parameter[1] (...) (mode = VAR) "y"
  47. 47. @ryzokuken@ryzokuken47 [generating bytecode for function: add] --- AST --- FUNC at 12 . KIND 0 . SUSPEND COUNT 0 . NAME "add" . PARAMS . . VAR (...) (mode = VAR) "x" . . VAR (...) (mode = VAR) "y" . RETURN at 22 . . ADD at 31 . . . VAR PROXY parameter[0] (...) (mode = VAR) "x" . . . VAR PROXY parameter[1] (...) (mode = VAR) "y" FUNC
  48. 48. @ryzokuken@ryzokuken48 [generating bytecode for function: add] --- AST --- FUNC at 12 . KIND 0 . SUSPEND COUNT 0 . NAME "add" . PARAMS . . VAR (...) (mode = VAR) "x" . . VAR (...) (mode = VAR) "y" . RETURN at 22 . . ADD at 31 . . . VAR PROXY parameter[0] (...) (mode = VAR) "x" . . . VAR PROXY parameter[1] (...) (mode = VAR) "y" FUNC
  49. 49. @ryzokuken@ryzokuken49 [generating bytecode for function: add] --- AST --- FUNC at 12 . KIND 0 . SUSPEND COUNT 0 . NAME "add" . PARAMS . . VAR (...) (mode = VAR) "x" . . VAR (...) (mode = VAR) "y" . RETURN at 22 . . ADD at 31 . . . VAR PROXY parameter[0] (...) (mode = VAR) "x" . . . VAR PROXY parameter[1] (...) (mode = VAR) "y" FUNC NAME “add”
  50. 50. @ryzokuken@ryzokuken50 [generating bytecode for function: add] --- AST --- FUNC at 12 . KIND 0 . SUSPEND COUNT 0 . NAME "add" . PARAMS . . VAR (...) (mode = VAR) "x" . . VAR (...) (mode = VAR) "y" . RETURN at 22 . . ADD at 31 . . . VAR PROXY parameter[0] (...) (mode = VAR) "x" . . . VAR PROXY parameter[1] (...) (mode = VAR) "y" FUNC NAME “add” PARAMS
  51. 51. @ryzokuken@ryzokuken51 [generating bytecode for function: add] --- AST --- FUNC at 12 . KIND 0 . SUSPEND COUNT 0 . NAME "add" . PARAMS . . VAR (...) (mode = VAR) "x" . . VAR (...) (mode = VAR) "y" . RETURN at 22 . . ADD at 31 . . . VAR PROXY parameter[0] (...) (mode = VAR) "x" . . . VAR PROXY parameter[1] (...) (mode = VAR) "y" FUNC NAME “add” PARAMS VAR “x”
  52. 52. @ryzokuken@ryzokuken52 [generating bytecode for function: add] --- AST --- FUNC at 12 . KIND 0 . SUSPEND COUNT 0 . NAME "add" . PARAMS . . VAR (...) (mode = VAR) "x" . . VAR (...) (mode = VAR) "y" . RETURN at 22 . . ADD at 31 . . . VAR PROXY parameter[0] (...) (mode = VAR) "x" . . . VAR PROXY parameter[1] (...) (mode = VAR) "y" FUNC NAME “add” PARAMS VAR “x” VAR “y”
  53. 53. @ryzokuken@ryzokuken53 [generating bytecode for function: add] --- AST --- FUNC at 12 . KIND 0 . SUSPEND COUNT 0 . NAME "add" . PARAMS . . VAR (...) (mode = VAR) "x" . . VAR (...) (mode = VAR) "y" . RETURN at 22 . . ADD at 31 . . . VAR PROXY parameter[0] (...) (mode = VAR) "x" . . . VAR PROXY parameter[1] (...) (mode = VAR) "y" FUNC NAME “add” PARAMS RETURN VAR “x” VAR “y”
  54. 54. @ryzokuken@ryzokuken54 [generating bytecode for function: add] --- AST --- FUNC at 12 . KIND 0 . SUSPEND COUNT 0 . NAME "add" . PARAMS . . VAR (...) (mode = VAR) "x" . . VAR (...) (mode = VAR) "y" . RETURN at 22 . . ADD at 31 . . . VAR PROXY parameter[0] (...) (mode = VAR) "x" . . . VAR PROXY parameter[1] (...) (mode = VAR) "y" FUNC NAME “add” PARAMS RETURN VAR “x” VAR “y” ADD
  55. 55. @ryzokuken@ryzokuken55 [generating bytecode for function: add] --- AST --- FUNC at 12 . KIND 0 . SUSPEND COUNT 0 . NAME "add" . PARAMS . . VAR (...) (mode = VAR) "x" . . VAR (...) (mode = VAR) "y" . RETURN at 22 . . ADD at 31 . . . VAR PROXY parameter[0] (...) (mode = VAR) "x" . . . VAR PROXY parameter[1] (...) (mode = VAR) "y" FUNC NAME “add” PARAMS RETURN VAR “x” VAR “y” ADD PROXY “x”
  56. 56. @ryzokuken@ryzokuken56 [generating bytecode for function: add] --- AST --- FUNC at 12 . KIND 0 . SUSPEND COUNT 0 . NAME "add" . PARAMS . . VAR (...) (mode = VAR) "x" . . VAR (...) (mode = VAR) "y" . RETURN at 22 . . ADD at 31 . . . VAR PROXY parameter[0] (...) (mode = VAR) "x" . . . VAR PROXY parameter[1] (...) (mode = VAR) "y" FUNC NAME “add” PARAMS RETURN VAR “x” VAR “y” ADD PROXY “x” PROXY “y”
  57. 57. @ryzokuken@ryzokuken57 Scope Resolution FUNC NAME “add” PARAMS RETURN VAR “x” VAR “y” ADD PROXY “y”PROXY “x”
  58. 58. @ryzokuken@ryzokuken58 Let’s step through the bytecode. Hope you like Assembly. Once this is done, we can generate bytecode.
  59. 59. @ryzokuken@ryzokuken59 [generated bytecode for function: add] Parameter count 3 Frame size 0 12 E> 0x38d5f59df42 @ 0 : a5 StackCheck 22 S> 0x38d5f59df43 @ 1 : 25 02 Ldar a1 31 E> 0x38d5f59df45 @ 3 : 34 03 00 Add a0, [0] 35 S> 0x38d5f59df48 @ 6 : a9 Return Constant pool (size = 0) Handler Table (size = 0)
  60. 60. @ryzokuken@ryzokuken60 [generated bytecode for function: add] Parameter count 3 Frame size 0 12 E> 0x38d5f59df42 @ 0 : a5 StackCheck 22 S> 0x38d5f59df43 @ 1 : 25 02 Ldar a1 31 E> 0x38d5f59df45 @ 3 : 34 03 00 Add a0, [0] 35 S> 0x38d5f59df48 @ 6 : a9 Return Constant pool (size = 0) Handler Table (size = 0)
  61. 61. @ryzokuken@ryzokuken61 [generated bytecode for function: add] Parameter count 3 Frame size 0 12 E> 0x38d5f59df42 @ 0 : a5 StackCheck 22 S> 0x38d5f59df43 @ 1 : 25 02 Ldar a1 31 E> 0x38d5f59df45 @ 3 : 34 03 00 Add a0, [0] 35 S> 0x38d5f59df48 @ 6 : a9 Return Constant pool (size = 0) Handler Table (size = 0)
  62. 62. @ryzokuken@ryzokuken62 [generated bytecode for function: add] Parameter count 3 Frame size 0 12 E> 0x38d5f59df42 @ 0 : a5 StackCheck 22 S> 0x38d5f59df43 @ 1 : 25 02 Ldar a1 31 E> 0x38d5f59df45 @ 3 : 34 03 00 Add a0, [0] 35 S> 0x38d5f59df48 @ 6 : a9 Return Constant pool (size = 0) Handler Table (size = 0)
  63. 63. @ryzokuken@ryzokuken63 StackCheck Ldar a1 Add a0, [0] Return
  64. 64. @ryzokuken@ryzokuken64 StackCheck Ldar a1 Add a0, [0] Return
  65. 65. @ryzokuken@ryzokuken65 StackCheck Ldar a1 Add a0, [0] Return
  66. 66. @ryzokuken@ryzokuken66 StackCheck Ldar a1 Add a0, [0] Return
  67. 67. @ryzokuken@ryzokuken67 Two important things happen here. 1. Addition: It’s complicated. 2. Profiling: Feedback Vectors help.
  68. 68. @ryzokuken@ryzokuken68 StackCheck Ldar a1 Add a0, [0] Return
  69. 69. @ryzokuken@ryzokuken69 What about that Speculative Optimization thingie he was talking about earlier? Now that we finally have the baseline code running, let’s put that profiling data to good use. But wait...
  70. 70. @ryzokuken@ryzokuken70 Oh, also, remember that time when I said addition in JavaScript was complicated?
  71. 71. @ryzokuken@ryzokuken71
  72. 72. @ryzokuken@ryzokuken72 Let me break it down for you.
  73. 73. @ryzokuken@ryzokuken73 Number String Object
  74. 74. @ryzokuken@ryzokuken74
  75. 75. @ryzokuken@ryzokuken75 Remember Feedback Vectors? Let’s see how they really look to see how it all works. Awesome! But how do we make that assumption?
  76. 76. @ryzokuken@ryzokuken76 function add(x, y) { return x + y; } console.log(add(1, 2));
  77. 77. @ryzokuken@ryzokuken77 function add(x, y) { return x + y; } console.log(add(1, 2)); %DebugPrint(add);
  78. 78. @ryzokuken@ryzokuken78 ... - feedback vector: 0x18bc7711df89: [FeedbackVector] in OldSpace - map: 0x18bc38c00bc1 <Map> - length: 1 - shared function info: 0x18bc7711dc59 <SharedFunctionInfo add> - optimized code/marker: OptimizationMarker::kNone - invocation count: 1 - profiler ticks: 0 - slot #0 BinaryOp BinaryOp:SignedSmall { [0]: 1 } ...
  79. 79. @ryzokuken@ryzokuken79 function add(x, y) { return x + y; } console.log(add(1, 2)); %DebugPrint(add);
  80. 80. @ryzokuken@ryzokuken80 function add(x, y) { return x + y; } console.log(add(1, 2)); console.log(add(1.1, 2.2)); %DebugPrint(add);
  81. 81. @ryzokuken@ryzokuken81 ... - feedback vector: 0xcbd92d1dfe1: [FeedbackVector] in OldSpace - map: 0x0cbd4f880bc1 <Map> - length: 1 - shared function info: 0x0cbd92d1dc59 <SharedFunctionInfo add> - optimized code/marker: OptimizationMarker::kNone - invocation count: 2 - profiler ticks: 0 - slot #0 BinaryOp BinaryOp:Number { [0]: 7 } ...
  82. 82. @ryzokuken@ryzokuken82
  83. 83. @ryzokuken@ryzokuken83 Question: Is there a method to all this? Answer: Yes, it is called the Feedback Lattice.
  84. 84. @ryzokuken@ryzokuken84 None SignedSmall Number BigIntString NumberOrOddball Any
  85. 85. @ryzokuken@ryzokuken85 None SignedSmall Number BigIntString NumberOrOddball Any
  86. 86. @ryzokuken@ryzokuken86 None SignedSmall Number BigIntString NumberOrOddball Any
  87. 87. @ryzokuken@ryzokuken87 None SignedSmall Number BigIntString NumberOrOddball Any
  88. 88. @ryzokuken@ryzokuken88 None SignedSmall Number BigIntString NumberOrOddball Any
  89. 89. @ryzokuken@ryzokuken89 None SignedSmall Number BigIntString NumberOrOddball Any
  90. 90. @ryzokuken@ryzokuken90 None SignedSmall Number BigIntString NumberOrOddball Any
  91. 91. @ryzokuken@ryzokuken91 None SignedSmall Number BigIntString NumberOrOddball Any
  92. 92. @ryzokuken@ryzokuken92 This data in the Feedback Vectors is used to finally optimize your code once a function is hot. When is a function “hot”? Let’s see what actually happens by explicitly triggering optimization.
  93. 93. @ryzokuken@ryzokuken93 function add(x, y) { return x + y; } add(1, 2);
  94. 94. @ryzokuken@ryzokuken94
  95. 95. @ryzokuken@ryzokuken95 function add(x, y) { return x + y; } add(1, 2); // Warm up with SignedSmall feedback. %OptimizeFunctionOnNextCall(add); add(1, 2); // Optimize and run generated code.
  96. 96. @ryzokuken@ryzokuken96 Question: What did we just do?
  97. 97. @ryzokuken@ryzokuken97 Let’s see the optimized code generated by passing the -- print-opt-code flag to d8.
  98. 98. @ryzokuken@ryzokuken98 leaq rbx,[rip+0xfffffff9] movq rbx,[rcx-0x20] testb [rbx+0xf],0x1 jz 0x198104882dfb <+0x3b> movq r10,0x10efbfde0 (CompileLazyDeoptimizedCode) jmp r10 push rbp movq rbp,rsp push rsi push rdi cmpq rsp,[r13+0x11e8] (root (stack_limit)) jna 0x198104882e55 <+0x95> movq rdx,[rbp+0x18] testb rdx,0x1 jnz 0x198104882e7b <+0xbb> movq rcx,[rbp+0x10] testb rcx,0x1 jnz 0x198104882e87 <+0xc7> movq rdi,rcx shrq rdi, 32 movq r8,rdx shrq r8, 32 addl rdi,r8 jo 0x198104882e93 <+0xd3> shlq rdi, 32 movq rax,rdi movq rsp,rbp pop rbp ret 0x18
  99. 99. @ryzokuken@ryzokuken99 leaq rbx,[rip+0xfffffff9] movq rbx,[rcx-0x20] testb [rbx+0xf],0x1 jz 0x198104882dfb <+0x3b> movq r10,0x10efbfde0 (CompileLazyDeoptimizedCode) jmp r10 push rbp movq rbp,rsp push rsi push rdi cmpq rsp,[r13+0x11e8] (root (stack_limit)) jna 0x198104882e55 <+0x95> movq rdx,[rbp+0x18] testb rdx,0x1 jnz 0x198104882e7b <+0xbb> movq rcx,[rbp+0x10] testb rcx,0x1 jnz 0x198104882e87 <+0xc7> movq rdi,rcx shrq rdi, 32 movq r8,rdx shrq r8, 32 addl rdi,r8 jo 0x198104882e93 <+0xd3> shlq rdi, 32 movq rax,rdi movq rsp,rbp pop rbp ret 0x18 Prologue
  100. 100. @ryzokuken@ryzokuken100 leaq rbx,[rip+0xfffffff9] movq rbx,[rcx-0x20] testb [rbx+0xf],0x1 jz 0x198104882dfb <+0x3b> movq r10,0x10efbfde0 (CompileLazyDeoptimizedCode) jmp r10 push rbp movq rbp,rsp push rsi push rdi cmpq rsp,[r13+0x11e8] (root (stack_limit)) jna 0x198104882e55 <+0x95> movq rdx,[rbp+0x18] testb rdx,0x1 jnz 0x198104882e7b <+0xbb> movq rcx,[rbp+0x10] testb rcx,0x1 jnz 0x198104882e87 <+0xc7> movq rdi,rcx shrq rdi, 32 movq r8,rdx shrq r8, 32 addl rdi,r8 jo 0x198104882e93 <+0xd3> shlq rdi, 32 movq rax,rdi movq rsp,rbp pop rbp ret 0x18 Check x is Smi
  101. 101. @ryzokuken@ryzokuken101 leaq rbx,[rip+0xfffffff9] movq rbx,[rcx-0x20] testb [rbx+0xf],0x1 jz 0x198104882dfb <+0x3b> movq r10,0x10efbfde0 (CompileLazyDeoptimizedCode) jmp r10 push rbp movq rbp,rsp push rsi push rdi cmpq rsp,[r13+0x11e8] (root (stack_limit)) jna 0x198104882e55 <+0x95> movq rdx,[rbp+0x18] testb rdx,0x1 jnz 0x198104882e7b <+0xbb> movq rcx,[rbp+0x10] testb rcx,0x1 jnz 0x198104882e87 <+0xc7> movq rdi,rcx shrq rdi, 32 movq r8,rdx shrq r8, 32 addl rdi,r8 jo 0x198104882e93 <+0xd3> shlq rdi, 32 movq rax,rdi movq rsp,rbp pop rbp ret 0x18 Check y is Smi
  102. 102. @ryzokuken@ryzokuken102 leaq rbx,[rip+0xfffffff9] movq rbx,[rcx-0x20] testb [rbx+0xf],0x1 jz 0x198104882dfb <+0x3b> movq r10,0x10efbfde0 (CompileLazyDeoptimizedCode) jmp r10 push rbp movq rbp,rsp push rsi push rdi cmpq rsp,[r13+0x11e8] (root (stack_limit)) jna 0x198104882e55 <+0x95> movq rdx,[rbp+0x18] testb rdx,0x1 jnz 0x198104882e7b <+0xbb> movq rcx,[rbp+0x10] testb rcx,0x1 jnz 0x198104882e87 <+0xc7> movq rdi,rcx shrq rdi, 32 movq r8,rdx shrq r8, 32 addl rdi,r8 jo 0x198104882e93 <+0xd3> shlq rdi, 32 movq rax,rdi movq rsp,rbp pop rbp ret 0x18 Smi → Word32 (x)
  103. 103. @ryzokuken@ryzokuken103 leaq rbx,[rip+0xfffffff9] movq rbx,[rcx-0x20] testb [rbx+0xf],0x1 jz 0x198104882dfb <+0x3b> movq r10,0x10efbfde0 (CompileLazyDeoptimizedCode) jmp r10 push rbp movq rbp,rsp push rsi push rdi cmpq rsp,[r13+0x11e8] (root (stack_limit)) jna 0x198104882e55 <+0x95> movq rdx,[rbp+0x18] testb rdx,0x1 jnz 0x198104882e7b <+0xbb> movq rcx,[rbp+0x10] testb rcx,0x1 jnz 0x198104882e87 <+0xc7> movq rdi,rcx shrq rdi, 32 movq r8,rdx shrq r8, 32 addl rdi,r8 jo 0x198104882e93 <+0xd3> shlq rdi, 32 movq rax,rdi movq rsp,rbp pop rbp ret 0x18 Smi → Word32 (y)
  104. 104. @ryzokuken@ryzokuken104 leaq rbx,[rip+0xfffffff9] movq rbx,[rcx-0x20] testb [rbx+0xf],0x1 jz 0x198104882dfb <+0x3b> movq r10,0x10efbfde0 (CompileLazyDeoptimizedCode) jmp r10 push rbp movq rbp,rsp push rsi push rdi cmpq rsp,[r13+0x11e8] (root (stack_limit)) jna 0x198104882e55 <+0x95> movq rdx,[rbp+0x18] testb rdx,0x1 jnz 0x198104882e7b <+0xbb> movq rcx,[rbp+0x10] testb rcx,0x1 jnz 0x198104882e87 <+0xc7> movq rdi,rcx shrq rdi, 32 movq r8,rdx shrq r8, 32 addl rdi,r8 jo 0x198104882e93 <+0xd3> shlq rdi, 32 movq rax,rdi movq rsp,rbp pop rbp ret 0x18 Add x and y Overflow Check
  105. 105. @ryzokuken@ryzokuken105 leaq rbx,[rip+0xfffffff9] movq rbx,[rcx-0x20] testb [rbx+0xf],0x1 jz 0x198104882dfb <+0x3b> movq r10,0x10efbfde0 (CompileLazyDeoptimizedCode) jmp r10 push rbp movq rbp,rsp push rsi push rdi cmpq rsp,[r13+0x11e8] (root (stack_limit)) jna 0x198104882e55 <+0x95> movq rdx,[rbp+0x18] testb rdx,0x1 jnz 0x198104882e7b <+0xbb> movq rcx,[rbp+0x10] testb rcx,0x1 jnz 0x198104882e87 <+0xc7> movq rdi,rcx shrq rdi, 32 movq r8,rdx shrq r8, 32 addl rdi,r8 jo 0x198104882e93 <+0xd3> shlq rdi, 32 movq rax,rdi movq rsp,rbp pop rbp ret 0x18 Result to Smi
  106. 106. @ryzokuken@ryzokuken106 leaq rbx,[rip+0xfffffff9] movq rbx,[rcx-0x20] testb [rbx+0xf],0x1 jz 0x198104882dfb <+0x3b> movq r10,0x10efbfde0 (CompileLazyDeoptimizedCode) jmp r10 push rbp movq rbp,rsp push rsi push rdi cmpq rsp,[r13+0x11e8] (root (stack_limit)) jna 0x198104882e55 <+0x95> movq rdx,[rbp+0x18] testb rdx,0x1 jnz 0x198104882e7b <+0xbb> movq rcx,[rbp+0x10] testb rcx,0x1 jnz 0x198104882e87 <+0xc7> movq rdi,rcx shrq rdi, 32 movq r8,rdx shrq r8, 32 addl rdi,r8 jo 0x198104882e93 <+0xd3> shlq rdi, 32 movq rax,rdi movq rsp,rbp pop rbp ret 0x18 Epilogue
  107. 107. @ryzokuken@ryzokuken107 Now, let’s try something fun.
  108. 108. @ryzokuken@ryzokuken108 function add(x, y) { return x + y; } add(1, 2); // Warm up with SignedSmall feedback. %OptimizeFunctionOnNextCall(add); add(1, 2); // Optimize and run generated code.
  109. 109. @ryzokuken@ryzokuken109 function add(x, y) { return x + y; } add(1, 2); // Warm up with SignedSmall feedback. %OptimizeFunctionOnNextCall(add); add(1, 2); // Optimize and run generated code. add(1.1, 2.2) // DEOPTIMIZE!
  110. 110. @ryzokuken@ryzokuken110
  111. 111. @ryzokuken@ryzokuken111 Note: I’m obviously kidding. Deoptimization is no laughing matter.
  112. 112. @ryzokuken@ryzokuken112 Let’s see how the code is actually deoptimized by passing the --trace-deopt flag to d8.
  113. 113. @ryzokuken@ryzokuken113 [deoptimizing (DEOPT eager): begin 0x08d97929dbc1 <JSFunction add (sfi = 0x8d97929d999)> (opt #0) @0, FP to SP delta: 24, caller sp: 0x7ffee7bee248] ;;; deoptimize at <add.js:2:12>, not a Smi reading input frame add => bytecode_offset=0, args=3, height=1, retval=0(#0); inputs: 0: 0x08d97929dbc1 ; [fp - 16] 0x08d97929dbc1 <JSFunction add (sfi = 0x8d97929d999)> 1: 0x08d9c6b81521 ; [fp + 32] 0x08d9c6b81521 <JSGlobal Object> 2: 0x08d97929da31 ; rdx 0x08d97929da31 <HeapNumber 1.1> 3: 0x08d97929da41 ; [fp + 16] 0x08d97929da41 <HeapNumber 2.2> 4: 0x08d979281749 ; [fp - 24] 0x08d979281749 <NativeContext[247]> 5: 0x08d92b080e19 ; (literal 2) 0x08d92b080e19 <Odd Oddball: optimized_out> translating interpreted frame add => bytecode_offset=0, height=8 0x7ffee7bee240: [top + 72] <- 0x08d9c6b81521 <JSGlobal Object> ; stack parameter (input #1) 0x7ffee7bee238: [top + 64] <- 0x08d97929da31 <HeapNumber 1.1> ; stack parameter (input #2) 0x7ffee7bee230: [top + 56] <- 0x08d97929da41 <HeapNumber 2.2> ; stack parameter (input #3) ------------------------- 0x7ffee7bee228: [top + 48] <- 0x00010d2881e8 ; caller's pc 0x7ffee7bee220: [top + 40] <- 0x7ffee7bee290 ; caller's fp 0x7ffee7bee218: [top + 32] <- 0x08d979281749 <NativeContext[247]> ; context (input #4) 0x7ffee7bee210: [top + 24] <- 0x08d97929dbc1 <JSFunction add (sfi = 0x8d97929d999)> ; function (input #0) 0x7ffee7bee208: [top + 16] <- 0x08d97929dca1 <BytecodeArray[7]> ; bytecode array 0x7ffee7bee200: [top + 8] <- 0x003900000000 <Smi 57> ; bytecode offset ------------------------- 0x7ffee7bee1f8: [top + 0] <- 0x08d92b080e19 <Odd Oddball: optimized_out> ; accumulator (input #5) [deoptimizing (eager): end 0x08d97929dbc1 <JSFunction add (sfi = 0x8d97929d999)> @0 => node=0, pc=0x00010d2886c0, caller sp=0x7ffee7bee248, took 1.163 ms]
  114. 114. @ryzokuken@ryzokuken Don’t worry, I got you.114
  115. 115. @ryzokuken@ryzokuken115 [deoptimizing (DEOPT eager): begin 0x08d97929dbc1 <JSFunction add (sfi = 0x8d97929d999)> (opt #0) @0, FP to SP delta: 24, caller sp: 0x7ffee7bee248] ;;; deoptimize at <add.js:2:12>, not a Smi reading input frame add => bytecode_offset=0, args=3, height=1, retval=0(#0); inputs: 0: 0x08d97929dbc1 ; [fp - 16] 0x08d97929dbc1 <JSFunction add (sfi = 0x8d97929d999)> 1: 0x08d9c6b81521 ; [fp + 32] 0x08d9c6b81521 <JSGlobal Object> 2: 0x08d97929da31 ; rdx 0x08d97929da31 <HeapNumber 1.1> 3: 0x08d97929da41 ; [fp + 16] 0x08d97929da41 <HeapNumber 2.2> 4: 0x08d979281749 ; [fp - 24] 0x08d979281749 <NativeContext[247]> 5: 0x08d92b080e19 ; (literal 2) 0x08d92b080e19 <Odd Oddball: optimized_out> translating interpreted frame add => bytecode_offset=0, height=8 0x7ffee7bee240: [top + 72] <- 0x08d9c6b81521 <JSGlobal Object> ; stack parameter (input #1) 0x7ffee7bee238: [top + 64] <- 0x08d97929da31 <HeapNumber 1.1> ; stack parameter (input #2) 0x7ffee7bee230: [top + 56] <- 0x08d97929da41 <HeapNumber 2.2> ; stack parameter (input #3) ------------------------- 0x7ffee7bee228: [top + 48] <- 0x00010d2881e8 ; caller's pc 0x7ffee7bee220: [top + 40] <- 0x7ffee7bee290 ; caller's fp 0x7ffee7bee218: [top + 32] <- 0x08d979281749 <NativeContext[247]> ; context (input #4) 0x7ffee7bee210: [top + 24] <- 0x08d97929dbc1 <JSFunction add (sfi = 0x8d97929d999)> ; function (input #0) 0x7ffee7bee208: [top + 16] <- 0x08d97929dca1 <BytecodeArray[7]> ; bytecode array 0x7ffee7bee200: [top + 8] <- 0x003900000000 <Smi 57> ; bytecode offset ------------------------- 0x7ffee7bee1f8: [top + 0] <- 0x08d92b080e19 <Odd Oddball: optimized_out> ; accumulator (input #5) [deoptimizing (eager): end 0x08d97929dbc1 <JSFunction add (sfi = 0x8d97929d999)> @0 => node=0, pc=0x00010d2886c0, caller sp=0x7ffee7bee248, took 1.163 ms]
  116. 116. @ryzokuken@ryzokuken116 [deoptimizing (DEOPT eager): begin 0x08d97929dbc1 <JSFunction add (sfi = 0x8d97929d999)> (opt #0) @0, FP to SP delta: 24, caller sp: 0x7ffee7bee248] ;;; deoptimize at <add.js:2:12>, not a Smi reading input frame add => bytecode_offset=0, args=3, height=1, retval=0(#0); inputs: 0: 0x08d97929dbc1 ; [fp - 16] 0x08d97929dbc1 <JSFunction add (sfi = 0x8d97929d999)> 1: 0x08d9c6b81521 ; [fp + 32] 0x08d9c6b81521 <JSGlobal Object> 2: 0x08d97929da31 ; rdx 0x08d97929da31 <HeapNumber 1.1> 3: 0x08d97929da41 ; [fp + 16] 0x08d97929da41 <HeapNumber 2.2> 4: 0x08d979281749 ; [fp - 24] 0x08d979281749 <NativeContext[247]> 5: 0x08d92b080e19 ; (literal 2) 0x08d92b080e19 <Odd Oddball: optimized_out> translating interpreted frame add => bytecode_offset=0, height=8 0x7ffee7bee240: [top + 72] <- 0x08d9c6b81521 <JSGlobal Object> ; stack parameter (input #1) 0x7ffee7bee238: [top + 64] <- 0x08d97929da31 <HeapNumber 1.1> ; stack parameter (input #2) 0x7ffee7bee230: [top + 56] <- 0x08d97929da41 <HeapNumber 2.2> ; stack parameter (input #3) ------------------------- 0x7ffee7bee228: [top + 48] <- 0x00010d2881e8 ; caller's pc 0x7ffee7bee220: [top + 40] <- 0x7ffee7bee290 ; caller's fp 0x7ffee7bee218: [top + 32] <- 0x08d979281749 <NativeContext[247]> ; context (input #4) 0x7ffee7bee210: [top + 24] <- 0x08d97929dbc1 <JSFunction add (sfi = 0x8d97929d999)> ; function (input #0) 0x7ffee7bee208: [top + 16] <- 0x08d97929dca1 <BytecodeArray[7]> ; bytecode array 0x7ffee7bee200: [top + 8] <- 0x003900000000 <Smi 57> ; bytecode offset ------------------------- 0x7ffee7bee1f8: [top + 0] <- 0x08d92b080e19 <Odd Oddball: optimized_out> ; accumulator (input #5) [deoptimizing (eager): end 0x08d97929dbc1 <JSFunction add (sfi = 0x8d97929d999)> @0 => node=0, pc=0x00010d2886c0, caller sp=0x7ffee7bee248, took 1.163 ms]
  117. 117. @ryzokuken@ryzokuken117 [deoptimizing (DEOPT eager): begin 0x08d97929dbc1 <JSFunction add (sfi = 0x8d97929d999)> (opt #0) @0, FP to SP delta: 24, caller sp: 0x7ffee7bee248] ;;; deoptimize at <add.js:2:12>, not a Smi reading input frame add => bytecode_offset=0, args=3, height=1, retval=0(#0); inputs: 0: 0x08d97929dbc1 ; [fp - 16] 0x08d97929dbc1 <JSFunction add (sfi = 0x8d97929d999)> 1: 0x08d9c6b81521 ; [fp + 32] 0x08d9c6b81521 <JSGlobal Object> 2: 0x08d97929da31 ; rdx 0x08d97929da31 <HeapNumber 1.1> 3: 0x08d97929da41 ; [fp + 16] 0x08d97929da41 <HeapNumber 2.2> 4: 0x08d979281749 ; [fp - 24] 0x08d979281749 <NativeContext[247]> 5: 0x08d92b080e19 ; (literal 2) 0x08d92b080e19 <Odd Oddball: optimized_out> translating interpreted frame add => bytecode_offset=0, height=8 0x7ffee7bee240: [top + 72] <- 0x08d9c6b81521 <JSGlobal Object> ; stack parameter (input #1) 0x7ffee7bee238: [top + 64] <- 0x08d97929da31 <HeapNumber 1.1> ; stack parameter (input #2) 0x7ffee7bee230: [top + 56] <- 0x08d97929da41 <HeapNumber 2.2> ; stack parameter (input #3) ------------------------- 0x7ffee7bee228: [top + 48] <- 0x00010d2881e8 ; caller's pc 0x7ffee7bee220: [top + 40] <- 0x7ffee7bee290 ; caller's fp 0x7ffee7bee218: [top + 32] <- 0x08d979281749 <NativeContext[247]> ; context (input #4) 0x7ffee7bee210: [top + 24] <- 0x08d97929dbc1 <JSFunction add (sfi = 0x8d97929d999)> ; function (input #0) 0x7ffee7bee208: [top + 16] <- 0x08d97929dca1 <BytecodeArray[7]> ; bytecode array 0x7ffee7bee200: [top + 8] <- 0x003900000000 <Smi 57> ; bytecode offset ------------------------- 0x7ffee7bee1f8: [top + 0] <- 0x08d92b080e19 <Odd Oddball: optimized_out> ; accumulator (input #5) [deoptimizing (eager): end 0x08d97929dbc1 <JSFunction add (sfi = 0x8d97929d999)> @0 => node=0, pc=0x00010d2886c0, caller sp=0x7ffee7bee248, took 1.163 ms]
  118. 118. @ryzokuken@ryzokuken118 Pro Tip: If you don’t want your code to be slow, try to stick to certain types. It makes things easier.
  119. 119. @ryzokuken Special Thanks ● Benedikt Meurer (@bmeurer) ● Yang Guo (@hashseed) ● Sathya Gunasekaran (@_gsathya) ● Jakob Gruber (@schuay) ● Sigurd Schneider (@sigurdschn) ● ...and everyone else from the V8 team. ● The organizers. 119
  120. 120. @ryzokuken@ryzokuken Paldies! 120

×