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
V8 internals for JavaScript developers
Search
Mathias Bynens
September 04, 2017
Technology
200
1
Share
V8 internals for JavaScript developers
Google Experts Summit 2017
Mathias Bynens
September 04, 2017
More Decks by Mathias Bynens
See All by Mathias Bynens
V8 internals for JavaScript developers @ Fronteers 2018
mathiasbynens
3
530
V8 internals for JavaScript developers
mathiasbynens
2
1.1k
What’s new in ES2018?
mathiasbynens
2
160
Preventing timing attacks on the web @ Fronteers Jam 2016
mathiasbynens
4
280
Front-End Performance: The Dark Side @ ColdFront Conference 2016
mathiasbynens
1
520
Hacking with Unicode in 2016
mathiasbynens
15
15k
Front-End Performance: The Dark Side @ Fronteers Spring Conference 2016
mathiasbynens
16
57k
3.14 things I didn’t know about CSS @ CSSConf.asia 2015
mathiasbynens
4
1.2k
3.14 things I didn’t know about CSS @ CSS Day 2014
mathiasbynens
70
29k
Other Decks in Technology
See All in Technology
「決め方」の渡し方 / How to hand over the "decision-making process"
pauli
7
1.2k
AIドリブン開発の実践知 ― AI-DLC Unicorn Gym実施から見えた可能性と課題
mixi_engineers
PRO
0
110
【関西電力KOI×VOLTMIND 生成AIハッカソン】空間AIブレイン ~⼤阪おばちゃんフィジカルAIに続く道~
tanakaseiya
0
150
TanStack Start エコシステムの現在地 / TanStack Start Ecosystem 2026
iktakahiro
1
290
Embeddings : Symfony AI en pratique
lyrixx
0
460
JSTQB Expert Levelシラバス「テストマネジメント」日本語版のご紹介
ymty
0
130
「活動」は激変する。「ベース」は変わらない ~ 4つの軸で捉える_AI時代ソフトウェア開発マネジメント
sentokun
0
150
組織的なAI活用を阻む 最大のハードルは コンテキストデザインだった
ixbox
1
520
2026-04-02 IBM Bobオンボーディング入門
yutanonaka
0
200
Oracle AI Databaseデータベース・サービス: BaseDB/ExaDB-Dの可用性
oracle4engineer
PRO
1
120
「できない」のアウトプット 同人誌『精神を壊してからの』シリーズ出版を 通して得られたこと
comi190327
3
570
ブラックボックス化したMLシステムのVertex AI移行 / mlops_community_62
visional_engineering_and_design
1
280
Featured
See All Featured
A Modern Web Designer's Workflow
chriscoyier
698
190k
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
210
How to audit for AI Accessibility on your Front & Back End
davetheseo
0
230
The State of eCommerce SEO: How to Win in Today's Products SERPs - #SEOweek
aleyda
2
10k
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
350
Believing is Seeing
oripsolob
1
100
Context Engineering - Making Every Token Count
addyosmani
9
790
Crafting Experiences
bethany
1
110
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.4k
Into the Great Unknown - MozCon
thekraken
40
2.3k
Mind Mapping
helmedeiros
PRO
1
140
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.4k
Transcript
None
V8 internals for JavaScript developers @mathias
Elements kinds in V8
const array = [1, 2, 3];
const array = [1, 2, 3]; // elements kind: PACKED_SMI_ELEMENTS
const array = [1, 2, 3]; // elements kind: PACKED_SMI_ELEMENTS
array.push(4.56);
const array = [1, 2, 3]; // elements kind: PACKED_SMI_ELEMENTS
array.push(4.56); // elements kind: PACKED_DOUBLE_ELEMENTS
const array = [1, 2, 3]; // elements kind: PACKED_SMI_ELEMENTS
array.push(4.56); // elements kind: PACKED_DOUBLE_ELEMENTS array.push('x');
const array = [1, 2, 3]; // elements kind: PACKED_SMI_ELEMENTS
array.push(4.56); // elements kind: PACKED_DOUBLE_ELEMENTS array.push('x'); // elements kind: PACKED_ELEMENTS
Smi Doubles Regular elements Elements kinds
const array = [1, 2, 3]; // elements kind: PACKED_SMI_ELEMENTS
array.push(4.56); // elements kind: PACKED_DOUBLE_ELEMENTS array.push('x'); // elements kind: PACKED_ELEMENTS
array.length; // 5 index 0 1 2 3 4 value
1 2 3 4.56 'x'
array.length; // 5 array[9] = 1; // array[5] until array[8]
are now holes index 0 1 2 3 4 5 6 7 8 9 value 1 2 3 4.56 'x' 1
array.length; // 5 array[9] = 1; // array[5] until array[8]
are now holes // elements kind: HOLEY_ELEMENTS index 0 1 2 3 4 5 6 7 8 9 value 1 2 3 4.56 'x' 1
array[8]; // → ??? index 0 1 2 3 4
5 6 7 8 9 value 1 2 3 4.56 'x' 1
array[8]; // → ??? ❌ index 0 1 2 3
4 5 6 7 8 9 value 1 2 3 4.56 'x' 1
array[8]; // → ??? ❌ 8 >= 0 && 8
< array.length; // bounds check // → true index 0 1 2 3 4 5 6 7 8 9 value 1 2 3 4.56 'x' 1
array[8]; // → ??? ❌ 8 >= 0 && 8
< array.length; // bounds check // → true ❌ index 0 1 2 3 4 5 6 7 8 9 value 1 2 3 4.56 'x' 1
array[8]; // → ??? ❌ 8 >= 0 && 8
< array.length; // bounds check // → true ❌ hasOwnProperty(array, '8'); // → false index 0 1 2 3 4 5 6 7 8 9 value 1 2 3 4.56 'x' 1
index 0 1 2 3 4 5 6 7 8
9 value 1 2 3 4.56 'x' 1 array[8]; // → ??? ❌ 8 >= 0 && 8 < array.length; // bounds check // → true ❌ hasOwnProperty(array, '8'); // → false ❌
array[8]; // → ??? ❌ 8 >= 0 && 8
< array.length; // bounds check // → true ❌ hasOwnProperty(array, '8'); // → false ❌ hasOwnProperty(Array.prototype, '8'); // → false
array[8]; // → ??? ❌ 8 >= 0 && 8
< array.length; // bounds check // → true ❌ hasOwnProperty(array, '8'); // → false ❌ hasOwnProperty(Array.prototype, '8'); // → false ❌
array[8]; // → ??? ❌ 8 >= 0 && 8
< array.length; // bounds check // → true ❌ hasOwnProperty(array, '8'); // → false ❌ hasOwnProperty(Array.prototype, '8'); // → false ❌ hasOwnProperty(Object.prototype, '8'); // → false
array[8]; // → ??? ❌ 8 >= 0 && 8
< array.length; // bounds check // → true ❌ hasOwnProperty(array, '8'); // → false ❌ hasOwnProperty(Array.prototype, '8'); // → false ❌ hasOwnProperty(Object.prototype, '8'); // → false ✅
array[8]; // → undefined ✅ 8 >= 0 && 8
< array.length; // bounds check // → true hasOwnProperty(array, '8'); // → false hasOwnProperty(Array.prototype, '8'); // → false hasOwnProperty(Object.prototype, '8'); // → false ✅
packedArray[8]; // → undefined ✅ 8 >= 0 && 8
< packedArray.length; // bounds check // → true ✅ hasOwnProperty(packedArray, '8'); // → true ✅ hasOwnProperty(Array.prototype, '8'); // → false ✅ hasOwnProperty(Object.prototype, '8'); // → false ✅
packedArray[8]; // → undefined ✅ 8 >= 0 && 8
< packedArray.length; // bounds check // → true ✅ hasOwnProperty(packedArray, '8'); // → true ✅ hasOwnProperty(Array.prototype, '8'); // → false ✅ hasOwnProperty(Object.prototype, '8'); // → false ✅
array[0]; // → ???
array[0]; // → ??? ❌
array[0]; // → ??? ❌ 0 >= 0 && 0
< array.length; // bounds check // → true
array[0]; // → ??? ❌ 0 >= 0 && 0
< array.length; // bounds check // → true ❌
array[0]; // → ??? ❌ 0 >= 0 && 0
< array.length; // bounds check // → true ❌ hasOwnProperty(array, '0'); // → true
array[0]; // → ??? ❌ 0 >= 0 && 0
< array.length; // bounds check // → true ❌ hasOwnProperty(array, '0'); // → true ✅
array[0]; // → 1 ✅ 0 >= 0 && 0
< array.length; // bounds check // → true hasOwnProperty(array, '0'); // → true ✅
PACKED > HOLEY
PACKED > HOLEY
Smi Doubles Regular elements Elements kinds
Smi, packed Doubles, packed Regular elements, packed Smi, holey Doubles,
holey Regular elements, holey
lattice
PACKED_SMI_ELEMENTS HOLEY_SMI_ELEMENTS PACKED_DOUBLE_ELEMENTS HOLEY_DOUBLE_ELEMENTS PACKED_ELEMENTS HOLEY_ELEMENTS
const array = new Array(3);
const array = new Array(3); index 0 1 2 value
const array = new Array(3); // HOLEY_SMI_ELEMENTS index 0 1
2 value
const array = new Array(3); // HOLEY_SMI_ELEMENTS array[0] = 'a';
index 0 1 2 value 'a'
const array = new Array(3); // HOLEY_SMI_ELEMENTS array[0] = 'a';
// HOLEY_ELEMENTS index 0 1 2 value 'a'
const array = new Array(3); // HOLEY_SMI_ELEMENTS array[0] = 'a';
// HOLEY_ELEMENTS array[1] = 'b'; index 0 1 2 value 'a' 'b'
const array = new Array(3); // HOLEY_SMI_ELEMENTS array[0] = 'a';
// HOLEY_ELEMENTS array[1] = 'b'; array[2] = 'c'; index 0 1 2 value 'a' 'b' 'c' now packed!
const array = new Array(3); // HOLEY_SMI_ELEMENTS array[0] = 'a';
// HOLEY_ELEMENTS array[1] = 'b'; array[2] = 'c'; // HOLEY_ELEMENTS (still!) now packed! but it’s too late index 0 1 2 value 'a' 'b' 'c'
const array = ['a', 'b', 'c']; // elements kind: PACKED_ELEMENTS
const array = ['a', 'b', 'c']; // elements kind: PACKED_ELEMENTS
// … array.push(someValue); array.push(someOtherValue);
Avoid holes! #ProTip Avoid holes
for (let i = 0, item; (item = items[i]) !=
null; i++) { doSomething(item); }
for (let i = 0, item; (item = items[i]) !=
null; i++) { doSomething(item); }
for (let i = 0, item; (item = items[i]) !=
null; i++) { doSomething(item); } for (let index = 0; index < items.length; index++) { doSomething(item); }
for (const item of items) { doSomething(item); }
Avoid holes! #ProTip Avoid out-of-bounds reads
[3, 2, 1, +0]; // PACKED_SMI_ELEMENTS
[3, 2, 1, +0]; // PACKED_SMI_ELEMENTS [3, 2, 1, -0];
// PACKED_DOUBLE_ELEMENTS
[3, 2, 1, +0]; // PACKED_SMI_ELEMENTS [3, 2, 1, -0];
// PACKED_DOUBLE_ELEMENTS [3, 2, 1, NaN, Infinity]; // PACKED_DOUBLE_ELEMENTS
Avoid holes! #ProTip Avoid elements kind transitions
const arrayLike = {}; arrayLike[0] = 'a'; arrayLike[1] = 'b';
arrayLike[2] = 'c'; arrayLike.length = 3;
Array.prototype.forEach.call(arrayLike, (value, index) => { console.log(`${ index }: ${ value
}`); }); // This logs '0: a', then '1: b', and finally '2: c'.
const actualArray = Array.prototype.slice.call(arrayLike, 0); actualArray.forEach((value, index) => { console.log(`${
index }: ${ value }`); }); // This logs '0: a', then '1: b', and finally '2: c'.
const logArgs = function() { Array.prototype.forEach.call(arguments, (value, index) => {
console.log(`${ index }: ${ value }`); }); }; logArgs('a', 'b', 'c'); // This logs '0: a', then '1: b', and finally '2: c'.
const logArgs = (...args) => { args.forEach((value, index) => {
console.log(`${ index }: ${ value }`); }); }; logArgs('a', 'b', 'c'); // This logs '0: a', then '1: b', and finally '2: c'.
Avoid holes! #ProTip Prefer arrays over array-like objects
$
$ rlwrap ~/projects/v8/out.gn/x64.debug/d8
$ rlwrap ~/projects/v8/out.gn/x64.debug/d8 --allow-natives-syntax
$ rlwrap ~/projects/v8/out.gn/x64.debug/d8 --allow-natives-syntax V8 version 6.2.0 (candidate) d8>
$ rlwrap ~/projects/v8/out.gn/x64.debug/d8 --allow-natives-syntax V8 version 6.2.0 (candidate) d8> const
array = [1, 2, 3];
$ rlwrap ~/projects/v8/out.gn/x64.debug/d8 --allow-natives-syntax V8 version 6.2.0 (candidate) d8> const
array = [1, 2, 3]; %DebugPrint(array);
$ rlwrap ~/projects/v8/out.gn/x64.debug/d8 --allow-natives-syntax V8 version 6.2.0 (candidate) d8> const
array = [1, 2, 3]; %DebugPrint(array); DebugPrint: 0x313389e0e551: [JSArray] - map = 0x3133e0582889 [FastProperties] - prototype = 0x313360387f81 - elements = 0x313389e0e4c9 <FixedArray[3]> [PACKED_SMI_ELEMENTS (COW)] - length = 3 - properties = 0x3133dae02241 <FixedArray[0]> { #length: 0x31336c242839 <AccessorInfo> (const accessor descriptor) } …
$ rlwrap ~/projects/v8/out.gn/x64.debug/d8 --allow-natives-syntax V8 version 6.2.0 (candidate) d8> const
array = [1, 2, 3]; %DebugPrint(array); DebugPrint: 0x313389e0e551: [JSArray] - map = 0x3133e0582889 [FastProperties] - prototype = 0x313360387f81 - elements = 0x313389e0e4c9 <FixedArray[3]> [PACKED_SMI_ELEMENTS (COW)] - length = 3 - properties = 0x3133dae02241 <FixedArray[0]> { #length: 0x31336c242839 <AccessorInfo> (const accessor descriptor) } …
None
Avoid holes. — J.K. Rowling
Avoid holes. Avoid out-of-bounds reads. — ancient Chinese proverb
Avoid holes. Avoid out-of-bounds reads. Avoid elements kind transitions. —
Justin Bieber
Avoid holes. Avoid out-of-bounds reads. Avoid elements kind transitions. Prefer
arrays over array-like objects. — Albert Einstein
Avoid holes. Avoid out-of-bounds reads. Avoid elements kind transitions. Prefer
arrays over array-like objects. Eat your vegetables. — this slide, just now
Thank you! @mathias