Mozilla HacksのCreating and working with WebAssembly modulesを読みました。WebAssemblyを、JavaScriptと競合するものではなく、JavaScriptから呼び出せる低レベルなmoduleとして説明する基礎記事です。
この記事で特に重要なのは、WebAssemblyを「特定CPU向けの機械語」ではなく、「概念機械向けの機械語」として説明している点です。x86やARMのような物理アーキテクチャを前提にせず、ブラウザが実行環境に合わせて実機の機械語へ変換できる中間地点に置かれています。
記事の要点
- WebAssemblyは、C/C++やRustなどJavaScript以外の言語をWebで使うための低レベルな実行形式です。
- JavaScriptを置き換えるものではなく、JavaScriptからWebAssembly moduleの関数を呼び出し、同じアプリケーション内で併用する前提で説明されています。
- CからWebAssemblyへ進む例では、Clang、LLVM IR、WebAssembly backend、Emscriptenといったツールチェーンが登場します。
.wasmはJavaScriptからWebAssembly.instantiateなどで読み込めます。現在のMDNではinstantiateStreamingやcompileStreamingも整理されています。- 複雑なデータ型をJavaScriptとWebAssemblyの間で渡す場合は、
WebAssembly.MemoryのArrayBufferを通じて、ポインタのように位置を渡す必要があります。 - WebAssemblyはstack machineとして説明され、命令は値をスタックに積み、演算が上から取り出す形で進みます。
.wasmmoduleは、Type、Function、Codeなどの必須sectionと、Import、Export、Memory、Table、Dataなどの任意sectionから構成されます。
参照リンクから見えたこと
MDNのWebAssemblyページでは、WebAssemblyは低レベルでコンパクトなバイナリ形式を持ち、C/C++、C#、Rustなどのコンパイルターゲットとして説明されています。この記事の時点では読み込み手順がまだ手作業寄りでしたが、現在のMDNではWebAssembly JavaScript APIや各種streaming APIも体系化されています。
WebAssembly text formatの解説も確認しました。バイナリの .wasm と、人間が読めるテキスト表現の対応を知ると、記事内で出てくるhex、binary、text representationの説明が見通しやすくなります。
コメント欄で触れられていたWebAssembly FAQも重要です。なぜLLVM bitcodeをそのまま配布形式にしないのか、という問いは、WebAssemblyが単なるコンパイラ内部表現ではなく、Webで長く安定して使うための実行形式として設計されていることを示しています。
気づき
今回の気づきは、WebAssembly moduleを理解するには「高速な別言語実行」より先に、「JavaScriptと低レベルコードの境界」を見る必要があることです。関数呼び出しは簡単に見えても、文字列や構造体を渡すにはMemoryを共有し、Export/Importで境界を設計する必要があります。この境界の設計が、後のWASIやRLBoxのような話にもつながっています。
