SVX日記
2023-10-14(Sat) WebAssembly $43
さて「グローバル変数」によりJavaScriptとWebAssembly間で情報を共有する方法をテストできたが、WebAssemblyは計算やメモリ操作しかできないので、どちらかというと大量のデータを処理する用途に向くわけだから、大きなメモリを共有してこそ真価が発揮されるわけだ。そこで次はJavaScriptとWebAssembly間でメモリ空間を共有できる「共有メモリ」をテストしてみることにする。
;; https://github.com/mdn/webassembly-examples/blob/main/js-api-examples/memory.wat
(module
(memory $mem (import "js" "mem") 1)
(func $log (import "console" "log") (param i32))
(func (export "memsize")
memory.size
call $log
)
(func (export "memStoreTest")
i32.const 0 ;; adr
i32.const 518 ;; val 0x_0000_0206
i32.store
i32.const 8 ;; adr
i32.const 524 ;; val 0x_0000_020C
i32.store
i32.const 5 ;; adr
i32.const 0x55
i32.store8
i32.const 6 ;; adr
i32.const 0xAA
i32.store8
i32.const 0x0d ;; adr
i32.const 0x55AA
i32.store16
i32.const -1
call $log
)
(func (export "memLoadTest") (param $adr i32)
local.get $adr
i32.load
call $log
local.get $adr
i32.load8_u
call $log
)
)
<!-- https://developer.mozilla.org/ja/docs/WebAssembly/JavaScript_interface/Memory -->
<HTML>
<HEAD>
<TITLE>WebAssembly Memory Test</TITLE>
</HEAD>
<BODY>
<SCRIPT>
async function main() {
const memory = new WebAssembly.Memory({ initial: 3, maximum: 8 }); // 1 PAGE = 64 KB
const importObjects = {
js: { mem: memory },
console: { log: (arg) => console.log(arg) },
};
const obj = await WebAssembly.instantiateStreaming(fetch('memory.wasm'), importObjects);
obj.instance.exports.memsize();
memory.grow(2); // +2 pages
obj.instance.exports.memsize();
const i8 = new Uint8Array(memory.buffer);
const i32 = new Uint32Array(memory.buffer);
function dump(i8) { // memory dump
const dump = [];
for(let p = 0; p < 16; p++) {
dump.push(i8[p].toString(16));
}
console.log('dump:', dump.join(' '));
}
dump(i8);
for(let p = 0; p < 16; p++) { // 8bit store by JavaScript
i8[p] = 0x80 + (p << 1);
}
dump(i8);
for(let p = 0; p < 16; p++) { // 32bit store by JavaScript
i32[p] = 0x80 + (p << 1);
}
dump(i8); // little endian
obj.instance.exports.memStoreTest(); // store by WebAssembly
dump(i8);
obj.instance.exports.memLoadTest(0); // load by WebAssembly
obj.instance.exports.memLoadTest(8);
}
main();
</SCRIPT>
</BODY>
</HTML>
3
5
dump: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
dump: 80 82 84 86 88 8a 8c 8e 90 92 94 96 98 9a 9c 9e
dump: 80 0 0 0 82 0 0 0 84 0 0 0 86 0 0 0
-1
dump: 6 2 0 0 82 55 aa 0 c 2 0 0 86 aa 55 0
518
6
524
12
その後、メモリの先頭16バイトをダンプ表示。JavaScript側では、Cの共用体のようにメモリをchar配列とint32配列とで共用する形にして、順に数字を格納していって、バイトオーダがリトルエンディアンであることを確認している。