世界を動かす技術を、日本語で。

WASM 3.0 完了

概要

  • Wasm 3.0 のリリース発表
  • 64ビットアドレス空間 や複数メモリ、ガーベジコレクションなど大規模な新機能追加
  • 例外処理型付き参照テイルコール など多言語対応強化
  • 決定論的プロファイルカスタムアノテーション による柔軟性向上
  • 主要ブラウザや Wasmtime などでのサポート進行中

Wasm 3.0の新機能概要

  • 64ビットアドレス空間 ・メモリやテーブルで i64アドレスタイプ 利用可能 ・理論上 16エクサバイト まで拡張可能 ・Web上では 16GB 制限、非Web環境で大規模アプリ・データセット対応

  • 複数メモリ対応 ・単一モジュールで 複数メモリ の宣言と直接アクセスが可能 ・モジュール間のデータコピーや 静的リンク ツール(wasm-merge等)への対応 ・セキュリティやバッファリング、計測用の分離アドレス空間活用

  • ガーベジコレクション(GC)Wasmランタイム による自動メモリ管理領域の追加 ・ struct型・array型・タグ付き整数 でメモリレイアウト宣言 ・オブジェクトシステムやクロージャ等の高レベル機能は未搭載 ・各言語のコンパイラが独自にデータ表現設計

  • 型付き参照参照型の拡張 でヒープ値の正確な型記述が可能 ・ランタイムチェック不要な安全性確保 ・ 関数参照 にも適用、 call_ref命令 で安全な間接呼び出し実現 ・ サブタイピング型再帰 もサポート

  • テイルコール ・関数呼び出し時に スタック消費を抑制 ・静的/動的な呼び出し両方に対応 ・関数型言語や内部処理技法への最適化

  • 例外処理ネイティブ例外処理 の導入 ・例外タグとペイロードデータで定義 ・例外のスローとタグによる選択的キャッチ ・ catch-all やタグ/ラベルペアによる分岐制御

  • リラックスドベクター命令SIMD命令 のパフォーマンス向上目的 ・一部動作を 実装依存 で許容 ・許可された選択肢から挙動を選択

  • 決定論的プロファイル非決定論的命令 (浮動小数点演算やリラックスドベクター命令等)に 標準動作 を規定 ・ ブロックチェーン やリプレイ可能システム等での 完全な決定論的実行 を保証 ・プラットフォーム間の再現性・移植性向上

  • カスタムアノテーション構文 ・Wasmテキストフォーマットで 注釈記法 追加 ・バイナリのカスタムセクション相当の情報を 人間可読・編集可能 に ・標準自体は意味付与せず、下流標準で具体化可能

JavaScriptとの連携強化

  • JS string builtins拡張 ・JavaScriptのstring値を externref としてWasmに渡す機能強化 ・新しいプリミティブライブラリの関数で Wasm内から直接文字列操作 が可能

多言語対応とエコシステム発展

  • 高レベル言語対応強化 ・Java、OCaml、Scala、Kotlin、Scheme、Dart等が GC機能 を活用 ・新しい言語のWasmターゲット化が加速

  • SpecTecツールチェーン での標準策定 ・より 信頼性の高い仕様 文書化を実現

  • 主要ブラウザWasmtime 等スタンドアロンエンジンでのサポート進行 ・ Wasm feature status page で各エンジンの対応状況を追跡可能


Wasm 3.0の意義と今後

  • 大規模アプリケーション多様な言語 のWasm対応促進
  • パフォーマンス安全性柔軟性 の向上
  • 標準仕様の進化 によるWeb外での利用拡大
  • 開発者・エンジン実装者 への新たな可能性

Hackerたちの意見

ガーベジコレクション。生のリニアメモリの機能を拡張するだけでなく、Wasmはガーベジコレクタを介してWasmランタイムによって自動的に管理される新しい(別の)ストレージ形式のサポートも追加します。Wasmが低レベル言語であるという精神を守りつつ、Wasm GCも低レベルです。Wasmをターゲットにしたコンパイラは、構造体や配列型、さらにアンボックスされたタグ付き整数のメモリレイアウトを宣言でき、その割り当てとライフタイムはWasmが処理します。でも、それだけです。すごい!

64ビットが仕様のデフォルト部分になるのはめっちゃ楽しみ!多くのウェブアプリがこれによって制限されてるから、特にオンラインの動画編集ツールなんかはね。Figmaでも32ビットの制限があって、いろいろと制約があるのが見える。気になるのは、モバイルデバイスがタブごとのアドレス可能メモリ制限をそのまま維持するのかどうか。これは32ビット空間に結びついているというより、OSによって定義されることが多いからね。

