関数の書き方
asm.jsでは、次の手順で最適化関数を実装します。
最適化したい関数の初期化を行う関数を実装します。この初期化関数をモジュールと呼びます。
モジュールは引数として、標準ライブラリ、外部インターフェース、メモリ配列の3つをとります。
モジュール内に、1つ以上の最適化したい関数を実装します。
モジュールはreturn時に、keyとして関数名、valueとして最適化したい関数を設定した連想配列を返します。
モジュールの具体的なレイアウトは次のようになります。
function モジュール名(標準ライブラリ名,外部インターフェース名,メモリ配列名) {
"use asm";
var 関数グローバル変数 = 変数の型つき初期化;
var 関数名 = 標準ライブラリ名.関数名;
var 関数名 = 標準ライブラリ名.Math.関数名;
var 配列名 = new 標準ライブラリ名.XXXArray(メモリ配列名);
function 最適化関数名(引数) {
引数 = 型指定つき引数;
var 関数内部の変数 = 変数の型つき初期化;
任意の演算処理;
return 型つきの戻り値;
}
return { 名前: 最適化関数名 };
}
上から順に説明していきます。
モジュールとその引数
モジュールは、Javascriptの関数として実装します。
関数は3つの引数をとり、それらは次の意味を持ちます。
標準ライブラリ名 | 仕様ではstdlibと呼ばれています。ライブラリへの参照です。通常はselfかwindowを渡します。 |
外部インターフェース名 | 仕様ではforeignと呼ばれています。呼び出したい外部関数を含む連想配列です。nullでもかまいません。 |
メモリ配列名 | 仕様ではheapと呼ばれています。ArrayBufferへの参照です。ArrayBufferはサイズ条件を満たす必要があります。 |
後ろの引数を必要としない場合は省略することも可能です。
ArrayBufferのサイズは、次のいずれかにする必要があります。サイズの単位はバイト数です。
(2の16乗)〜(2の24乗)までの、2の整数乗のバイト数。
(2の24乗)の倍数のバイト数。
このサイズ以外のArrayBufferをモジュールの引数として与えると、asm.js未対応のコードとして扱われます。
use asm
モジュール実装部分の先頭に、セミコロンつきの文字列として "use asm"; を与えます。
asm.jsに対応したJavascriptエンジンでは、関数の先頭にこの文字列があると、
その関数に対してasm.jsとしての解釈を試みます。
Javascriptの文法としては代入先がない文字列定数を与えているだけですので、
asm.jsに対応していないJavascriptエンジンでは、この文字列は何もしません。
関数グローバル変数の初期化
最適化関数から参照する変数は、ここで初期化します。
ここでは、次のいずれかの変数を初期化できます。
変数の種類 | 変数の型 |
関数グローバル変数 | 変数の型としてint,float,doubleのいずれかを指定して初期化します。 |
ライブラリ関数 | 標準ライブラリ名.関数名、または標準ライブラリ名.Math.関数名という関数参照を代入する形で初期化します。 |
外部関数 | 外部インターフェース名.関数名という関数参照を代入する形で初期化します。 |
配列への参照 | new 標準ライブラリ名.型つき配列クラス(メモリ配列名);という形で、型つき配列にアクセスするための参照変数を初期化します。 |
最適化関数
asm.jsで高速化の対象とする関数は、次の要素を持ちます。
要素 | 内容 |
引数の型指定 | 引数の型としてint,float,doubleのいずれかを指定します。 |
内部変数の型つき初期化 | 変数の型としてint,float,doubleのいずれかを指定して初期化します。 |
任意の演算処理 | asm.jsに対応した型つき演算を行います。 |
戻り値を返す | double,signed,floatのいずれかの型をつけた戻り値を返します。戻り値なしでも問題ありません。 |
連想配列による最適化関数の公開
最適化関数の実装部分が終わったら、モジュールは最適化関数を格納した連想配列を返します。
連想配列には、keyとして関数名、valueとして最適化関数への参照を格納します。
複数の最適化関数を実装し、それらすべてを返すこともできます。
モジュールから返された最適化関数は、好きなときに外部から呼び出せるようになります。
モジュールをasm.jsとして扱うことができなかったり、
Javascriptエンジンが"use asm";に対応していなかった場合は、
通常のJavascriptとして扱われます。