
V8コンパイルパイプライン

点火! スタート! Ignitionインタープリターは、その名前を「点火」と翻訳することができ、2016年からV8コンパイルパイプラインの一部となっています。
V8がJavaScriptコードをコンパイルすると、パーサーは抽象構文ツリーを生成します。 構文ツリーは、JSコードの構文構造のツリービューです。 Ignitionインタープリターは、このデータ構造からバイトコードを生成します。 最適化TurboFanコンパイラは、最終的にバイトコードから最適化されたマシンコードを生成します。

V8コンパイルパイプライン
V8に2つの実行モードがある理由を知りたい場合は、JSConfEUでの私のパフォーマンスを見てください。
V8バイトコードの基本
バイトコードはマシンコードの抽象化です 。 バイトコードが物理プロセッサで使用されているのと同じ計算モデルを使用して設計されている場合、バイトコードをマシンコードにコンパイルするのは簡単です。 そのため、通訳者はしばしばマシンを登録またはスタックします。
Ignitionインタープリターは、累積レジスターを持つレジスターマシンです。

左のコードは人々にとって便利です。 右側のコード-車用
V8バイトコードは、JavaScript機能を実装できる小さなビルディングブロックと考えることができます。 V8には数百のバイトコードがあります。
Add
や
TypeOf
などのステートメント、または
LdaNamedProperty
などのプロパティをロードするためのコードがあります。 V8には、
CreateObjectLiteral
や
SuspendGenerator
など、かなり具体的なバイトコードもあります。 bytecodes.hヘッダーファイルには、V8バイトコードの完全なリストがあります。
各バイトコードは、入力および出力データをレジスタオペランドとして定義します。 Ignitionは、レジスター
r0, r1, r2, ...
、および累積レジスターを使用します。 ほとんどすべてのバイトコードはストレージレジスタを使用します。 通常の場合と似ていますが、バイトコードで明示的に示されていない点が異なります。 たとえば、
Add r1
コマンドは、レジスタ
r1
値を累積レジスタに格納されている値に追加します。 これにより、バイトコードが短くなり、メモリが節約されます。
多くのバイトコード名は
Lda
または
Sta
始まります。
Lda
および
Sta
の文字
a
は、累積器(累積レジスタ)の略語です。
たとえば、
LdaSmi [42]
コマンド
LdaSmi [42]
は、小さな整数(Small Integer、Smi)
42
を累積レジスタにロードします。
Star r0
コマンドは、累算レジスタにある値を
r0
レジスタに書き込みます。
機能バイトコード分析
ここで、基本的な概念を検討した後、実際の関数のバイトコードを見てみましょう。
function incrementX(obj) { return 1 + obj.x; } incrementX({x: 42}); // V8 , , ,
JavaScriptコードのバイトコードを表示したい場合は、
--print-bytecode
フラグを指定してD8またはNode.js デバッガー (バージョン8.3以降)を呼び出して表示できます。 Chromeの場合、コマンドラインからキー
--js-flags="--print-bytecode"
ます。 これがChromiumのキーコールです 。
$ node --print-bytecode incrementX.js ... [generating bytecode for function: incrementX] Parameter count 2 Frame size 8 12 E> 0x2ddf8802cf6e @ StackCheck 19 S> 0x2ddf8802cf6f @ LdaSmi [1] 0x2ddf8802cf71 @ Star r0 34 E> 0x2ddf8802cf73 @ LdaNamedProperty a0, [0], [4] 28 E> 0x2ddf8802cf77 @ Add r0, [6] 36 S> 0x2ddf8802cf7a @ Return Constant pool (size = 1) 0x2ddf8802cf21: [FixedArray] in OldSpace - map = 0x2ddfb2d02309 <Map(HOLEY_ELEMENTS)> - length: 1 0: 0x2ddf8db91611 <String[1]: x> Handler Table (size = 16)
バイトコードに焦点を当てて、このデータのかなりの部分を無視できます。 ここに表示される内容の説明を示します。
LdaSmi [1]
LdaSmi [1]
コマンドは、定数
1
を累積レジスタにロードします。

スターr0
Star r0
コマンドは、累積レジスタの値、つまり
1
を
r0
レジスタに書き込みます。

LdaNamedProperty a0、[0]、[4]
LdaNamedProperty
コマンドは、名前付きプロパティ
a0
を累積レジスターにロードします。
ai
コンストラクトは、
incrementX()
関数のi番目の引数を参照し
incrementX()
。 この例では、
a0
の名前付きプロパティ、つまり
incrementX()
最初の引数にアクセスします。 名前は定数
0
によって決定され
0
。
LdaNamedProperty
は
0
を使用して、別のテーブルで名前を検索します。
- length: 1 0: 0x2ddf8db91611 <String[1]: x>
ここで
0
x
マッピングされます。 その結果、このバイトコードが
obj.x
ロードすることが
obj.x
4
オペランドは何に使用されますか? これは、
increment(x)
いわゆるフィードバックベクトルのインデックスです。 フィードバックベクトルには、パフォーマンスを最適化するために使用されるランタイム情報が含まれています。
現在、レジスタの内容は次のとおりです。

r0を追加、[6]
最後の命令は
r0
の内容を累積レジスタに追加し、最終的な値は
43
ます。 番号
6 —
、フィードバックベクトルの別のインデックスです。

戻る
Return
コマンドは、累積レジスタの内容を返します。 これは、
incrementX()
関数の完了です。
incrementX()
原因は、累積レジスタの番号
43
から始まり、この値でいくつかのアクションを実行し続けることができます。
この素材が専用のバイトコードは、V8バージョン6.2、Chrome 62、およびまだリリースされていないノード9で使用されていることに注意してください。 V8の他のバージョンでは、ここで説明したものとバイトコードにいくつかの違いがある場合があります。
まとめ
一見すると、V8バイトコードは、特に大量の追加情報が表示されている場合は、かなりわかりにくいように見えます。 ただし、Ignitionが累積レジスタを持つレジスタマシンであることがわかると、ほとんどのバイトコードの目的を理解できます。
親愛なる読者! JSプログラムのバイトコードを分析する予定ですか?