残念ながら、Memory64はかなりのパフォーマンスペナルティがあるんだ。なぜなら、wasmランタイムが境界をチェックしなきゃいけないから(32ビットの時は、ランタイムが毎回4GBのアドレス空間を全て割り当ててたから必要なかった)。でも、4GB以上のメモリが本当に必要なら、使ってもいいよ。

ウェブの制限が具体的に16GBになっているのには技術的な理由があるの?それとも、単に標準化のために選ばれた丸い数字なのかな?それに、JSのヒープサイズ(およびArrayBufferサイズ)の制限も16GBに緩和されたの?それともまだ低いまま?

コンポーネントモデルの作業(https://component-model.bytecodealliance.org/)は、3.0リリースに何か関係あるの?

いや、コンポーネントモデルの提案はWasm 3.0のリリースには含まれていないよ。提案がWasmのポイントリリースに入るのは、ステージ5に達したときだけだから、コンポーネントモデルはまだ開発中で、フェーズを進めようとはしていないんだ。Wasm 3.0に含まれた提案とは違って、コンポーネントモデルはコアWasmモジュールのエンコーディングやその意味に変更を加えない。代わりに、コアWasmモジュールを含む新しいエンコーディングコンテナとして設計されていて、各モジュールのインターフェースタイプや、それらのモジュールをインスタンス化してリンクする方法を説明する追加情報を加えている。これらの追加をコアWasmの外に置くことで、どんな古いWasmエンジンでも実装を構築できるし、モジュールをインスタンス化してリンクするための追加コードや、コアWasm ABIから高レベルのインターフェースタイプへの変換もできる。Jcoプロジェクトは、すべてのウェブエンジンのWasm実装で使われる共通のJSインターフェースを使って、まさにそれを実現しているよ。だから、ウェブエンジンが自分たちで作業をする必要なく、ウェブ上でコンポーネントモデルを提供できるんだ。コアWasmに変更を加える提案ではそれは不可能なんだけどね。

AssemblyScriptがWASM GCに移行するきっかけになればいいなと思ってる: https://github.com/AssemblyScript/assemblyscript/issues/2808 そこにはポリフィルを待っているコメントもあるけど、GCサポートは広く普及しているから、主要バージョンでは非GCランタイムのサポートをやめてもいいんじゃないかな。

gcについて:> Wasm GCも低レベルです。Wasmをターゲットにしたコンパイラは、構造体や配列型、さらにアンボックスされたタグ付き整数のメモリレイアウトを宣言でき、その割り当てとライフタイムはWasmが処理します。Wasmについてはすでに多くの誤解があるし、「GCをサポートしてるから、PythonやJava、C#、Goなどをエクスポートできる」と言う人が出てくるのが心配。これは魔法の解決策じゃないよ。CppやRustがまだ主流になると思う。WASMのGC機能に頼るには、WASMを生成するコンパイラの抽象化に基づいたコードを書く必要がある。

WASMにおけるGCの目的は、そんな高レベル言語をWASM内に置くために、重いランタイムを必要としないことだと思ってたんだけど、もしそうでないならWASM GCの価値は何なの?

KotlinのWasmコンパイラは、基本的にWasmのGCサポートの上に構築されているんだ。まあまあうまく動いてるよ。私の理解では、基本的には通常のJavaScriptでも使われているのと同じガーベジコレクタだね。 > これは銀の弾丸ではないよ。CppやRustがやっぱり主流になると思う。もうそれは必ずしも真実ではないと思うけど。だけど、君が言うように、使うコンパイラやそれがどれだけうまく活用されるかによるね。JetbrainsはKotlinとWasmに大きな計画を持っていて、例えばCompose Multiplatformがすでにそれをサポートしているよ(iOSネイティブやAndroidも含めて)。

Wasm-GCはコンパイラ作成者向けの抽象化で、GC依存の言語が既にGCされたブラウザ/Wasmヒープの中でGCを持たずに動作できるようにするものなんだ。だから、JavaやC#などはより良く動くよ(今のC#のWASMエクスポートが生成するひどい混乱を見れば、基本的に内部プラットフォームにGCを含んでるからね)。でも、明確に「javascript」オブジェクトとはやり取りしないよ(JSオブジェクトへの参照は持てるけど、JSメソッドを直接呼ぶことはできない)。

例えばDartでは全然違うよ。DartはWASM-GC言語だからね。Dartの一番の売りは、一度コードを書けばどこでも動くってこと。WASMはx64やRISC-V、iOSと同じようなコンパイルターゲットの一つなんだ。

まだここでは言及されていないけど、複数メモリ機能がWebGPUリソースをマッピングする際に現在必要な余分なコピーを回避できるかどうか気になる。このマッピングは別のArrayBufferオブジェクトにあり、WASMからはJSを呼び出してArrayBufferからWASMヒープにコピーして戻す必要がある。複数のWASMメモリとClang/LLVMのアドレス空間機能がその問題を解決できそうだけど、実際にそれが簡単かどうかは分からないな…

なんか全体的にひどいセグメンテーションとファーポインタの雰囲気が漂ってる。今、クラシックなゲームボーイのゲームを作って遊んでるから、メモリマッピングをいじるのが「楽しみ」の一部なんだけど、制約のないものには嫌だな。ファーポインタはDOSとWin16で埋めた理由があるからね。

ツールチェーンのサポートについての議論があったけど(https://github.com/WebAssembly/multi-memory/issues/45)、まだLLVMでWasmマルチメモリをサポートするために複数のアドレス空間を使うステップがあったかはわからないな。

まだDOMについての言及はないね。WASM 4.0で会おう!

同じことを願ってるよ、お願いだからWasmチーム、DOM操作の機能を統合するための最善の方法を探ってくれるなら、3年待つのも全然構わないよ。時々、JSは魔法みたいすぎると感じるから、普通の退屈なGolangを使って、htmxを使わずにDOM関数を書きたいんだ。もっと自由をください!これが一番リクエストされている機能かもしれないし、これがきっかけでWasmを知ったんだ(多分、あるYouTuberのLeptosの動画だったと思う、ごめん、忘れちゃったかも)。

これに関してRustツールチェーンを侮らないで!今すぐWasm経由でDOMを使えるよ、ツールがすべての接続部分を生成してくれるし、オーバーヘッドもそんなに悪くないから。

https://danfabulich.medium.com/webassembly-wont-get-direct-d...

またその古い話か ;) 直接DOMにアクセスするのはWASMの機能としては意味がないよ。せいぜい、ブラウザベンダーがWASMの外で実装する必要があるウェブブラウザの機能になるだけだ(DOM JS APIにマッピングする標準化されたC-APIを定義して、そのC APIを関数インポートテーブルを通じてWASMに直接公開する必要があるけど、そのアイデアは理論上は悪いとは思えないけど、実際にはその通りだよ)。DOMを操作する必要があるなら、JSでやればいいんだ。WASMからJSを呼び出すのは安価だし、JSも意外と速いよ。ただし、JSコードには十分な「肉」があることを確認してね。例えば、すべてのDOMメソッド呼び出しやプロパティ変更のたびにWASM/JSの境界を越えて呼び出さないように。呼び出し自体は速いけど、WASMヒープ上のソース言語特有の文字列表現からJS文字列への文字列変換は無料じゃないからね(この文字列のマージをなくすことが「ネイティブ」WASM DOM APIの唯一の理論上の利点になるだろう)。

DOMはWASMの一部じゃなくて、ホストの一部になるんだよね。もしWASMネイティブのDOM APIができたら、WASMのGCがそれにかなり役立つはず。

Wasm-GC仕様からも明確に否定されてるし、セキュリティの問題が多すぎて、ブラウザメーカーは「触りたくない」って感じで固まってるんだよね。

僕はシンプルな男で、シンプルなニーズがあるんだ。Goの構造体をランタイムに出入りさせるための、もっと良くて速い方法が欲しいんだ。厚手のニットウールの靴下を履いてパーケットフロアで剣の舞をする必要がない方法がいいな。もしもっと多くの言語に対応するソリューションがあれば、最高だね。主にGoのためにこれが欲しいんだ。もしそれがある程度の「合理的な」制限を意味するなら、それも全然構わないよ。

最近のWASMの開発はあんまり追ってなかったから、WASMがバージョン管理されたリリースモデルに移行したことに気づかなかったよ。開発中のいろんな機能には気づいてたけど、最近の機能はオプションのままだと思ってた。でも、実装がすべての機能をサポートしないと「WASM 3.0」との互換性を主張できないってことなのかな?次に3.0を完全にサポートする非ブラウザベースのWASMランタイムは何になるか、楽しみだね(個人的にはwasmtimeが最初だと思ってるけど、Denoはv8を使ってるからカウントしない)。ガベージコレクションは特に難しい機能みたいだし。3.0のリリースが以前発表された「エバーグリーン」リリースモデルにどう関わるのか、誰か知ってる?

「2.0の登場により、作業グループは今後のリリースのためにいわゆる“エバーグリーン”モデルに切り替えています。つまり、言語の新しいバージョンを作成する際に、候補勧告がその場で更新され、技術的には最終勧告状態に移行することはありません。実質的には、最新の候補勧告草案が現在の標準と見なされ、コミュニティグループと作業グループの合意を表しています。」