WebAssemblyのRuntime Structureを思い出す

一回インタプリタを作ったんですが、結構前なので忘れてるんですよね。というわけで仕様を再確認します。

WebAssemblyのVMはスタックマシンで、内部は大きくStoreStackの2つに分かれます。

The store represents all global state that can be manipulated by WebAssembly programs.

ということで、storeは関数、テーブル(関数ポインタを持っていると思ってください)、線形メモリ、グローバル変数など、全域的な状態を保持しています。stackはもちろん読んで字の如し、スタックなんですが、種類としてはさらに以下の3つに分かれます。

Values: the operands of instructions. Labels: active structured control instructions that can be targeted by branches. Activations: the call frames of active function calls.

Valueは通常の即値のことでi32 i64 f32 f64の4種類。Labelは、一言で言うとジャンプ先の目印のことで、ループなどのブロック構造からの脱出先になったりします。というかプログラミング言語でも使えるものも多いですよね。最後のActivationはいわゆる関数のローカル変数などを持つcall frameのことです。ちなみに、仕様上、WebAssemblyはこれらの実装方法にまでは踏み込んでいません。つまり、これらを同一のスタックで実現してもいいし、種類ごとに3つに分けても構いません。

もう一つ、重要な構造としてはモジュールインスタンスがあります。

A module instance is the runtime representation of a module. It is created by instantiating a module, and collects runtime representations of all entities that are imported, defined, or exported by the module.

これはモジュールを初期化すると出来上がるもので、上記Storeが持っている内容へのポインタを所持しています。Storeにない情報としてはexport instanceがあって、ここにはexportしている要素(関数やグローバル変数)の情報が入っています。

たぶん、一読して難しいのはStoreとモジュールインスタンスの違いではないかと思います。鍵は、モジュールはimportやexportが可能であり、複数のモジュールで定義された要素がVMに入る可能性がある、ということだと思います。言い換えれば、Storeは各要素の、VM上で扱う全ての実体を持っていている一方、モジュールインスタンスはあくまでも1つのモジュールに関する情報をStore内要素へのポインタとして保持している、ということです。