バックグラウンド
SpiderMonkeyバイトコードはJavaScriptエンジンで使用されることを公式に認められたコードの形式です。JavaScriptフロントエンドはソーステキストからASTを構築し、そしてJSScriptデータ構造の一部としてASTからスタックベースのバイトコードを生成します。バイトコードはJSSCriptデータ構造を含んでいるオブジェクトとアトムを(通常、配列のインデックスによって)参照できます。
エンジン内では全てのバイトコードはスタックフレーム内で実行され、大域的な(上位にある)数値を求めるコードであってもそれに関連づけたスタックフレームをもっています。スタック内のフレームはいくつかの異なるカテゴリーに分類される(タグバリュー形式の)JavaScriptの値を納めるアドレス空間(メモリ領域)を保持しています。一つのJavaScript値のための空間は"スロット"と呼ばれ、その分類として:
機能に関連づけたthis
のように呼び出しと戻り値の値を保持するいくつかのスロット領域があります。
スタックの最上位(TOS)領域の内容は常に、スタックに積まれる命令の最新の値に一致しています。全てのバイトコードは暗黙にこの位置に置かれで操作されます。
バイトコードリスト
全ての命令コード(opcode)は、実行時に開始から終了まで処理全体を通して使用するスタック領域の大きさに相当する数の[pop数、push数]に注解がついています。
命令コードに対するどのようなデータもバイトコード列の中では暗黙のものとして、命令コードのための決まり事として関数内の変数のような形式でリストされます。例えば、 JSOP_GOTO(uint16_t offset)
-
引数のスロット:現在のフレームに変数を渡すために実際の変数を保持します。
-
局所スロット:現在のコードで使用する内部変数を保持します。
-
命令スロット:スタック内で計算するための一時的なメモリ領域として保持されます。例えば、(a + b) + c という計算の中では、aをスタックにプッシュし、その後bをスタックにプッシュし、その後加算し、その後cをスタックにプッシュし、それから加算します。その計算では、最大で二つの命令スロットを必要とします。
- JSOP_NOP [-0, +0]
- 何も操作のないバイトコード。これは従来の使い方を踏襲し、TraceMonkey内でブラックリストループ(1命令コードを実行する時間だけ処理時間を消費する命令)として使用します。(FIXME)おそらく実装上はデコンパイラと関連しています。
- JSOP_PUSH [-0, +1]
-
スタックに不定値をプッシュします。
- JSOP_POPV [-1, +0]
- 現在の実行フレーム内の戻り値の場所にスタックの先頭の値をポップします。
- JSOP_ENTERWITH [-1, +1]
- スコープチェインのメンバー内のTOS(スタックの先頭)の値を変更します。値をポップし、新しいスコープチェインのオブジェクトをプッシュします。実際、新しいスコープチェインのオブジェクトがプッシュされた値を得るということは、ビット処理として危険なことです。それはエンジン固有の内部データ構造の一つであり、すべてのユーザデータがあるスタック上の終端になります。
- JSOP_LEAVEWITH [-1, +0]
- JSOP_ENTERWITHからTOS(スタックの先頭)を外し、スコープチェインオブジェクトをポップします。
- JSOP_RETURN [-1, +0, STOPS]
- TOSを戻り値のスロットにポップし、現在実行中のコードをその呼び出し元に戻します。
- JSOP_GOTO(int16_t offset) [-0, +0, JUMPS]
- 現在のバイトコードから16ビットオフセット値離れたバイトコードへジャンプします。
- JSOP_IFEQ(int16_t offset) [-1, +0, JUMPS]
- TOSから値をポップし、真偽値に変換します。そして、もし結果が偽であれば、現在のバイトコードから16ビットオフセット離れたバイトコードへジャンプします。この考え方は、戻り値を実行するシーケンスとして JSOP_ZERO, JSOP_ZERO, JSOP_EQ, JSOP_IFEQ, JSOP_RETURNのように、よくできた線形的なシーケンスのように命令を読み込みます。
- JSOP_IFNE(int16_t offset) [-1, +0, JUMPS]
- JSOP_IFEQと同様の命令ですが、TOSからポップした値が真であるときにジャンプします。
- JSOP_ARGUMENTS [-0, +1]
- 現在にフレーム内の(argumentsに一致する)引数オブジェクトをプッシュします。引数オブジェクトはゆっくりと遅く生成されます。
- JSOP_SWAP [-0, +0]
- スタック上の先頭の二つの値を交換します。ポストインクリメント/デクリメント処理のような処理に使いやすい機能です。
- JSOP_POPN(uint16_t N) [-N, +0]
- 単一の命令コード内のスタック上で上位N個の値をポップします。