blob: b0f1754bc8e0959880ec80d457e5625d3d557cd5 [file] [edit]
//@ requireOptions("--alwaysUseShadowChicken=true", "--slowPathAllocsBetweenGCs=1", "--forceGCSlowPaths=true")
import * as assert from "../assert.js"
// Companion to ref-func-wrapper-alloc-frame-tracer.js, for array.init_elem.
//
// array.init_elem copies a funcref elem segment through copyElementSegment, which
// materializes each element's JS wrapper. Unlike array.new_elem it does not
// allocate the array itself, so the earlier Wasm GC slow path audit missed it.
//
// Kept as bytes rather than WAT: the Wasm GC text format needs gc/wast.js, whose
// 6.6MB of JS takes ~45s to load under this test's forced-GC options.
//
// (module
// (type $arr (array (mut funcref)))
// (import "m" "f" (func $import))
// (elem $e funcref (ref.func $f0) (ref.func $f1) (ref.func $f2) (ref.func $f3) (ref.func $f4) (ref.func $f5) (ref.func $f6) (ref.func $f7))
// (func $f0)
// (func $f1)
// (func $f2)
// (func $f3)
// (func $f4)
// (func $f5)
// (func $f6)
// (func $f7)
// (func (export "test")
// (local $a (ref null $arr))
// (local.set $a (array.new_default $arr (i32.const 1)))
// (call $import)
// (array.init_elem $arr $e (local.get $a) (i32.const 0) (i32.const 0) (i32.const 1))
// (call $import)
// (array.init_elem $arr $e (local.get $a) (i32.const 0) (i32.const 1) (i32.const 1))
// (call $import)
// (array.init_elem $arr $e (local.get $a) (i32.const 0) (i32.const 2) (i32.const 1))
// (call $import)
// (array.init_elem $arr $e (local.get $a) (i32.const 0) (i32.const 3) (i32.const 1))
// (call $import)
// (array.init_elem $arr $e (local.get $a) (i32.const 0) (i32.const 4) (i32.const 1))
// (call $import)
// (array.init_elem $arr $e (local.get $a) (i32.const 0) (i32.const 5) (i32.const 1))
// (call $import)
// (array.init_elem $arr $e (local.get $a) (i32.const 0) (i32.const 6) (i32.const 1))
// (call $import)
// (array.init_elem $arr $e (local.get $a) (i32.const 0) (i32.const 7) (i32.const 1))
// )
// )
const wasmBytes = new Uint8Array([
0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x02, 0x5e,
0x70, 0x01, 0x60, 0x00, 0x00, 0x02, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x01, 0x6d, 0x01, 0x66,
0x00, 0x01, 0x03, 0x8a, 0x80, 0x80, 0x80, 0x00, 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x07, 0x88, 0x80, 0x80, 0x80, 0x00, 0x01, 0x04, 0x74, 0x65, 0x73, 0x74, 0x00, 0x09,
0x09, 0x9c, 0x80, 0x80, 0x80, 0x00, 0x01, 0x05, 0x70, 0x08, 0xd2, 0x01, 0x0b, 0xd2, 0x02, 0x0b,
0xd2, 0x03, 0x0b, 0xd2, 0x04, 0x0b, 0xd2, 0x05, 0x0b, 0xd2, 0x06, 0x0b, 0xd2, 0x07, 0x0b, 0xd2,
0x08, 0x0b, 0x0a, 0xba, 0x81, 0x80, 0x80, 0x00, 0x09, 0x82, 0x80, 0x80, 0x80, 0x00, 0x00, 0x0b,
0x82, 0x80, 0x80, 0x80, 0x00, 0x00, 0x0b, 0x82, 0x80, 0x80, 0x80, 0x00, 0x00, 0x0b, 0x82, 0x80,
0x80, 0x80, 0x00, 0x00, 0x0b, 0x82, 0x80, 0x80, 0x80, 0x00, 0x00, 0x0b, 0x82, 0x80, 0x80, 0x80,
0x00, 0x00, 0x0b, 0x82, 0x80, 0x80, 0x80, 0x00, 0x00, 0x0b, 0x82, 0x80, 0x80, 0x80, 0x00, 0x00,
0x0b, 0xfc, 0x80, 0x80, 0x80, 0x00, 0x01, 0x01, 0x63, 0x00, 0x41, 0x01, 0xfb, 0x07, 0x00, 0x21,
0x00, 0x10, 0x00, 0x20, 0x00, 0x41, 0x00, 0x41, 0x00, 0x41, 0x01, 0xfb, 0x13, 0x00, 0x00, 0x10,
0x00, 0x20, 0x00, 0x41, 0x00, 0x41, 0x01, 0x41, 0x01, 0xfb, 0x13, 0x00, 0x00, 0x10, 0x00, 0x20,
0x00, 0x41, 0x00, 0x41, 0x02, 0x41, 0x01, 0xfb, 0x13, 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x41,
0x00, 0x41, 0x03, 0x41, 0x01, 0xfb, 0x13, 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x41, 0x00, 0x41,
0x04, 0x41, 0x01, 0xfb, 0x13, 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x41, 0x00, 0x41, 0x05, 0x41,
0x01, 0xfb, 0x13, 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x41, 0x00, 0x41, 0x06, 0x41, 0x01, 0xfb,
0x13, 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x41, 0x00, 0x41, 0x07, 0x41, 0x01, 0xfb, 0x13, 0x00,
0x00, 0x0b,
]);
const numFuncs = 8;
const numInstances = 8;
let calls = 0;
const imports = { m: { f: () => { ++calls; } } };
const module = new WebAssembly.Module(wasmBytes);
for (let i = 0; i < numInstances; ++i)
new WebAssembly.Instance(module, imports).exports.test();
assert.eq(calls, numFuncs * numInstances);