GraalWasm

GraalWasmはオープンソースのWebAssemblyランタイムです。バイナリ形式のWebAssemblyプログラムを実行し、JavaアプリケーションにWebAssemblyモジュールを埋め込み、活用するために使用できます。GraalWasmは現在も開発中で、多くのWebAssembly拡張機能に対応しています。

WebAssemblyモジュールシステム #

GraalWasmを使用すると、アプリケーションにWebAssemblyモジュールをロードし、Javaからアクセスし、他のGraal言語と相互運用させることができます。GraalWasmを効率的に使用するには、まずGraalWasmがWebAssemblyのモジュールシステムをPolyglot APIにどのようにマッピングするかを理解することが重要です。

GraalWasmは、WebAssemblyモジュールのバイナリ形式をその言語として使用します。GraalWasmを使用して評価できる有効なSourceは、常にバイナリ形式の単一のWebAssemblyモジュールです。

WebAssembly Sourceを構築する方法は次のとおりです。

Source source = Source.newBuilder("wasm", new File("example.wasm")).name("example").build();

WebAssembly Sourceを評価すると、モジュールが解析および検証され、モジュールインスタンスが結果の値として返されます。モジュールインスタンスは、後でトップレベルのバインディングからも取得できます。トップレベルスコープ内のバインディングの名前は、評価されたSourceの名前と同じです。

// Evaluate the Source named "example".
Value exampleModule = context.eval(source);
// It is now accessible under the binding name "example".
assert context.getBindings("wasm").getMember("example") == exampleModule;

Source名はGraalWasmで重要です。モジュールのインポートを解決するためにも使用されるためです。モジュールがモジュールfooからシンボルをインポートしようとすると、GraalWasmはそのシンボルを、Sourcefooと名付けられたモジュール内で検索します。これらのインポートは、WebAssemblyモジュールインスタンスのメンバーが特定のコンテキストで初めてアクセスまたは実行されるまで解決されません。

モジュールインスタンスオブジェクト #

Polyglot APIを介してWebAssemblyモジュールを評価することにより、モジュールインスタンスオブジェクトにアクセスできます。モジュールインスタンスオブジェクトは、WebAssemblyモジュールからエクスポートされたすべてのシンボルに対してメンバーを公開します。getMemberKeysを使用してエクスポートされたすべてのシンボルのリストを取得し、getMemberを使用して個々のエクスポートにアクセスし、変更可能なグローバル変数の場合は、putMemberを使用してその値を設定できます。

さまざまな種類のWebAssemblyエクスポートがPolyglot値にマップされる方法を次に示します。

  • 関数

    関数は実行可能な値としてエクスポートされ、executeを使用して呼び出すことができます。関数引数と戻り値は、型マッピングを使用してWebAssembly値型とPolyglot値の間でマッピングされます。関数が複数の値を返す場合、それらはInterop配列にラップされます。

  • グローバル変数

    getMemberを使用してエクスポートされたグローバル変数にアクセスすると、型マッピングを使用してマッピングされたグローバル変数の値が取得されます。グローバル変数が変更可能な場合、putMemberを使用してその値を更新することもできます。現在、グローバル変数の設定は、数値型に対してのみ機能し、その値は型マッピングに従ってマッピングされます。

  • メモリ

    エクスポートされたメモリは、配列インターフェースとバッファーインターフェースの両方を実装します。配列インターフェースを使用すると、getArrayElementsetArrayElementを使用して、メモリをバイトの配列として表示できます。バッファーインターフェースを使用すると、readBufferを使用してメモリのバルクコピーを実行し、readBuffer*メソッドとwriteBuffer*メソッドを使用して、Javaプリミティブ型をメモリとの間で読み書きできます。

  • テーブル

    エクスポートされたテーブルは不透明であり、クエリまたは変更できません。

型マッピング #

