# Source to Binary - journey of V8 javascript engine

V8 javascript engineについて
パーサー、AST、Ignition/TurboFan、最適化周り等

## Taketoshi Aono(青野健利 a.k.a brn)

November 25, 2017

## Transcript

1. Name
@brn (ꫬꅿ⨳ⵃ)
Occupation
ؿٗٝزؒٝسؒٝآص،٥ط؎ذ؍ـؒٝآص،
Company
Cyberagent ،سذؙأةآؔ AI Messenger
Blog
http://abcdef.gets.b6n.ch/
GitHub
https://github.com/brn

2. Agenda
•  What is V8?
•  Execution ﬂow of V8
•  Parsing
•  Abstract Syntax Tree
•  Ignition – BytecodeInterpreter
•  CodeStubAssembler
•  Builtins / Runtime
•  Optimization / Hidden Class / Inline Caching
•  TurboFan / Deoptimization

3. What is V8?

4. Execution Flow

5. Source AST Bytecode Graph Assembly
ﬁrst time hot code

6. Parsing

7. Basic parsing
V8כا٦أ؝٦س׾ػ٦أ׃גASTח㢌䳔ׅ׷
ASTהכAbstractSyntaxTreeך殛獥
䬄韋圓俑加הㄎל׸׷
Parsing

8. if (x) {
x = 100
}

9. IF
CONDITION
THEN
BLOCK
EXPRESSION
STATEMENT
ASSIGN
VAR PROXY (X) LITERAL (100)
if
(x)

