WebAssembly

WebAssemblyは仮想命令セットアーキテクチャあるいはプログラミング言語の一種である。略称はWasm。C・Rustなど様々なプログラミング言語のコンパイルターゲットとしてWasmバイナリは生成され、ウェブブラウザを含む様々な環境内のスタックベース仮想マシンにより実行される。
ネイティブコード相当の高速性・隔離環境でのメモリ安全な実行による安全性・仮想マシンによるハードウェア/プラットフォーム可搬性・ソースプログラミング言語中立性などを特徴とする。この命令セットはバイナリ形式で定義されており、またアセンブリ言語ライクなテキスト形式も定義されている（その意味で低水準プログラミング言語といえる）。
Wasm自体は命令セットアーキテクチャであり、Linuxカーネルが提供するようなシステムコール（例: ファイルI/O）、Webブラウザが提供するようなDOMアクセスなどを提供していない。上記の安全性や可搬性はこの特徴に由来している。それと同時に、WasmエコシステムとしてはシステムコールやDOMアクセスがAPIとして個別に定義されており、Wasmランタイムが実装することでそれらの機能を提供している（例: システムコールを提供するWASI）。シンプルでオープンなISAとランタイムごとのAPIを組み合わせることでWasmエコシステムは高い拡張性を有している。例えばWasmをHTTPプロキシでのフィルタスクリプトとして利用するプロジェクトが存在する。
仕様.
WebAssemblyはポータブルなスタックマシンであり、既存のウェブブラウザで広く用いられているJavaScriptと比べ、構文解析と実行が高速になるよう設計されている。WASM specification はWASMの言語仕様および実行ファイル形式を定義する。
言語.
Wasmは高水準のアセンブリ言語として設計されている。x64等のアセンブリ言語にみられない特徴として以下がある。
値型.
値に定義される型は codice_7 / codice_8 / codice_9 / codice_10 の4種類である。char/stringは型としてサポートされない。また、高級言語のように関数が構造体型を取り回すようなコードが直接的には記述できない。
入出力.
デフォルトでは外部と隔離されている（サンドボックス）。計算結果を渡したり外部関数を呼び出したりするために、WASMは "imports"/"exports" 機能を提供する。対象となるオブジェクトは関数・テーブル・メモリ・グローバル変数の4種類。"exports"要素に対象のインデックスを登録することで、WASM外からそのオブジェクトへアクセスできる（関数呼び出しやメモリ読み書き）。またimports要素に対象の名前と型を登録することで、WASM外に存在する対象へのアクセスをWASMランタイムが提供する。
フォーマット.
Wasmはバイナリフォーマット（）およびテキストフォーマット（）を定義している。フォーマットの設計方針として "Compact" / "Modular" / "Efficient" / "Streamable" / "Parallelizable" / "Portable" を掲げている。
言語のバイナリ/テキスト表現（例: オペコード）に加え、実行ファイル形式（コンテナフォーマット）を定義する。"module" が1つの実行ファイルに相当し、マジックナンバー等のメタ情報が冒頭に記述され、関数やexportsなど11種類のセクションが続く。セクションはサイズ情報を持っており、並行処理可能に設計されている。
以下に、C言語のソースコードが、wasmのリニアアセンブリバイトコードとバイナリにそれぞれ変換された例を示す。
内部的には、wasmコンパイラシステムは中間コードを扱うためにS式を使用している。サンプルを以下に示す。
(module
 (memory 256 256)
 (export "memory" memory)
 (type $FUNCSIG$dd (func (param f64) (result f64)))
 (import $exp "global.Math" "exp" (param f64) (result f64))
 (export "doubleExp" $doubleExp)
 (func $doubleExp (param $0 f64) (result f64)
 (f64.mul
 (call_import $exp
 (get_local $0)
 (f64.const 2)
 )
機能.
ベクトル演算.
WASMは128ビット幅のベクトル型（codice_11）をもち、ベクトル命令（）すなわちSIMD命令を定義している。WASM SIMDはChromiumでサポートされている。
連携.
Wasmはホスト環境に埋め込まれるサンドボックスであり、import/exportを介したホストとの連携によって意味ある結果が得られる。WasmがシンプルなVMである反面として、Wasm-ホスト間の連携にはいくつかのテクニックが必要となる。また各moduleが1つのサンドボックスとして働くため、Wasmモジュール間の連携にも同様のことが言える。
基本的な問題として、Wasm-ホスト間の型システム不一致解消（マーシャリング）を取り扱うことになる。
文字列.
char/stringは型としてサポートされない。Wasm上で扱うためにはcharをintとして操作し、線形メモリ上にchar配列を構築する形になる。export関数も数値型しか返せないため、stringの表現として線形メモリのオフセットと長さを返し（intなので返せる）これに基づきランタイム側で該当メモリ区間を文字列型として読む、といった工夫が必要となる。あるいはmalloc等の外部アロケータをimportした上で線形メモリの内容を外部メモリへ割り当て、そのアドレス・参照をintでランタイムへ返す必要がある。
ツール.
ランタイム.
仮想マシンの命令セットであるWASMはコンピュータの実行ファイルではないため、そのまま機械語として実行はできない。そのためWASMファイルはランタイムを介し解釈・実行される。ランタイムにはインタプリタ/JITコンパイラ/AOTコンパイラがあり用途に合わせて選択される。
ランタイムはウェブブラウザへの組み込み（JavaScript実行環境からの呼び出し）や独立したWASMネイティブランタイム (例: CLIにおける codice_12) として存在する。
かつて存在したランタイムにはCraneliftコンパイラベースのLucetがある。
歴史.
WebAssemblyサポートの初期実装は、既存のとPNaClをベースとしている。
WebAssemblyの最初のアナウンスは2015年6月17日に行われ、2016年3月15日には主要ブラウザ (Firefox, Chromium, Google Chrome, Microsoft Edge) 上でUnityによるAngry Botsというデモが行われた。
最初の目標としてCとC++からのコンパイルをサポートすることを目指し、Rustがバージョン1.14以降で、Goがバージョン1.11以降で、Kotlin/Nativeがバージョン0.4以降で<ref name="Kotlin/Native"></ref>で対応するなど、他のプログラミング言語のサポートも進められた。
2017年3月7日には、WebAssemblyに標準対応した初のブラウザとなるFirefox 52.0がリリースされた。2017年11月、MozillaはSafariとEdgeがWebAssemblyに対応したと発表し、すでに対応しているChromeとFirefoxを含め、主要なブラウザすべてでサポートされることになった。
2019-12-05にはW3C勧告「WebAssembly Core Specification」が策定され、WebAssemblyは正式なウェブ標準に認定された。
ガベージコレクション (GC) の対応を行い、JavaやC#といったGCを持つ言語をサポート対象に加えることが計画されている。
WebAssemblyの開発はMozilla、マイクロソフト、Google、Appleといった主要ブラウザの開発者により行われている。