SVX日記

2004|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|09|10|11|12|
2024|01|02|03|04|05|06|07|08|09|10|11|

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

  いろいろなことをやっているが、最初はJavaScript側でメモリを3ページ確保してWebAssembly側に渡し、それに2ページ追加してWebAssembly側に検知させている。

  その後、メモリの先頭16バイトをダンプ表示。JavaScript側では、Cの共用体のようにメモリをchar配列とint32配列とで共用する形にして、順に数字を格納していって、バイトオーダがリトルエンディアンであることを確認している。

  最後に、WebAssembly側で、int32での格納、charでの格納、int16での格納、デバッグログ出力(console.logの呼び出し、数字だけだけど)、int32での読出、charでの読出、その結果の出力、という感じ。

  このひと通りのテストを通じて、WebAssembly側で画像処理を行う目処が得られた気がする。よっしゃよっしゃ。任務完了。