WebAssembly値が関数呼び出し、戻り値、またはエクスポートされたグローバル変数アクセスを介してJavaコードまたは別のGraal言語に渡されるたびに、Polyglot値にマッピングされます。以下の表は、このマッピングがどのように機能するかを示しています。WebAssemblyは静的に型付けされた言語であり、すべての値(ローカル変数、関数引数、戻り値)には静的型があります。この型に基づいて、GraalWasmはPolyglot値をこの型の値として解釈するか、型が一致しない場合は型エラーを報告します。

Polyglot値としてのWebAssembly値 #

この表では、各WebAssembly値型について、結果の値が実装するPolyglotインターフェースについて説明します。

WebAssembly型 Polyglotインターフェース
i32 intに収まる数値
i64 longに収まる数値
f32 floatに収まる数値
f64 doubleに収まる数値
v128 16バイトの読み取り専用バッファー
funcref 実行可能オブジェクト
externref そのまま返される

WebAssembly関数への引数の渡し #

エクスポートされたWebAssembly関数を呼び出す場合、その正確な型シグネチャを尊重する必要があります。以下の表は、可能なすべてのWebAssemblyパラメーター型に対する期待される引数型を示しています。

WebAssemblyパラメーター型 期待される引数型
i32 int
i64 long
f32 float
f64 double
v128 WebAssemblyから受信した既存のv128
funcref WebAssemblyのref.nullまたはエクスポートされたWebAssembly関数
externref 何でもかまいません(WebAssemblyのref.nullのみがref.is_nullによってnullとして認識されます)

オプション #

GraalWasmはいくつかのオプションで構成できます。Polyglot APIを使用する場合、オプションはプログラムによってContextオブジェクトに渡されます。

Context.newBuilder("wasm").option("wasm.Builtins", "wasi_snapshot_preview1").build();

オプションをプログラムで設定する方法の詳細については、Polyglotプログラミングリファレンスを参照してください。

使用可能なオプションは、安定したオプションと実験的なオプションに分けられます。実験的なオプションは、将来のサポートを保証するものではなく、バージョンごとに変更される可能性があります。実験的なオプションをwasmランチャーで使用する場合、--experimental-optionsオプションを指定する必要があります。Contextを使用する場合、Context.BuilderallowExperimentalOptions(true)メソッドを呼び出す必要があります。

安定したオプション #

次の安定したオプションが提供されています。

  • --wasm.Builtins: 一部のGraalWasm提供の組み込みモジュールを公開します。値の構文は[<linkingName>:]<builtinModuleName>,[<linkingName>:]<builtinModuleName>,...です。要求されたモジュールはコンマで区切られます。各モジュールには、オプションでコロンで区切られたリンキング名を付けることができます。リンキング名が指定されている場合、モジュールはそのリンキング名でエクスポートされます。そうでない場合、モジュールは組み込みモジュール名でエクスポートされます。

    提供されている組み込みモジュールは次のとおりです。

  • --wasm.WasiMapDirs: WebAssemblyシステムインターフェースAPIを介してアクセスできる、事前に開かれたディレクトリのリスト。値の構文は[<virtualDir>::]<hostDir>,[<virtualDir>::]<hostDir>,...です。事前に開かれたディレクトリはコンマで区切られます。各ディレクトリには、オプションでダブルコロンで区切られた仮想パスを付けることができます。WebAssemblyモジュール内では、ディレクトリは仮想パスで使用できます。仮想パスが省略されている場合、事前に開かれたディレクトリはホストファイルシステムと同じパスにあります。

    このオプションを設定して、WASIを使用するモジュールがファイルシステムにアクセスできるようにする必要があります。アクセスは、これらの事前に開かれたディレクトリのコンテンツに対してのみ許可されます。

実験的なオプション #

これらのオプションは実験的なものであり、将来維持またはサポートされる保証がないことに注意してください。これらを使用するには、--experimental-optionsオプションが必要であるか、Contextで実験的なオプションを有効にする必要があります(上記を参照)。

