Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Source to Binary - journey of V8 javascript engine
Search
Taketoshi Aono(青野健利 a.k.a brn)
November 25, 2017
Programming
13
13k
Source to Binary - journey of V8 javascript engine
V8 javascript engineについて
パーサー、AST、Ignition/TurboFan、最適化周り等
Taketoshi Aono(青野健利 a.k.a brn)
November 25, 2017
Tweet
Share
More Decks by Taketoshi Aono(青野健利 a.k.a brn)
See All by Taketoshi Aono(青野健利 a.k.a brn)
document.write再考
brn
6
2.9k
Parsing Javascript
brn
12
9k
JSON & Object Tips
brn
1
400
CA 1Day Youth Bootcamp for Frontend LT
brn
0
790
Modern TypeScript
brn
2
750
javascript - behind the scene
brn
3
680
tc39 proposals
brn
0
780
プロダクト開発とTypeScript
brn
8
2.8k
React-Springでリッチなアニメーション
brn
1
600
Other Decks in Programming
See All in Programming
TypeScript Graph でコードレビューの心理的障壁を乗り越える
ysk8hori
2
1.1k
型付き API リクエストを実現するいくつかの手法とその選択 / Typed API Request
euxn23
8
2.2k
距離関数を極める! / SESSIONS 2024
gam0022
0
280
ペアーズにおけるAmazon Bedrockを⽤いた障害対応⽀援 ⽣成AIツールの導⼊事例 @ 20241115配信AWSウェビナー登壇
fukubaka0825
6
1.8k
Realtime API 入門
riofujimon
0
150
Amazon Bedrock Agentsを用いてアプリ開発してみた!
har1101
0
330
Outline View in SwiftUI
1024jp
1
320
Quine, Polyglot, 良いコード
qnighy
4
640
A Journey of Contribution and Collaboration in Open Source
ivargrimstad
0
870
ECS Service Connectのこれまでのアップデートと今後のRoadmapを見てみる
tkikuc
2
250
PHP でアセンブリ言語のように書く技術
memory1994
PRO
1
170
ActiveSupport::Notifications supporting instrumentation of Rails apps with OpenTelemetry
ymtdzzz
1
230
Featured
See All Featured
The Art of Programming - Codeland 2020
erikaheidi
52
13k
Building a Modern Day E-commerce SEO Strategy
aleyda
38
6.9k
BBQ
matthewcrist
85
9.3k
Six Lessons from altMBA
skipperchong
27
3.5k
Building Your Own Lightsaber
phodgson
103
6.1k
A Tale of Four Properties
chriscoyier
156
23k
A Modern Web Designer's Workflow
chriscoyier
693
190k
GraphQLとの向き合い方2022年版
quramy
43
13k
Fashionably flexible responsive web design (full day workshop)
malarkey
405
65k
Practical Orchestrator
shlominoach
186
10k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
246
1.3M
The Language of Interfaces
destraynor
154
24k
Transcript
None
Name @brn (ꫬꅿ⨳ⵃ) Occupation ؿٗٝزؒٝسؒٝآص،٥ط؎ذ؍ـؒٝآص، Company Cyberagent ،سذؙأةآؔ AI Messenger
Blog http://abcdef.gets.b6n.ch/ Twitter https://twitter.com/brn227 GitHub https://github.com/brn
Agenda • What is V8? • Execution flow of V8
• Parsing • Abstract Syntax Tree • Ignition – BytecodeInterpreter • CodeStubAssembler • Builtins / Runtime • Optimization / Hidden Class / Inline Caching • TurboFan / Deoptimization
What is V8? V8הכGoogle爡ָ㹋鄲׃javascriptؒٝآٝדծ Google Chrome/Node.JSךjavascriptؒٝآٝח䱰欽ׁגְתׅկ
Execution Flow
Source AST Bytecode Graph Assembly first time hot code
Parsing
Basic parsing V8כا٦أ؝٦سػ٦أ׃גASTח㢌䳔ׅ ASTהכAbstractSyntaxTreeך殛獥 䬄韋圓俑加הㄎל Parsing
if (x) { x = 100 }
IF CONDITION THEN BLOCK EXPRESSION STATEMENT ASSIGN VAR PROXY (X)
LITERAL (100) if (x) { x = 100
Problems
Parsing all functions - Slow ׅץגך؝٦س剑ⴱחػ٦أׅךכ֮ת״׃ֻזְ ׃ػ٦أ׃؝٦سָ㹋遤ׁזֽל䠐ָזְ Parsing
Split parsing phase ػ٦أ鹼䒀׃ג遤ֲחծػ٦أ✳媮ꥡחⴓֽ Parsing
PreParsing ✲חׅץגךꟼ侧ךٖ؎،ؐز ػ٦أ׃גֶֻ Parsing
function x(a, b) { return a + b; } FUNCTION(X)
parameter-count: 2 start-position: 1 end-position: 34 use-super-property: false …
// when x is called x() FUNCTION NAME (x) RETURN
LITERAL(1)
Lazy Parsing V8כ㹋ꥷח״ןׁתדػ٦أ鹼䒀ׅ ꟼ侧כㄎן⳿ׁגⴱג؝ٝػ؎ׁٕ Parsing
More About https://docs.google.com/presentation/d/1b- ALt6W01nIxutFVFmXMOyd_6ou_6qqP6S0Prmb1iDs/present? slide=id.p Parsing
Abstract Syntax Tree
AST Rewriting Parserח״ג欰䧭ׁAST㢌䕎ׅ ְֻאַ稱➜ AbstractSyntaxTree
Subsclass constructor return 竰䪫׃ؙٓأך؝ٝأزؙٓة㢌䕎ׅ 崢欰ؙٓأך؝ٝأزؙٓةד䒭return׃גְ儗כծ 3갪怴皾㶨ח㢌䳔׃גծ 䒭ך穠卓ָundefined㜥さחכthis䨱ׅկ AbstractSyntaxTree
constructor() {! super();! return expr! }! ! constructor() {! super();!
var tmp;! return (temp = expr) === undefined?! this: temp;! }!
for (let/const/var in/of e) for-in/ofךⴱ劍⻉דconst/let⢪ֲחծⰋ⡤ـٗحؙד㔲 㢌侧㹑鎉ׅկ AbstractSyntaxTree
for (const key of e) {! ...! }!
{! var temp;! for (temp of e) {! const x
= temp;! ...! }! let x! }!
Spread operator doהfor-ofח縧ֹ䳔ִגⳢ椚 AbstractSyntaxTree
const x = [1,2,3];! const y = [...x];!
do {! $R = [];! for ($i of x)! %AppendElement($R,
$i);! $R! }!
Ecmascript? – Binary AST ➙תד鋅״ֲחASTך؟؎ؤכ穠圓㣐ְֹךדծ 㖇簭ׅ䲿周 Parsing
Ignition
Bytecode Interpreter V8כ欰䧭׃AST1~4byteךBytecodeח㢌䳔׃גַ㹋遤ׅ Ignition
How does it work? ♧אך،ُؗيٖ٦ة٦⪒ִٖآأةك٦أד⹛⡲ׅ؎ٝ ة٦فٔة Ignition
Pseudo javascript code Javascriptד圓鸡垷⦺ׅהֿך״ֲחז Ignition
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++]);!
How to create bytecode? BytecodeכASTַAstVisitorⵃ欽׃ג欰䧭ׁ AstVisitorכVistorػة٦ٝⵃ欽׃ؙٓأדծ AST帾ׁ⮚⯓䱱稊׃זָ㼎䘔ׅ؝٦ٕغحؙꟼ侧ㄎן⳿ ׅ Ignition
BytecodeArray 欰䧭ׁBytecodeכBytecodeArrayח呓秛ׁ BytecodeArrayכꟼ侧⽃⡘ד㶷㖈ׅ Ignition
Dispatch Table Stub(Machine Code) BytecodeArray Dispatch Tableから対応するHandlerを取り出して実行 0 1 3
4 5 6 7 8 5 6 1
InterpreterEntryTrampoline 剑穄涸ח欰䧭ׁBytecodeכInterpreterEntrynTrampolineה ㄎלBuiltin؝٦سַ㹋遤ׁ InterpreterEntryTrampolineכAssemblyח؝ٝػ؎ׁٕծ 鸐䌢ךCךꟼ侧הㄎן⳿ׁ Ignition
InterpreterEntryTrampoline(Assembly) Script::Run Call as C function Ignition DispatchTable Dispatch First
bytecode
Ignition Handler ⯓玎亻⡂؝٦سד爙׃BytecodeHandlersכV8דכ Ignition Handlerהㄎלגְ Ignition HandlerכCodeStubAssemblerהְֲDSLד鎸鶢ׁג ְ Iginition
CodeStub Assember
What is CodeStubAssmber? CodeStubAssembler(CSA)כ؝٦س欰䧭ؚٓؿ欰䧭ח䬄韋⻉׃ V8ⰻ鿇ךDSL 㹋遤✮㹀Node穈甧גֽדծCodeGeneratorח״גぐ ،٦ؗذؙثٍぢֽך؝٦سָ欰䧭ׁծ،إٝـٔ鎉铂 ְְ倜ח剅ֻ䗳銲ָזְ CodeStubAssembler
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);! }!
Graph based DSL ֿךCodeStubAssemblerךֶַ־ד㹋ꥷך،٦ؗذؙثٍぢֽ ך،إٝـٓ擾濼׃גְזֻג֮ח؝٦س鷄⸇ֿׅ הָ㺁僒חזծ ת〳铣䚍ꬊ䌢ח넝ֻזגְ CodeStubAssembler
Dispatch Table 00 01 02 04 08 0f 10 10
Node Node Node Operator Operator IGNITION_HANDLER Stub (Mahine Code Fragment) グラフからコードを生成 生成したコードを、 DispatchTableの対応する バイトコードのインデックスへ 登録 Assemble
Assembler 㹋ꥷחぐ،٦ؗذؙثٍぢֽך؝٦س⳿⸂ׅ X64ぢֽךjmpص٦ٌصحؙ׳הֽ鋖ְג״ֲ CodeStubAssembler
void Assembler::jmp(! Handle<Code> target,! RelocInfo::Mode rmode! ) {! EnsureSpace ensure_space(this);!
// 1110 1001 #32-bit disp.! // ここでメモリ上にアセンブラを書き出す! emit(0xE9);! emit_code_target(target, rmode);! }!
Where to use BuiltinsכAssemblerؙٓأⵃ欽׃גぐ،٦ؗذؙثٍ嫣ך Stubָ鎸鶢ׁגְ ♧鿇CSA⢪ֲ皘䨽֮(*-gen.cc) Ignition HandlerכקרⰋגָCSAד鎸鶢ׁגְ CodeStubAssembler
Builtins & Runtime
Builtins BuiltinsכV8ך饯⹛儗ח؝ٝػ؎ׁٕ،إٝـٓך؝٦س晙 ꟼ侧ך״ֲחCallBuiltin穗歋דㄎן⳿ׁ Stubהㄎל 㹋遤儗ך剑黝⻉כ遤זְ Builtins & Runtime
Runtime RuntimeכBuiltinsװך➭ך،إٝـٓ؝٦سַㄎן⳿ֿׅ הָדֹC++ך؝٦س Javascriptך⚅歲ַC++ך⚅歲אזּ؝٦س晙 ずֻׄ㹋遤儗ך剑黝⻉כ遤זְ Builtins & Runtime
Hidden Class
What is Hidden Class? Javascriptחכ㘗ָזְךדؔـآؙؑز鋉㹀ׅךָ搀ְկ ךծV8כؔـآؙؑزך圓鸡荈⡤㘗ך״ֲח䪔גְկ ֿHidden Classהㄎע Hidden Class
• Hidden Class const point1 = {x: 0, y: 0};!
const point2 = {x: 0, y: 0};! Map FixedArray [ {x: {offset: 0}}, {y: {offset: 1}} ]
Map הִJavascript♳דכⴽךؔـآؙؑزד֮גծ ずׄ圓鸡䭯גְלずׄHidden ClassⰟ剣ׅ ׃גֿךؔـآؙؑزך酅ח֮圓鸡Mapהㄎע Hidden Class
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!
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!
Layout Mapؔـآؙؑزכַז⿑㺘חفٗػذ؍ךoffsetثؑحؙ ׅծٔذٕٓךⴱ劍⻉갫٥فٗػذ؍ךⴱ劍⻉갫٥فٗػ ذ؍ך侧ָ麩ֲהⴽךMapָⶴ䔲ג Hidden Class
Map Transition ׃ַ׃فٗػذ؍ך㟓幾ָ걼籕ח饯ֿJavascriptדծ嫣㔐Map 欰䧭ׅה؝أزָ搀鋔דֹזְךדכ V8כفٗػذ؍ך㟓幾ָ֮㜥さחכMapⰟ剣׃זָծ 㟓ִ鿇ⴓךך倜׃ְMap欰䧭ׅ ֿMap Transitionהㄎע Hidden Class
function Point(x, y) { this.x = x; this.y = y;
} Map FixedArray [ {x: {offset: 0}}, {y: {offset: 1}}, ] var x = new Point(1, 1); x.z = 1; Map FixedArray [ {z: {offset: 2}} ] transition {z: transi>on(address)}
What's Happening? Hidden Classָ֮ה⡦ָ㴍׃ְַהְֲהծ ؔـآؙؑزךفٗػذ؍،ؙإأװ㘗ךثؑحؙ״넝鸞חծ ״㸜Ⰻח遤ִ״ֲחז Hidden Class
Inline Caching
What is Inline Caching فٗػذ؍،ؙإأך넝鸞⻉ךח麓ך،ؙإأٍؗح ءُ׃גֶֻ Inline Caching
function x(obj) {! return obj.x + obj.y;! }! ! x({x:
0, y: 0});! x({x: 1, y: 1});! x({x: 2, y: 2});!
Search Property ؔـآؙؑزַفٗػذ؍䱱ׅחכծ HashMapװFixedArrayַفٗػذ؍ٗ٦سׅ ׃ַ׃嫣㔐遤ֲךכꬊ䌢ח鹼ְ Inline Caching
Reduce Property Access ֿך⢽דכxהyפך،ؙإأָずׄMap䭯אؔـآؙؑزח㼎 ׃ג⡦䏝㹋遤ׁגְ ׅדחobjכ{x, y}ךMapהַגְךד֮לծ 䔲搫ًٌٖٔ؎،ؐزַגְךדծ湫䱸offset䭷㹀׃ ג،ؙإأ׃קֲָ傍ְ Inline
Caching
Cache זךדծ暴㹀ךMapך،ؙإأ鎸䥉׃גֶֻ ֮فٗػذ؍פ،ؙإأ׃㜥さծךMapؔـآؙؑز鎸 䥉ֿׅהד2㔐湡⟃꣬ךفٗػذ؍،ؙإأָ넝鸞⻉ׁ Inline Caching
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})! // load ic miss! x({x: 1, y: 1, foo() {}});! // load ic miss!
Cache Miss ׃ծMapָ㢌⻉׃㜥さחכ䔲搫CacheךMissؼحزָ饯ֹ ךדծתفٗػذ؍ٗ٦س׃ג倜ח鎸䥉׃湫ׅ ׃ׅץג鎸ꐮׅךכ♶〳腉זךדծ4אתדMapؔـ آؙؑز鎸ꐮׅ Inline Cache
Cahce State ٍؗحءُך朐䡾כ⟃♴ך״ֲח鼂獳ׅ PreMonomorphic Monomorphic Polymorphic Megamorphic Inline Caching
Pre Monomorphic ؝٦س♳ך鿪さד劢ⴱ劍ַוֲַⴻ㹀ׅח㶷㖈ׅךדծ ֮ת䠐כזְ Inline Caching
Monomorphic ⽃♧ךMapפך،ؙإأ׃ַ㶷㖈׃זְ朐䡾 椚䟝涸ז朐䡾ה鎉ִ Inline Caching
Polymorphic MapָFixedArrayח呓秛ׁגֶ醱侧ךMapַ嗚稊׃ג فٗػذ؍،ؙإأ㹋遤ׅ ٍؗحءُ荈⡤כׁגְךדת넝鸞 Inline Caching
Megamorphic ֮תחMissָ㢳ְךדծMapך鎸ꐮ⨡姺׃朐䡾 איחStubַGetPropertyㄎן⳿׃גفٗػذ؍《䖤ׅ 剑鹼ְ朐䡾 Inline Caching
Optimization
Hot or Small 䌢ח؝٦س剑黝⻉ׅךכꬊ䌢ח搀꼽 ⟃♴ך勴⟝ח䔲גכת؝٦س剑黝⻉ׅ • (ꟼ侧ךغ؎ز؝٦سꞿ/ 1200) + 2ך㔐侧ꟼ侧ָㄎן⳿ׁ
גְ • ꟼ侧ָ㼭ְׁ(غ؎ز؝٦سךꞿָׁ90劢弫) Optimization
Optimization Budget غ؎ز؝٦س㹋遤⚥חぐꟼ侧חכ剑黝⻉✮皾ָⶴ䮶גֶծ ך⦼ָ0ⴖה؝٦س剑黝⻉⦪酡הז Optimization
For loop ٕ٦فדכJumpLoopהְֲغ؎ز؝٦سָ⳿⸂ׁ ֿךJumpLoopך⚥ד䨱⯓ך،سٖأ⦼ךoffsetꅾח׃גծ ⯓玎ך✮皾ַ⦼䒷ֹծָ0ⶴٕ٦فⰻך剑黝⻉ ָ涪欰ׅ Optimization
function id(v) {return v;}! function x(v) {! for (var i
= 0; i < 10000; i++) {! id(v + i);! }! }! x(1);!
0x1bb9e5e2935e LdaSmi.Wide [1000] 0x1bb9e5e2937e JumpLoop [32], [0] (0x1bb9e5e2935e @ 4)
Bytecode length = 100 if (budget –= 100 < 0) { OptimizeAndOSR(); }
OSR - OnStackReplacement ؝ٝػ؎ׁٕגغ؎ز؝٦سַ堣唒铂ח㢌䳔ׁ؝٦سכծ ٕ٦فך鷿⚥ד굲ן⯓ָ剅ֹ䳔ִג倜ז堣唒铂ך؝٦سָ 㹋遤ׁ Optimization
For function ꟼ侧ך㜥さכReturnغ؎ز؝٦سָ䗳׆欰䧭ׁ ֿדInterruptָ遤ג✮皾ךثؑحָؙ涪欰ׅ Optimization
function x() {! const x = 1 + 1;! }!
x();!
0x3d22953a917a StackCheck 0x3d22953a9180 Return Bytecode length 30 if (budget -=
30 < 0) { OptimizeConcurrent(); }
Concurrent Compilation ꟼ侧剑黝⻉ׅ㜥さכծ⚛؝ٝػ؎ָٕꬊず劍ח遤 ך如㔐⟃꣬ךꟼ侧ㄎן⳿׃ָ䗳׆剑黝⻉ׁגְֽד כזְ Optimization
CompilationQueue CompilationJob CompilationJob CompilationJob Hot Function Bytecode Called Hot Function(Queued)
Bytecode Called Hot Function(Queued) Bytecode Called Optimized Function Assembly Called
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();!
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
Budget for function הִٕ٦فָⴓⶴׁגְגⰋ⡤ך✮皾Returnד鎘皾ׅ ךד㉏겗זֻ剑黝⻉ָ遤 Optimization
TurboFan
What is TurboFan? TurboFanהכV8ך剑黝⻉أةحؙךֿה V8כBytecodeַ剑黝⻉؝ٝػ؎ٕ遤ֲ㜥さחծ ♧傉IR欰䧭ׅ ֿךGraph欰䧭ה剑黝⻉遤ֲךָTurboFan TurboFan
Bytecode IR TurboFan Optimization & CodeGeneration
IR 䬄韋涸ז㹋遤ـٗحؙ Control Flow Graph TurboFan
#22:Branch[None](#21:SpeculativeNumberLessThan, #9:Loop) #28:IfTrue(#22:Branch) #30:JSStackCheck(#11:Phi, #32:FrameState, #21:SpeculativeNumberLessThan, #28:IfTrue) #33:JSLoadGlobal[0x2f3e1c607881 <String[1]: a>,
1] (#11:Phi, #34:FrameState, #30:JSStackCheck, #30:JSStackCheck) #2:HeapConstant[0x2f3e1c6022e1 <undefined>]() #39:FrameState #36:StateValues[sparse:^^](#12:Phi, #33:JSLoadGlobal) #37:FrameState#35:Checkpoint(#37:FrameState, #33:JSLoadGlobal, #33:JSLoadGlobal) #38:JSCall[2, 15256, NULL_OR_UNDEFINED] (#33:JSLoadGlobal, #2:HeapConstant, #11:Phi, #39:FrameState, #35:Checkpoint, #33:JSLoadGlobal) #9:Loop(#0:Start, #38:JSCall)
Optimization TurboFanכGraphח㼎׃ג剑黝⻉遤ֲ TurboFan
inline ꟼ侧ㄎן⳿׃ךInline⻉ trimming ⵋ麦׃זְNodeךꤐ type 㘗䱿锷 typed-lowering 㘗ח㛇בְג䒭װㄏ⟀״知⽃זⳢ椚ח縧ֹ䳔ִ loop-peeling ٕ٦فⰻךⳢ椚㢩ח⳿ׅկ
loop-exit-elimination LoopExitꤐ load-elimination 搀꼽ז⦼ך铣⳿׃װcheckꤐ simplified-lowering ״Ⱗ⡤涸ז⦼דㄏ⟀ءٝفٕח㢌䳔ׅ generic-lowering JSفٖؿ؍حؙأך➰ֻㄏ⟀״ءٝفٕזㄎן⳿׃װ stubךㄎן⳿׃ח㢌䳔ׅ dead-code-elimination
ⵋ麦♶腉؝٦سךꤐ
Code generation 剑穄涸חInstructionSelectorהְֲؙٓأָregisterךⶴ➰遤 ְծ ֿךؚٓؿַCodeGeneratorָ堣唒铂欰䧭׃ג PC(ProgramCounter)ח،إٝـٔ剅ֹ⳿׃גְֻ Optimization
Deoptimization
What is Deoptimization? Deoptimization(膴剑黝⻉)הכ剑黝⻉׃Assembly؝٦سח✮劍 ׇט⦼ָ床㜥さחծⱄ䏝؝ٝػ؎ٕ׃湫ׅ堣腉 㼰זְח馉׃ֿהכזְ Deoptimizationָ涪欰ׅ⢽然钠׃ג״ֲ Deoptimization
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});!
Wrong Map ➙ך⢽דכ剑ⴱח{x}ךMapח㼎׃ג剑黝⻉ׁAssembly⳿ ⸂׃ָծ ✳㔐湡ךㄎן⳿׃ָ{x,y}ךMapחծⱄ؝ٝػ؎ٕ⡭ ⭑זֻׁג׃ת ׳הֽAssembly鋖ְג״ֲ Deoptimization
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
Bailout ֿך״ֲח⳿⸂ׁ؝٦سחMap然钠ׅ؝٦سろתג ְ Deoptimizationָ遤ה؝٦سכBytecode㹋遤ח䨱ָծ ֿBailoutהㄎע Deoptimization
Summary ⟃♳ָV8ָJS㹋遤ׅ䊨玎ד֮ 儗ך鿪さ♳GCכ満ְ V8ך؝٦سٔ٦ر؍ؚٝך䪮遭瘝כתـؚٗח剅ֻ✮㹀 http://abcdef.gets.b6n.ch/ ׀幠耮ָ֮הֲ׀ְׂת׃