Lock in $30 Savings on PRO—Offer Ends Soon! ⏳
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
1
190
V8 internals for JavaScript developers
Google Experts Summit 2017
Mathias Bynens
September 04, 2017
Tweet
Share
More Decks by Mathias Bynens
See All by Mathias Bynens
V8 internals for JavaScript developers @ Fronteers 2018
mathiasbynens
3
520
V8 internals for JavaScript developers
mathiasbynens
2
970
What’s new in ES2018?
mathiasbynens
2
160
Preventing timing attacks on the web @ Fronteers Jam 2016
mathiasbynens
4
270
Front-End Performance: The Dark Side @ ColdFront Conference 2016
mathiasbynens
1
460
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.1k
3.14 things I didn’t know about CSS @ CSS Day 2014
mathiasbynens
70
29k
Other Decks in Technology
See All in Technology
Reinforcement Fine-tuning 基礎〜実践まで
ch6noota
0
190
S3を正しく理解するための内部構造の読解
nrinetcom
PRO
2
170
たまに起きる外部サービスの障害に備えたり備えなかったりする話
egmc
0
260
re:Invent2025 3つの Frontier Agents を紹介 / introducing-3-frontier-agents
tomoki10
0
240
Strands Agents × インタリーブ思考 で変わるAIエージェント設計 / Strands Agents x Interleaved Thinking AI Agents
takanorig
2
230
業務のトイルをバスターせよ 〜AI時代の生存戦略〜
staka121
PRO
2
220
Sansanが実践する Platform EngineeringとSREの協創
sansantech
PRO
2
930
マイクロサービスへの5年間 ぶっちゃけ何をしてどうなったか
joker1007
15
6.6k
20251219 OpenIDファウンデーション・ジャパン紹介 / OpenID Foundation Japan Intro
oidfj
0
150
まだ間に合う! Agentic AI on AWSの現在地をやさしく一挙おさらい
minorun365
12
540
[デモです] NotebookLM で作ったスライドの例
kongmingstrap
0
160
AI 駆動開発勉強会 フロントエンド支部 #1 w/あずもば
1ftseabass
PRO
0
400
Featured
See All Featured
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Learning to Love Humans: Emotional Interface Design
aarron
274
41k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
122
21k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
5.8k
Making Projects Easy
brettharned
120
6.5k
VelocityConf: Rendering Performance Case Studies
addyosmani
333
24k
Speed Design
sergeychernyshev
33
1.4k
How to Ace a Technical Interview
jacobian
281
24k
Practical Orchestrator
shlominoach
190
11k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
1.8k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.3k
We Have a Design System, Now What?
morganepeng
54
7.9k
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