| //@ 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); |