{

x = 100

10. Problems

11. Parsing all functions - Slow
ׅץגך؝٦س׾剑ⴱחػ٦أׅ׷ךכ֮ת׶״׹׃ֻזְ
׮׃ػ٦أ׃׋؝٦سָ㹋遤ׁ׸זֽ׸ל䠐㄂ָזְ
Parsing

12. Split parsing phase
ػ٦أ׾鹼䒀׃ג遤ֲ׋׭חծػ٦أ׾✳媮ꥡחⴓֽ׷
Parsing

13. PreParsing ✲⵸חׅץגךꟼ侧ךٖ؎،ؐز׾
ػ٦أ׃גֶֻ
Parsing

14. function x(a, b) {
return a + b;
}
FUNCTION(X)
parameter-count: 2
start-position: 1
end-position: 34
use-super-property: false

15. // when x is called
x()
FUNCTION
NAME (x)
RETURN
LITERAL(1)

16. Lazy Parsing
V8כ㹋ꥷח״ן׌ׁ׸׷תדػ٦أ׾鹼䒀ׅ׷
ꟼ侧כㄎן⳿ׁ׸גⴱ׭ג؝ٝػ؎ׁٕ׸׷
Parsing

ALt6W01nIxutFVFmXMOyd_6ou_6qqP6S0Prmb1iDs/present?
slide=id.p
Parsing

18. Abstract
Syntax
Tree

19. AST Rewriting
Parserח״׏ג欰䧭ׁ׸׋AST׾㢌䕎ׅ׷
ְֻאַ稱➜
AbstractSyntaxTree

20. Subsclass constructor return
竰䪫׃׋ؙٓأך؝ٝأزؙٓة׾㢌䕎ׅ׷
崢欰ؙٓأך؝ٝأزؙٓةד䒭׾return׃גְ׷儗כծ
3갪怴皾㶨ח㢌䳔׃גծ
䒭ך穠卓ָundeﬁned׌׏׋㜥さחכthis׾䨱ׅկ
AbstractSyntaxTree

21. constructor() {!
super();!
return expr!
}!
!
constructor() {!
super();!
var tmp;!
return (temp = expr) === undefined?!
this: temp;!
}!

22. for (let/const/var in/of e)
for-in/ofךⴱ劍⻉דconst/let׾⢪ֲ׋׭חծⰋ⡤׾ـٗحؙד㔲
׫㢌侧׾㹑鎉ׅ׷կ
AbstractSyntaxTree

23. for (const key of e) {!
...!
}!

24. {!
var temp;!
for (temp of e) {!
const x = temp;!
...!
}!
let x!
}!

doהfor-ofח縧ֹ䳔ִגⳢ椚
AbstractSyntaxTree

26. const x = [1,2,3];!
const y = [...x];!

27. do {!
\$R = [];!
for (\$i of x)!
%AppendElement(\$R, \$i);!
\$R!
}!

28. Ecmascript? – Binary AST
➙תד鋅׋״ֲחASTך؟؎ؤכ穠圓㣐ְֹךדծ
׉׸׾㖇簭ׅ׷䲿周
Parsing

29. Ignition

30. Bytecode Interpreter
V8כ欰䧭׃׋AST׾1~4byteךBytecodeח㢌䳔׃גַ׵㹋遤ׅ
׷
Ignition

31. How does it work?
♧אך،ُؗيٖ٦ة٦׾⪒ִٖآأةك٦أד⹛⡲ׅ׷؎ٝ
ة٦فٔة
Ignition

32. Pseudo javascript code
Javascriptד圓鸡׾垷⦺ׅ׷הֿך״ֲחז׷
Ignition

33. const Bytecodes = [0,1,2,3,4,5];!
let index = 0;!
function dispatch(next) {BytecodeHandlers[next]
();}!
const BytecodeHandlers = [!
() => {...; dispatch(Bytecodes[index++])},!
() => {...; dispatch(Bytecodes[index++])},!
() => {...; dispatch(Bytecodes[index++])},!
() => {...; dispatch(Bytecodes[index++])},!
() => {...; dispatch(Bytecodes[index++])},!
() => {...; dispatch(Bytecodes[index++])},!
]!
dispatch(Bytecodes[index++]);!

34. How to create bytecode?
BytecodeכASTַ׵AstVisitor׾ⵃ欽׃ג欰䧭ׁ׸׷
AstVisitorכVistorػة٦ٝ׾ⵃ欽׃׋ؙٓأדծ
AST׾帾ׁ⮚⯓䱱稊׃זָ׵㼎䘔ׅ׷؝٦ٕغحؙꟼ侧׾ㄎן⳿
ׅ
Ignition

35. BytecodeArray
欰䧭ׁ׸׋BytecodeכBytecodeArrayח呓秛ׁ׸׷
BytecodeArrayכꟼ侧⽃⡘ד㶷㖈ׅ׷
Ignition

36. Dispatch Table
Stub(Machine Code)
BytecodeArray
Dispatch Tableから対応するHandlerを取り出して実行
0 1 3 4 5 6 7 8
5 6 1

37. InterpreterEntryTrampoline
剑穄涸ח欰䧭ׁ׸׋BytecodeכInterpreterEntrynTrampolineה
ㄎל׸׷Builtin؝٦سַ׵㹋遤ׁ׸׷
InterpreterEntryTrampolineכAssemblyח؝ٝػ؎ׁٕ׸ծ
鸐䌢ךCךꟼ侧הㄎן⳿ׁ׸׷
Ignition

38. InterpreterEntryTrampoline(Assembly)
Script::Run
Call as C function
Ignition DispatchTable
Dispatch First bytecode

39. Ignition Handler
⯓玎亻⡂؝٦سד爙׃׋BytecodeHandlersכV8דכ
Ignition Handlerהㄎל׸גְ׷
Ignition HandlerכCodeStubAssemblerהְֲDSLד鎸鶢ׁ׸ג
ְ׷
Iginition

40. CodeStub
Assember

41. What is CodeStubAssmber?
CodeStubAssembler(CSA)כ؝٦س欰䧭׾ؚٓؿ欰䧭ח䬄韋⻉׃
׋V8ⰻ鿇ךDSL
㹋遤✮㹀Node׾穈׫甧ג׷׌ֽדծCodeGeneratorח״׏גぐ
،٦ؗذؙثٍぢֽך؝٦سָ欰䧭ׁ׸׷׋׭ծ،إٝـٔ鎉铂
׾ְ׍ְ׍倜׋ח剅ֻ䗳銲ָזְ
CodeStubAssembler

42. IGNITION_HANDLER(JumpIfToBooleanFalse, InterpreterAssembler) {!
Node* value = GetAccumulator();!
// Accumulatorの値を取得!
Node* relative_jump = BytecodeOperandUImmWord(0);!
// 引数のoperandを取得!
Label if_true(this), if_false(this);!
BranchIfToBooleanIsTrue(value, &if_true, &if_false);!
// valueがtrueならif_true、falseならif_false!
Bind(&if_true);!
Dispatch();!
Bind(&if_false);!
// operandのbytecodeまでjump!
Jump(relative_jump);!
}!

43. Graph based DSL
ֿךCodeStubAssemblerךֶַ־ד㹋ꥷך،٦ؗذؙثٍぢֽ
ך،إٝـٓ׾擾濼׃גְזֻג׮֮׵׋ח؝٦س׾鷄⸇ׅ׷ֿ
הָ㺁僒חז׶ծ
ת׋〳铣䚍׮ꬊ䌢ח넝ֻז׏גְ׷
CodeStubAssembler

44. Dispatch Table
00 01 02 04 08 0f 10 10
Node
Node
Node
Operator
Operator
IGNITION_HANDLER
Stub (Mahine Code Fragment)
グラフからコードを生成
生成したコードを、
DispatchTableの対応する
バイトコードのインデックスへ
登録
Assemble

45. Assembler
㹋ꥷחぐ،٦ؗذؙثٍぢֽך؝٦س׾⳿⸂ׅ׷
X64ぢֽךjmpص٦ٌصحؙ׾׍׳׏ה׌ֽ鋖ְג׫״ֲ
CodeStubAssembler

46. void Assembler::jmp(!
Handle target,!
RelocInfo::Mode rmode!
) {!
EnsureSpace ensure_space(this);!
// 1110 1001 #32-bit disp.!
// ここでメモリ上にアセンブラを書き出す!
emit(0xE9);!
emit_code_target(target, rmode);!
}!

47. Where to use
BuiltinsכAssemblerؙٓأ׾ⵃ欽׃גぐ،٦ؗذؙثٍ嫣ך
Stubָ鎸鶢ׁ׸גְ׷
♧鿇CSA׾⢪ֲ皘䨽׮֮׷(*-gen.cc)
Ignition HandlerכקרⰋגָCSAד鎸鶢ׁ׸גְ׷
CodeStubAssembler

48. Builtins
&
Runtime

49. Builtins
BuiltinsכV8ך饯⹛儗ח؝ٝػ؎ׁٕ׸׷،إٝـٓך؝٦س晙
ꟼ侧ך״ֲחCallBuiltin穗歋דㄎן⳿ׁ׸׷
Stubה׮ㄎל׸׷
㹋遤儗ך剑黝⻉כ遤׻׸זְ
Builtins & Runtime

50. Runtime
RuntimeכBuiltinsװ׉ך➭ך،إٝـٓ؝٦سַ׵ㄎן⳿ֿׅ
הָדֹ׷C++ך؝٦س
Javascriptך⚅歲ַ׵C++ך⚅歲׾אזּ؝٦س晙
ずֻׄ㹋遤儗ך剑黝⻉כ遤׻׸זְ
Builtins & Runtime

51. Hidden
Class

52. What is Hidden Class?
Javascriptחכ㘗ָזְךדؔـآؙؑز׾鋉㹀ׅ׷׮ךָ搀ְկ
׉ך׋׭ծV8כؔـآؙؑزך圓鸡荈⡤׾㘗ך״ֲח䪔׏גְ׷կ
ֿ׸׾Hidden Classהㄎע
Hidden Class

53. •  Hidden Class
const point1 = {x: 0, y: 0};!
const point2 = {x: 0, y: 0};!
Map
FixedArray [
{x: {offset: 0}},
{y: {offset: 1}}
]

54. Map
׋הִJavascript♳דכⴽךؔـآؙؑزד֮׏ג׮ծ
ずׄ圓鸡׾䭯׏גְ׸לずׄHidden Class׾Ⱏ剣ׅ׷
׉׃גֿךؔـآؙؑزך酅ח֮׷圓鸡׾Mapהㄎע
Hidden Class

55. const pointA = {x: 0, y: 0};!
const pointB = {x: 0, y: 0};!
// pointA.Map === pointB.Map;!
!
const pointC = {y: 0, x: 0};!
// pointA.Map !== pointC.Map!
!
const point3D = {x: 0, y: 0, z: 0};!
// point3D.Map !== pointA.Map!

56. class PointA {!
constructor() {!
this.x = 0;!
this.y = 0;!
}!
}!
const pointAInstance = new PointA();!
!
class PointB {!
constructor() {!
this.y = 0;!
this.x = 0;!
}!
}!
const pointBInstance = new PointB();!
// PointAInstance.Map !== PointBInstance.Map!

57. Layout
Mapؔـآؙؑزכַז׶⿑㺘חفٗػذ؍ךoffset׾ثؑحؙ
ׅ׷׋׭ծٔذٕٓךⴱ劍⻉갫٥فٗػذ؍ךⴱ劍⻉갫٥فٗػ
ذ؍ך侧ָ麩ֲהⴽךMapָⶴ׶䔲ג׵׸׷
Hidden Class

58. Map Transition
׃ַ׃فٗػذ؍ך㟓幾ָ걼籕ח饯ֿ׷Javascriptדծ嫣㔐Map
׾欰䧭ׅ׷ה؝أزָ搀鋔דֹזְךדכ
V8כفٗػذ؍ך㟓幾ָ֮׏׋㜥さחכMap׾Ⱏ剣׃זָ׵ծ
㟓ִ׋鿇ⴓך׫ך倜׃ְMap׾欰䧭ׅ׷
ֿ׸׾Map Transitionהㄎע
Hidden Class

59. function Point(x, y) {
this.x = x;
this.y = y;
}
Map
FixedArray [
{x: {oﬀset: 0}},
{y: {oﬀset: 1}},
]
var x = new Point(1, 1);
x.z = 1;
Map
FixedArray [
{z: {offset: 2}}
]
transition

60. What's Happening?
Hidden Classָ֮׷ה⡦ָ㴍׃ְַהְֲהծ
ؔـآؙؑزךفٗػذ؍،ؙإأװ㘗ךثؑحؙ׾״׶넝鸞חծ
״׶㸜Ⰻח遤ִ׷״ֲחז׷
Hidden Class

61. Inline Caching

62. What is Inline Caching
فٗػذ؍،ؙإأך넝鸞⻉ך׋׭ח麓⿠ך،ؙإأ׾ٍؗح
ءُ׃גֶֻ
Inline Caching

63. function x(obj) {!
return obj.x + obj.y;!
}!
!
x({x: 0, y: 0});!
x({x: 1, y: 1});!
x({x: 2, y: 2});!

64. Search Property
ؔـآؙؑزַ׵فٗػذ؍׾䱱ׅ׋׭חכծ
HashMapװFixedArrayַ׵فٗػذ؍׾ٗ٦سׅ׷
׃ַ׃׉׸׾嫣㔐遤ֲךכꬊ䌢ח鹼ְ
Inline Caching

65. Reduce Property Access
ֿך⢽דכxהyפך،ؙإأָずׄMap׾䭯אؔـآؙؑزח㼎
׃ג⡦䏝׮㹋遤ׁ׸גְ׷
ׅדחobjכ{x, y}ךMapה׻ַ׏גְ׷ךד֮׸לծ
䔲搫ًٌٖٔ؎،ؐز׮׻ַ׏גְ׷ךדծ湫䱸offset׾䭷㹀׃
ג،ؙإأ׃׋קֲָ傍ְ
Inline Caching

66. Cache
זךדծ暴㹀ךMapך،ؙإأ׾鎸䥉׃גֶֻ
֮׷فٗػذ؍פ،ؙإأ׃׋㜥さծ׉ךMapؔـآؙؑز׾鎸
䥉ׅ׷ֿהד2㔐湡⟃꣬ךفٗػذ؍،ؙإأָ넝鸞⻉ׁ׸׷
Inline Caching

67. x({x: 0, y: 0});!
// uninitialized!
x({x: 1, y: 1});!
// stub_call!
x({x: 2, y: 2});!
// found ic!
x({x: 1, y: 1, z: 1})!
x({x: 1, y: 1, foo() {}});!

68. Cache Miss
׋׌׃ծMapָ㢌⻉׃׋㜥さחכ䔲搫CacheךMissؼحزָ饯ֹ
׷ךדծת׋فٗػذ؍׾ٗ٦س׃ג倜׋ח鎸䥉׃湫ׅ
׋׌׃ׅץג׾鎸ꐮׅ׷ךכ♶〳腉זךדծ4אתדMapؔـ
آؙؑز׾鎸ꐮׅ׷
Inline Cache

69. Cahce State
ٍؗحءُך朐䡾כ⟃♴ך״ֲח鼂獳ׅ׷
PreMonomorphic
Monomorphic
Polymorphic
Megamorphic
Inline Caching

70. Pre Monomorphic
؝٦س♳ך鿪さד劢ⴱ劍ַוֲַⴻ㹀ׅ׷׋׭ח㶷㖈ׅ׷ךדծ
֮ת׶䠐㄂כזְ
Inline Caching

71. Monomorphic
⽃♧ךMapפך،ؙإأ׃ַ㶷㖈׃זְ朐䡾
椚䟝涸ז朐䡾ה鎉ִ׷
Inline Caching

72. Polymorphic
MapָFixedArrayח呓秛ׁ׸גֶ׶醱侧ךMapַ׵嗚稊׃ג
فٗػذ؍،ؙإأ׾㹋遤ׅ׷
ٍؗحءُ荈⡤כׁ׸גְ׷ךדת׌넝鸞
Inline Caching

73. Megamorphic
֮ת׶חMissָ㢳ְךדծMapך鎸ꐮ׾⨡姺׃׋朐䡾
איחStubַ׵GetProperty׾ㄎן⳿׃גفٗػذ؍׾《䖤ׅ׷
剑׮鹼ְ朐䡾
Inline Caching

74. Optimization

75. Hot or Small
䌢ח؝٦س׾剑黝⻉ׅ׷ךכꬊ䌢ח搀꼽
⟃♴ך勴⟝ח䔲גכת׷؝٦س׾剑黝⻉ׅ׷
•  (ꟼ侧ךغ؎ز؝٦سꞿ/ 1200) + 2ך㔐侧ꟼ侧ָㄎן⳿ׁ׸
גְ׷
•  ꟼ侧ָ㼭ְׁ(غ؎ز؝٦سךꞿָׁ90劢弫)
Optimization

76. Optimization Budget
غ؎ز؝٦س㹋遤⚥חぐꟼ侧חכ剑黝⻉✮皾ָⶴ׶䮶׵׸גֶ׶ծ
׉ך⦼ָ0׾ⴖ׷ה؝٦س剑黝⻉⦪酡הז׷
Optimization

77. For loop
ٕ٦فדכJumpLoopהְֲغ؎ز؝٦سָ⳿⸂ׁ׸׷
ֿךJumpLoopך⚥ד䨱׶⯓ך،سٖأ⦼ךoffset׾ꅾ׫ח׃גծ
⯓玎ך✮皾ַ׵⦼׾䒷ֹծ׉׸ָ0׾ⶴ׏׋׵ٕ٦فⰻך剑黝⻉
ָ涪欰ׅ׷
Optimization

78. function id(v) {return v;}!
function x(v) {!
for (var i = 0; i < 10000; i++) {!
id(v + i);!
}!
}!
x(1);!

79. 0x1bb9e5e2935e LdaSmi.Wide [1000]
0x1bb9e5e2937e JumpLoop [32], [0] (0x1bb9e5e2935e @ 4)
Bytecode length = 100
if (budget –= 100 < 0) {
OptimizeAndOSR();
}

80. OSR - OnStackReplacement
؝ٝػ؎ׁٕ׸גغ؎ز؝٦سַ׵堣唒铂ח㢌䳔ׁ׸׋؝٦سכծ
ٕ٦فך鷿⚥ד굲ן⯓ָ剅ֹ䳔ִ׵׸ג倜׋ז堣唒铂ך؝٦سָ
㹋遤ׁ׸׷
Optimization

81. For function
ꟼ侧ך㜥さכReturnغ؎ز؝٦سָ䗳׆欰䧭ׁ׸׷
׉ֿדInterruptָ遤׻׸ג✮皾ךثؑحָؙ涪欰ׅ׷
Optimization

82. function x() {!
const x = 1 + 1;!
}!
x();!

83. 0x3d22953a917a StackCheck
0x3d22953a9180 Return
Bytecode length 30
if (budget -= 30 < 0) {
OptimizeConcurrent();
}

84. Concurrent Compilation
ꟼ侧׾剑黝⻉ׅ׷㜥さכծ⚛⴨؝ٝػ؎ָٕꬊず劍ח遤׻׸׷
׉ך׋׭如㔐⟃꣬ךꟼ侧ㄎן⳿׃ָ䗳׆剑黝⻉ׁ׸גְ׷׻ֽד
כזְ
Optimization

85. CompilationQueue
CompilationJob
CompilationJob
CompilationJob
Hot Function
Bytecode Called
Hot Function(Queued)
Bytecode Called
Hot Function(Queued)
Bytecode Called
Optimized Function
Assembly Called

86. const x = x => x;!
const y = () => {!
for (let i = 0; i < 1000; i++) {!
x(i);!
}!
!
for (let i = 0; i < 1000; i++) {!
x(i);!
}!
};!
y();!

87. 0x13b567fa924e LdaSmi.Wide [1000]
0x13b567fa9268 JumpLoop [26], [0] (0x13b567fa924e @ 4)
Bytecode length 26 budget –= 26
0x13b567fa926e LdaSmi.Wide [1000]
0x13b567fa9288 JumpLoop [26], [0] (0x13b567fa926e @ 36)
Bytecode length 26 budget –= 26
0x13b567fa928c Return
budget –= all_bytecode_length

88. Budget for function
׋הִٕ٦فָⴓⶴׁ׸גְג׮Ⰻ⡤ך✮皾׾Returnד׮鎘皾ׅ
׷ךד㉏겗זֻ剑黝⻉ָ遤׻׸׷
Optimization

89. TurboFan

90. What is TurboFan?
TurboFanהכV8ך剑黝⻉أةحؙךֿה
V8כBytecodeַ׵剑黝⻉؝ٝػ؎ٕ׾遤ֲ㜥さחծ
♧傉IR׾欰䧭ׅ׷
ֿךGraph欰䧭ה剑黝⻉׾遤ֲךָTurboFan
TurboFan

91. Bytecode
IR
TurboFan
Optimization
&
CodeGeneration

92. IR
䬄韋涸ז㹋遤ـٗحؙ
Control Flow Graph
TurboFan

93. #22:Branch[None](#21:SpeculativeNumberLessThan, #9:Loop)
#28:IfTrue(#22:Branch)
#30:JSStackCheck(#11:Phi, #32:FrameState,
#21:SpeculativeNumberLessThan, #28:IfTrue)
(#11:Phi, #34:FrameState, #30:JSStackCheck,
#30:JSStackCheck)
#2:HeapConstant[0x2f3e1c6022e1 ]()
#39:FrameState
#37:FrameState#35:Checkpoint(#37:FrameState,
#38:JSCall[2, 15256, NULL_OR_UNDEFINED]
#9:Loop(#0:Start, #38:JSCall)

94. Optimization
TurboFanכGraphח㼎׃ג剑黝⻉׾遤ֲ
TurboFan

95. inline
ꟼ侧ㄎן⳿׃ךInline⻉
trimming
ⵋ麦׃זְNodeך⵴ꤐ
type
㘗䱿锷
typed-lowering
㘗ח㛇בְג䒭װㄏ⟀׾״׶知⽃זⳢ椚ח縧ֹ䳔ִ׷
loop-peeling
ٕ٦فⰻךⳢ椚׾㢩ח⳿ׅկ

96. loop-exit-elimination
LoopExit׾⵴ꤐ
搀꼽ז⦼ך铣׫⳿׃װcheck׾⵴ꤐ
simpliﬁed-lowering
״׶Ⱗ⡤涸ז⦼דㄏ⟀׾ءٝفٕח㢌䳔ׅ׷
generic-lowering
JSفٖؿ؍حؙأך➰ֻㄏ⟀׾״׶ءٝفٕזㄎן⳿׃װ
stubךㄎן⳿׃ח㢌䳔ׅ׷
ⵋ麦♶腉؝٦سך⵴ꤐ

97. Code generation
剑穄涸חInstructionSelectorהְֲؙٓأָregisterךⶴ➰׾遤
ְծ
ֿךؚٓؿַ׵CodeGeneratorָ堣唒铂׾欰䧭׃ג
PC(ProgramCounter)ח،إٝـٔ׾剅ֹ⳿׃גְֻ
Optimization

98. Deoptimization

99. What is Deoptimization?
Deoptimization(膴剑黝⻉)הכ剑黝⻉׃׋Assembly؝٦سח✮劍
ׇט⦼ָ床׏׋㜥さחծⱄ䏝؝ٝػ؎ٕ׃湫ׅ堣腉
׮׍׹׿㼰זְח馉׃׋ֿהכזְ
Deoptimizationָ涪欰ׅ׷⢽׾然钠׃ג׫״ֲ
Deoptimization

100. const id = x => x;!
const test = obj => {!
for (let i = 0; i < 100000; i++) {!
id(obj.x);!
}!
};!
!
test({x: 1});!
test({x: 1, y: 1});!

101. Wrong Map
➙ך⢽דכ剑ⴱח{x}ךMapח㼎׃ג剑黝⻉ׁ׸׋Assembly׾⳿
⸂׃׋ָծ
✳㔐湡ךㄎן⳿׃ָ{x,y}ךMap׌׏׋׋׭חծⱄ؝ٝػ؎ٕ׾⡭
⭑זֻׁ׸ג׃ת׏׋
׍׳׏ה׌ֽAssembly׾鋖ְג׫״ֲ
Deoptimization

102. 0x451eb30464c 8c 48b9f1c7d830391e0000 REX.W movq rcx,
0x1e3930d8c7f1
0x451eb304656 96 483bca REX.W cmpq rcx,rdx
0x451eb304659 99 0f8591000000 jnz 0x451eb3046f0
;; Check Map!!
...
0x451eb3046f0 130 e81ff9cfff call 0x451eb004014
;; deoptimization bailout 2

103. Bailout
ֿך״ֲח⳿⸂ׁ׸׋؝٦سחMap׾然钠ׅ׷؝٦س׮ろת׸ג
ְ׷
Deoptimizationָ遤׻׸׷ה؝٦سכBytecode㹋遤ח䨱׷ָծ
ֿ׸׾Bailoutהㄎע
Deoptimization

104. Summary
⟃♳ָV8ָJS׾㹋遤ׅ׷䊨玎ד֮׷
儗꟦ך鿪さ♳GCכ満ְ׋
V8ך؝٦سٔ٦ر؍ؚٝך䪮遭瘝כת׋ـؚٗח剅ֻ✮㹀
http://abcdef.gets.b6n.ch/
׀幠耮֮׶ָהֲ׀ְׂת׃׋