以下のオプションは、WebAssembly標準に新しい機能を追加する機能提案に対応しています。許容される値は、機能を有効にする場合はtrue、機能を無効にする場合はfalseです。WebAssembly仕様に既にマージされている機能は、GraalWasmではデフォルトで有効になっています。まだ仕様にマージされていない機能は、デフォルトで無効になっています。ユーザーはデフォルトをオーバーライドして、今後の機能を試したり、標準化された機能をオプトアウトしたりできます。

  • --wasm.BulkMemoryAndRefTypes: バルクメモリ操作機能参照型機能のサポートを有効にし、効率的なメモリ初期化のための命令を公開し、ファーストクラスの不透明参照のサポートを追加します。デフォルトはtrueです。

  • --wasm.ExtendedConstExpressions: 拡張定数式機能のサポートを有効にし、定数式内の算術命令を限定的にサポートします。デフォルトはfalseです。

  • --wasm.Memory64: Memory64機能のサポートを有効にし、メモリを4GiBより大きくすることができます。デフォルトはfalseです。

  • --wasm.MultiMemory: 複数メモリ機能のサポートを有効にし、モジュールが複数のメモリを持つことを許可します。デフォルトはfalseです。

  • --wasm.MultiValue: 複数値機能のサポートを有効にし、関数が複数の値を返すことを許可します。デフォルトはtrueです。

  • --wasm.SaturatingFloatToInt: 非トラッピング浮動小数点数から整数への変換機能のサポートを有効にし、トラップで失敗する代わりに飽和する浮動小数点数から整数への変換命令を追加します。デフォルトはtrueです。

  • --wasm.SignExtensionOps: 符号拡張演算子機能のサポートを有効にし、符号付き整数の値を拡張するための命令を追加します。デフォルトはtrueです。

  • --wasm.SIMD: 固定幅SIMD機能(仕様はこちら)のサポートを有効にします。新しい値型v128と、SIMD演算のための関連命令が導入されます。デフォルトはtrueです。

  • --wasm.Threads: スレッド機能(概要はこちら)のサポートを有効にします。WebAssemblyモジュールは、アトミックメモリアクセスのための新しい命令を使用できるようになります。デフォルトはfalseです。

GraalWasmランチャーの使用 #

GraalWasmスタンドアロンは、wasmランチャーを提供します。これを使用して、WebAssemblyバイナリモジュールとしてコンパイルされたプログラムを実行できます。

wasm [OPTION...] [--entry-point=FN] FILE [ARG...]
  • [OPTION...]

    オプションには、--wasm.で始まるGraalWasmエンジンオプション(例:--wasm.WasiMapDirs=preopened-dir)と、その他のポリグロットエンジンオプションが含まれます。wasmランチャーを使用する場合、--wasm.Builtins=wasi_snapshot_preview1オプションはデフォルトで設定されているため、WebAssembly System Interface Snapshot Preview 1に対してコンパイルされたモジュールを直接実行できます。

    使用可能なオプションはオプションに記載されています。wasmランチャーに--help:wasmオプションを渡すと、GraalWasmエンジンオプションの完全なリストを取得できます。内部オプションを含めるには、--help:wasm:internalを使用します。これらのリストには、安定版のサポートされているオプションと実験的なオプションの両方が含まれていることに注意してください。

  • [--entry-point=FN]

    --entry-pointオプションを指定して、モジュールのエントリポイントとして使用するエクスポートされた関数を指定できます(例:--entry-point=my_custom_main_fn)。--entry-pointオプションがない場合、GraalWasmはエントリポイントを自動検出しようとします。まず、_startという名前のエクスポートされた関数を探し、次に_mainという名前のエクスポートされた関数を探します。最初に検出された関数が、wasmランチャーによってエントリポイントとして実行されます。

  • FILE

    実行されるバイナリモジュールのパスです。

  • [ARG...]

    WASIのargs_get関数とargs_sizes_get関数を通じてプログラムからアクセスできるプログラム引数です。

お問い合わせ