Source code

Revision control

Copy as Markdown

Other Tools

// Uses only web-compatible APIs (no minorgc/gczeal/gcparam).
"use strict";
function gcWrapper() {
gc();
return 0;
}
const wat = `
(module
(type $i32arr (array (mut i32)))
(import "env" "triggerGC" (func $triggerGC (result i32)))
;; 32 i32 elements = 128 bytes data > 112 (MaxInlineBytes) => OOL
;; OOL block = 136 bytes <= 256 (MaxNurseryTrailerSize) => nursery-direct
(func (export "test") (result i32)
(local $arr (ref $i32arr))
(local.set $arr (array.new $i32arr (i32.const 0) (i32.const 32)))
(array.set $i32arr (local.get $arr) (i32.const 0) (i32.const 0xCAFEBABE))
(array.set $i32arr (local.get $arr) (i32.const 1) (i32.const 0xDEADBEEF))
(array.set $i32arr (local.get $arr) (i32.const 15) (i32.const 0xBAADF00D))
(array.set $i32arr (local.get $arr) (i32.const 31) (i32.const 0x1337C0DE))
;; GC safepoint: Ion keeps data pointer live across this call
(drop (call $triggerGC))
;; Reads via (potentially stale) data pointer
(i32.add
(i32.add
(array.get $i32arr (local.get $arr) (i32.const 0))
(array.get $i32arr (local.get $arr) (i32.const 1)))
(i32.add
(array.get $i32arr (local.get $arr) (i32.const 15))
(array.get $i32arr (local.get $arr) (i32.const 31))))
)
)`;
const inst = wasmEvalText(wat, { env: { triggerGC: gcWrapper } });
let res = inst.exports.test();
assertEq(res, 2006067864);