зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-inbound to mozilla-central. a=merge
This commit is contained in:
Коммит
a625f06db9
|
@ -42,10 +42,14 @@ body.config-warning {
|
|||
background-repeat: no-repeat;
|
||||
background-position: 9px center;
|
||||
background-size: 12px 12px;
|
||||
padding-left: 30px;
|
||||
padding-inline-start: 30px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
#about-config-search:dir(rtl) {
|
||||
background-position-x: right 9px;
|
||||
}
|
||||
|
||||
#prefs {
|
||||
background-color: var(--in-content-box-background);
|
||||
color: var(--in-content-text-color);
|
||||
|
@ -81,6 +85,10 @@ body.config-warning {
|
|||
background-size: 16px 16px;
|
||||
}
|
||||
|
||||
#prefs > tr.locked:dir(rtl) {
|
||||
background-position-x: right 9px;
|
||||
}
|
||||
|
||||
#prefs > tr > td,
|
||||
#prefs > tr > th {
|
||||
padding: 4px;
|
||||
|
|
|
@ -98,8 +98,9 @@ const I64DivSCode = 0x7f;
|
|||
const I64DivUCode = 0x80;
|
||||
const I64RemSCode = 0x81;
|
||||
const I64RemUCode = 0x82;
|
||||
const RefNull = 0xd0;
|
||||
const PlaceholderRefFunc = 0xd2;
|
||||
const RefNullCode = 0xd0;
|
||||
const RefIsNullCode = 0xd1;
|
||||
const RefFuncCode = 0xd2;
|
||||
|
||||
const FirstInvalidOpcode = 0xc5;
|
||||
const LastInvalidOpcode = 0xfb;
|
||||
|
|
|
@ -27,7 +27,7 @@ function gen2(base, offset) {
|
|||
(memory 1)
|
||||
(data (i32.const 65528) "aaaaaaaa")
|
||||
(func (result i32)
|
||||
(drop (grow_memory (i32.const 1)))
|
||||
(drop (memory.grow (i32.const 1)))
|
||||
(i32.store (i32.const 65536) (i32.const 0x61616161))
|
||||
(i32.store (i32.const 65540) (i32.const 0x61616161))
|
||||
(i32.store (i32.const 80000) (i32.const 0x61616161))
|
||||
|
|
|
@ -1541,7 +1541,7 @@ function integrateWasmJS(Module) {
|
|||
return null;
|
||||
}
|
||||
} else {
|
||||
exports['__growWasmMemory']((size - oldSize) / wasmPageSize); // tiny wasm method that just does grow_memory
|
||||
exports['__growWasmMemory']((size - oldSize) / wasmPageSize); // tiny wasm method that just does memory.grow
|
||||
// in interpreter, we replace Module.buffer if we allocate
|
||||
return Module['buffer'] !== old ? Module['buffer'] : null; // if it was reallocated, it changed
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
wasmFullPass(`(module
|
||||
(memory 1 32768)
|
||||
(func $test (result i32)
|
||||
(if (i32.eq (grow_memory (i32.const 16384)) (i32.const -1)) (return (i32.const 42)))
|
||||
(if (i32.eq (memory.grow (i32.const 16384)) (i32.const -1)) (return (i32.const 42)))
|
||||
(i32.store (i32.const 1073807356) (i32.const 42))
|
||||
(i32.load (i32.const 1073807356)))
|
||||
(export "run" $test)
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
{
|
||||
let ins = wasmEvalText(`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
|
||||
(type $p (struct (field f64) (field (mut i32))))
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
|||
|
||||
{
|
||||
let ins = wasmEvalText(`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
|
||||
(type $p (struct (field f64)))
|
||||
|
||||
|
@ -44,7 +44,7 @@
|
|||
|
||||
{
|
||||
let ins = wasmEvalText(`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
|
||||
(type $q (struct (field (mut f64))))
|
||||
(type $p (struct (field (mut (ref $q)))))
|
||||
|
@ -74,7 +74,7 @@
|
|||
|
||||
{
|
||||
let ins = wasmEvalText(`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
|
||||
(type $q (struct (field (mut f64))))
|
||||
(type $p (struct (field (mut (ref $q))) (field (mut anyref))))
|
||||
|
@ -104,7 +104,7 @@
|
|||
|
||||
{
|
||||
let ins = wasmEvalText(`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $p (struct (field (mut i64))))
|
||||
(func (export "mkp") (result anyref)
|
||||
(struct.new $p (i64.const 0x1234567887654321))))`).exports;
|
||||
|
@ -133,7 +133,7 @@
|
|||
{
|
||||
let ins = wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $p (struct (field i64)))
|
||||
(type $q (struct (field i32) (field i32)))
|
||||
(func $f (param anyref) (result i32)
|
||||
|
|
|
@ -43,7 +43,7 @@ for (let v of VALUES)
|
|||
{
|
||||
let ins = wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $S (struct (field $S.x (mut anyref))))
|
||||
(func (export "make") (param $v anyref) (result anyref)
|
||||
(struct.new $S (get_local $v))))`);
|
||||
|
@ -57,7 +57,7 @@ for (let v of VALUES)
|
|||
{
|
||||
let ins = wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $S (struct (field $S.x (mut anyref))))
|
||||
(func (export "make") (result anyref)
|
||||
(struct.new $S (ref.null)))
|
||||
|
@ -74,7 +74,7 @@ for (let v of VALUES)
|
|||
{
|
||||
let ins = wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $S (struct (field $S.x (mut anyref))))
|
||||
(func (export "make") (result anyref)
|
||||
(struct.new $S (ref.null)))
|
||||
|
@ -108,7 +108,7 @@ for (let v of VALUES) {
|
|||
{
|
||||
let ins = wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $S (struct (field $S.x (mut anyref))))
|
||||
(func (export "make") (result anyref)
|
||||
(struct.new $S (ref.null))))`);
|
||||
|
@ -123,7 +123,7 @@ for (let v of VALUES) {
|
|||
{
|
||||
let ins = wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $S (struct (field $S.x (mut anyref))))
|
||||
(func (export "make") (result anyref)
|
||||
(struct.new $S (ref.null))))`);
|
||||
|
@ -149,7 +149,7 @@ for (let v of VALUES) {
|
|||
let params = iota(10).map((i) => `(param $${i} anyref)`).join(' ');
|
||||
let args = iota(10).map((i) => `(get_local $${i})`).join(' ');
|
||||
let txt = `(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $S (struct ${fields}))
|
||||
(func (export "make") ${params} (result anyref)
|
||||
(struct.new $S ${args})))`;
|
||||
|
|
|
@ -58,7 +58,7 @@ for (let v of VALUES)
|
|||
let g = new WebAssembly.Global({value: "anyref"}, v);
|
||||
let ins = wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(import $glob "m" "g" (global anyref))
|
||||
(func (export "f") (result anyref)
|
||||
(get_global $glob)))`,
|
||||
|
@ -73,7 +73,7 @@ for (let v of VALUES)
|
|||
let g = new WebAssembly.Global({value: "anyref", mutable: true});
|
||||
let ins = wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(import $glob "m" "g" (global (mut anyref)))
|
||||
(func (export "f") (param $v anyref)
|
||||
(set_global $glob (get_local $v))))`,
|
||||
|
@ -112,7 +112,7 @@ for (let v of VALUES)
|
|||
let t = new WebAssembly.Table({element: "anyref", initial: 10});
|
||||
let ins = wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(import $t "m" "t" (table 10 anyref))
|
||||
(func (export "f") (param $v anyref)
|
||||
(table.set $t (i32.const 3) (get_local $v))))`,
|
||||
|
@ -128,7 +128,7 @@ for (let v of VALUES)
|
|||
let t = new WebAssembly.Table({element: "anyref", initial: 10});
|
||||
let ins = wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(import $t "m" "t" (table 10 anyref))
|
||||
(func (export "f") (result anyref)
|
||||
(table.get $t (i32.const 3))))`,
|
||||
|
@ -146,7 +146,7 @@ for (let v of VALUES)
|
|||
let receiver = function (w) { assertEq(w, v); };
|
||||
let ins = wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(import $returner "m" "returner" (func (result anyref)))
|
||||
(import $receiver "m" "receiver" (func (param anyref)))
|
||||
(func (export "test_returner") (result anyref)
|
||||
|
|
|
@ -10,7 +10,7 @@ function Baguette(calories) {
|
|||
// Ensure the baseline compiler sync's before the postbarrier.
|
||||
(function() {
|
||||
wasmEvalText(`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(global (mut anyref) (ref.null))
|
||||
(func (export "f")
|
||||
get_global 0
|
||||
|
@ -22,7 +22,7 @@ function Baguette(calories) {
|
|||
})();
|
||||
|
||||
let exportsPlain = wasmEvalText(`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(global i32 (i32.const 42))
|
||||
(global $g (mut anyref) (ref.null))
|
||||
(func (export "set") (param anyref) get_local 0 set_global $g)
|
||||
|
@ -30,7 +30,7 @@ let exportsPlain = wasmEvalText(`(module
|
|||
)`).exports;
|
||||
|
||||
let exportsObj = wasmEvalText(`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(global $g (export "g") (mut anyref) (ref.null))
|
||||
(func (export "set") (param anyref) get_local 0 set_global $g)
|
||||
(func (export "get") (result anyref) get_global $g)
|
||||
|
|
|
@ -10,7 +10,7 @@ if (opts['ion.enable'] || opts['baseline.enable'])
|
|||
const { startProfiling, endProfiling, assertEqPreciseStacks, isSingleStepProfilingEnabled } = WasmHelpers;
|
||||
|
||||
let e = wasmEvalText(`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(global $g (mut anyref) (ref.null))
|
||||
(func (export "set") (param anyref) get_local 0 set_global $g)
|
||||
)`).exports;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// ref.eq is part of the gc feature, not the reftypes feature.
|
||||
|
||||
let { exports } = wasmEvalText(`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
|
||||
(func (export "ref_eq") (param $a anyref) (param $b anyref) (result i32)
|
||||
(ref.eq (get_local $a) (get_local $b)))
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
gczeal(14, 1);
|
||||
let { exports } = wasmEvalText(`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(global $anyref (import "glob" "anyref") anyref)
|
||||
(func (export "get") (result anyref) get_global $anyref)
|
||||
)`, {
|
||||
|
|
|
@ -10,14 +10,14 @@ function Baguette(calories) {
|
|||
const { validate, CompileError } = WebAssembly;
|
||||
|
||||
assertErrorMessage(() => wasmEvalText(`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(func (result anyref)
|
||||
i32.const 42
|
||||
)
|
||||
)`), CompileError, mismatchError('i32', 'anyref'));
|
||||
|
||||
assertErrorMessage(() => wasmEvalText(`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(func (result anyref)
|
||||
i32.const 0
|
||||
ref.null
|
||||
|
@ -27,7 +27,7 @@ assertErrorMessage(() => wasmEvalText(`(module
|
|||
)`), CompileError, /select operand types/);
|
||||
|
||||
assertErrorMessage(() => wasmEvalText(`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(func (result i32)
|
||||
ref.null
|
||||
if
|
||||
|
@ -40,16 +40,16 @@ assertErrorMessage(() => wasmEvalText(`(module
|
|||
// Basic compilation tests.
|
||||
|
||||
let simpleTests = [
|
||||
"(module (gc_feature_opt_in 2) (func (drop (ref.null))))",
|
||||
"(module (gc_feature_opt_in 2) (func $test (local anyref)))",
|
||||
"(module (gc_feature_opt_in 2) (func $test (param anyref)))",
|
||||
"(module (gc_feature_opt_in 2) (func $test (result anyref) (ref.null)))",
|
||||
"(module (gc_feature_opt_in 2) (func $test (block anyref (unreachable)) unreachable))",
|
||||
"(module (gc_feature_opt_in 2) (func $test (local anyref) (result i32) (ref.is_null (get_local 0))))",
|
||||
`(module (gc_feature_opt_in 2) (import "a" "b" (param anyref)))`,
|
||||
`(module (gc_feature_opt_in 2) (import "a" "b" (result anyref)))`,
|
||||
`(module (gc_feature_opt_in 2) (global anyref (ref.null)))`,
|
||||
`(module (gc_feature_opt_in 2) (global (mut anyref) (ref.null)))`,
|
||||
"(module (gc_feature_opt_in 3) (func (drop (ref.null))))",
|
||||
"(module (gc_feature_opt_in 3) (func $test (local anyref)))",
|
||||
"(module (gc_feature_opt_in 3) (func $test (param anyref)))",
|
||||
"(module (gc_feature_opt_in 3) (func $test (result anyref) (ref.null)))",
|
||||
"(module (gc_feature_opt_in 3) (func $test (block anyref (unreachable)) unreachable))",
|
||||
"(module (gc_feature_opt_in 3) (func $test (local anyref) (result i32) (ref.is_null (get_local 0))))",
|
||||
`(module (gc_feature_opt_in 3) (import "a" "b" (param anyref)))`,
|
||||
`(module (gc_feature_opt_in 3) (import "a" "b" (result anyref)))`,
|
||||
`(module (gc_feature_opt_in 3) (global anyref (ref.null)))`,
|
||||
`(module (gc_feature_opt_in 3) (global (mut anyref) (ref.null)))`,
|
||||
];
|
||||
|
||||
for (let src of simpleTests) {
|
||||
|
@ -60,7 +60,7 @@ for (let src of simpleTests) {
|
|||
// Basic behavioral tests.
|
||||
|
||||
let { exports } = wasmEvalText(`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(func (export "is_null") (result i32)
|
||||
ref.null
|
||||
ref.is_null
|
||||
|
@ -98,7 +98,7 @@ assertEq(exports.is_null_local(), 1);
|
|||
// Anyref param and result in wasm functions.
|
||||
|
||||
exports = wasmEvalText(`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(func (export "is_null") (result i32) (param $ref anyref)
|
||||
get_local $ref
|
||||
ref.is_null
|
||||
|
@ -156,13 +156,13 @@ assertEq(ref.calories, baguette.calories);
|
|||
// Make sure grow-memory isn't blocked by the lack of gc.
|
||||
(function() {
|
||||
assertEq(wasmEvalText(`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(memory 0 64)
|
||||
(func (export "f") (param anyref) (result i32)
|
||||
i32.const 10
|
||||
grow_memory
|
||||
memory.grow
|
||||
drop
|
||||
current_memory
|
||||
memory.size
|
||||
)
|
||||
)`).exports.f({}), 10);
|
||||
})();
|
||||
|
@ -172,7 +172,7 @@ assertEq(ref.calories, baguette.calories);
|
|||
function assertJoin(body) {
|
||||
let val = { i: -1 };
|
||||
assertEq(wasmEvalText(`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(func (export "test") (param $ref anyref) (param $i i32) (result anyref)
|
||||
${body}
|
||||
)
|
||||
|
@ -239,7 +239,7 @@ assertJoin(`(block $out anyref (block $unreachable anyref (loop $top
|
|||
|
||||
let x = { i: 42 }, y = { f: 53 };
|
||||
exports = wasmEvalText(`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(func (export "test") (param $lhs anyref) (param $rhs anyref) (param $i i32) (result anyref)
|
||||
get_local $lhs
|
||||
get_local $rhs
|
||||
|
@ -294,7 +294,7 @@ let imports = {
|
|||
};
|
||||
|
||||
exports = wasmEvalText(`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(import $ret "funcs" "ret" (result anyref))
|
||||
(import $param "funcs" "param" (param anyref))
|
||||
|
||||
|
@ -323,7 +323,7 @@ assertEq(exports.ret(), imports.myBaguette);
|
|||
// Check lazy stubs generation.
|
||||
|
||||
exports = wasmEvalText(`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(import $mirror "funcs" "mirror" (param anyref) (result anyref))
|
||||
(import $augment "funcs" "augment" (param anyref) (result anyref))
|
||||
|
||||
|
@ -407,11 +407,11 @@ assertEq(exports.count_g(), 1);
|
|||
|
||||
// Anyref globals in wasm modules.
|
||||
|
||||
assertErrorMessage(() => wasmEvalText(`(module (gc_feature_opt_in 2) (global (import "glob" "anyref") anyref))`, { glob: { anyref: new WebAssembly.Global({ value: 'i32' }, 42) } }),
|
||||
assertErrorMessage(() => wasmEvalText(`(module (gc_feature_opt_in 3) (global (import "glob" "anyref") anyref))`, { glob: { anyref: new WebAssembly.Global({ value: 'i32' }, 42) } }),
|
||||
WebAssembly.LinkError,
|
||||
/imported global type mismatch/);
|
||||
|
||||
assertErrorMessage(() => wasmEvalText(`(module (gc_feature_opt_in 2) (global (import "glob" "i32") i32))`, { glob: { i32: {} } }),
|
||||
assertErrorMessage(() => wasmEvalText(`(module (gc_feature_opt_in 3) (global (import "glob" "i32") i32))`, { glob: { i32: {} } }),
|
||||
WebAssembly.LinkError,
|
||||
/import object field 'i32' is not a Number/);
|
||||
|
||||
|
@ -425,7 +425,7 @@ imports = {
|
|||
};
|
||||
|
||||
exports = wasmEvalText(`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(global $g_imp_imm_null (import "constants" "imm_null") anyref)
|
||||
(global $g_imp_imm_bread (import "constants" "imm_bread") anyref)
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ const v2vSigSection = sigSection([v2vSig]);
|
|||
|
||||
function checkInvalid(body, errorMessage) {
|
||||
assertErrorMessage(() => new WebAssembly.Module(
|
||||
moduleWithSections([gcFeatureOptInSection(2), v2vSigSection, declSection([0]), bodySection([body])])),
|
||||
moduleWithSections([gcFeatureOptInSection(3), v2vSigSection, declSection([0]), bodySection([body])])),
|
||||
WebAssembly.CompileError,
|
||||
errorMessage);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
(function() {
|
||||
let g = newGlobal({newCompartment: true});
|
||||
let dbg = new Debugger(g);
|
||||
g.eval(`o = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary('(module (gc_feature_opt_in 2) (func (result anyref) (param anyref) get_local 0) (export "" 0))')));`);
|
||||
g.eval(`o = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary('(module (gc_feature_opt_in 3) (func (result anyref) (param anyref) get_local 0) (export "" 0))')));`);
|
||||
})();
|
||||
|
||||
(function() {
|
||||
|
@ -12,7 +12,7 @@
|
|||
|
||||
let src = `
|
||||
(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(func (export "func") (result anyref) (param $ref anyref)
|
||||
get_local $ref
|
||||
)
|
||||
|
|
|
@ -9,15 +9,15 @@ function assertValidateError(text) {
|
|||
}
|
||||
|
||||
let simpleTests = [
|
||||
"(module (gc_feature_opt_in 2) (func (drop (ref.null))))",
|
||||
"(module (gc_feature_opt_in 2) (func $test (local anyref)))",
|
||||
"(module (gc_feature_opt_in 2) (func $test (param anyref)))",
|
||||
"(module (gc_feature_opt_in 2) (func $test (result anyref) (ref.null)))",
|
||||
"(module (gc_feature_opt_in 2) (func $test (block anyref (unreachable)) unreachable))",
|
||||
"(module (gc_feature_opt_in 2) (func $test (local anyref) (result i32) (ref.is_null (get_local 0))))",
|
||||
`(module (gc_feature_opt_in 2) (import "a" "b" (param anyref)))`,
|
||||
`(module (gc_feature_opt_in 2) (import "a" "b" (result anyref)))`,
|
||||
`(module (gc_feature_opt_in 2) (type $s (struct)))`,
|
||||
"(module (gc_feature_opt_in 3) (func (drop (ref.null))))",
|
||||
"(module (gc_feature_opt_in 3) (func $test (local anyref)))",
|
||||
"(module (gc_feature_opt_in 3) (func $test (param anyref)))",
|
||||
"(module (gc_feature_opt_in 3) (func $test (result anyref) (ref.null)))",
|
||||
"(module (gc_feature_opt_in 3) (func $test (block anyref (unreachable)) unreachable))",
|
||||
"(module (gc_feature_opt_in 3) (func $test (local anyref) (result i32) (ref.is_null (get_local 0))))",
|
||||
`(module (gc_feature_opt_in 3) (import "a" "b" (param anyref)))`,
|
||||
`(module (gc_feature_opt_in 3) (import "a" "b" (result anyref)))`,
|
||||
`(module (gc_feature_opt_in 3) (type $s (struct)))`,
|
||||
];
|
||||
|
||||
// Two distinct failure modes:
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
//
|
||||
// Struct types are only available if we opt in, so test that.
|
||||
|
||||
let CURRENT_VERSION = 2;
|
||||
let CURRENT_VERSION = 3;
|
||||
|
||||
new WebAssembly.Module(wasmTextToBinary(
|
||||
`(module
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
|
||||
// Version numbers
|
||||
|
||||
let CURRENT_VERSION = 2;
|
||||
let OLDER_INCOMPATIBLE_VERSION = 1; // v1 incompatible with v2
|
||||
let FUTURE_VERSION = 3;
|
||||
let CURRENT_VERSION = 3;
|
||||
let SOME_OLDER_INCOMPATIBLE_VERSION = CURRENT_VERSION - 1; // v1 incompatible with v2, v2 with v3
|
||||
let SOME_FUTURE_VERSION = CURRENT_VERSION + 1; // ok for now
|
||||
|
||||
// Encoding. If the section is present it must be first.
|
||||
|
||||
|
@ -36,13 +36,13 @@ new WebAssembly.Module(wasmTextToBinary(
|
|||
|
||||
assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in ${OLDER_INCOMPATIBLE_VERSION}))`)),
|
||||
(gc_feature_opt_in ${SOME_OLDER_INCOMPATIBLE_VERSION}))`)),
|
||||
WebAssembly.CompileError,
|
||||
/GC feature version \d+ is no longer supported by this engine/);
|
||||
/GC feature version.*no longer supported by this engine/);
|
||||
|
||||
assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in ${FUTURE_VERSION}))`)),
|
||||
(gc_feature_opt_in ${SOME_FUTURE_VERSION}))`)),
|
||||
WebAssembly.CompileError,
|
||||
/GC feature version is unknown/);
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
var refmod = new WebAssembly.Module(wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
|
||||
(import $tbl "" "tbl" (table 4 anyfunc))
|
||||
(import $print "" "print" (func (param i32)))
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
{
|
||||
let bin = wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
|
||||
(type $point (struct
|
||||
(field $x f64)
|
||||
|
@ -42,7 +42,7 @@
|
|||
{
|
||||
let bin = wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
|
||||
(type $point (struct
|
||||
(field $x f64)
|
||||
|
@ -87,7 +87,7 @@
|
|||
{
|
||||
let bin = wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(import $g "" "g" (global anyref))
|
||||
(global $glob anyref (get_global $g))
|
||||
(func (export "get") (result anyref)
|
||||
|
@ -105,7 +105,7 @@
|
|||
{
|
||||
let bin = wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $box (struct (field $val i32)))
|
||||
(import "m" "g" (global (mut (ref $box)))))`);
|
||||
|
||||
|
@ -120,7 +120,7 @@
|
|||
{
|
||||
let bin = wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $box (struct (field $val i32)))
|
||||
(global $boxg (export "box") (mut (ref $box)) (ref.null)))`);
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ function wasmCompile(text) {
|
|||
|
||||
assertErrorMessage(() => wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $box (struct (field $x i32)))
|
||||
(func (export "f") (param (ref $box)) (unreachable)))`),
|
||||
WebAssembly.CompileError,
|
||||
|
@ -59,7 +59,7 @@ assertErrorMessage(() => wasmCompile(
|
|||
|
||||
assertEq(typeof wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(func (export "f") (param anyref) (unreachable)))`),
|
||||
"object");
|
||||
|
||||
|
@ -67,7 +67,7 @@ assertEq(typeof wasmCompile(
|
|||
|
||||
assertErrorMessage(() => wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $box (struct (field $x i32)))
|
||||
(func (export "f") (result (ref $box)) (ref.null)))`),
|
||||
WebAssembly.CompileError,
|
||||
|
@ -75,7 +75,7 @@ assertErrorMessage(() => wasmCompile(
|
|||
|
||||
assertEq(typeof wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(func (export "f") (result anyref) (ref.null)))`),
|
||||
"object");
|
||||
|
||||
|
@ -83,7 +83,7 @@ assertEq(typeof wasmCompile(
|
|||
|
||||
assertErrorMessage(() => wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $box (struct (field $x i32)))
|
||||
(import "m" "f" (param (ref $box))))`),
|
||||
WebAssembly.CompileError,
|
||||
|
@ -91,7 +91,7 @@ assertErrorMessage(() => wasmCompile(
|
|||
|
||||
assertEq(typeof wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(import "m" "f" (param anyref)))`),
|
||||
"object");
|
||||
|
||||
|
@ -99,7 +99,7 @@ assertEq(typeof wasmCompile(
|
|||
|
||||
assertErrorMessage(() => wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $box (struct (field $x i32)))
|
||||
(import "m" "f" (param i32) (result (ref $box))))`),
|
||||
WebAssembly.CompileError,
|
||||
|
@ -107,7 +107,7 @@ assertErrorMessage(() => wasmCompile(
|
|||
|
||||
assertEq(typeof wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(import "m" "f" (param i32) (result anyref)))`),
|
||||
"object");
|
||||
|
||||
|
@ -115,7 +115,7 @@ assertEq(typeof wasmCompile(
|
|||
|
||||
assertErrorMessage(() => wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $box (struct (field $val i32)))
|
||||
(import "m" "g" (global (mut (ref $box)))))`),
|
||||
WebAssembly.CompileError,
|
||||
|
@ -123,7 +123,7 @@ assertErrorMessage(() => wasmCompile(
|
|||
|
||||
assertErrorMessage(() => wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $box (struct (field $val i32)))
|
||||
(import "m" "g" (global (ref $box))))`),
|
||||
WebAssembly.CompileError,
|
||||
|
@ -131,13 +131,13 @@ assertErrorMessage(() => wasmCompile(
|
|||
|
||||
assertEq(typeof wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(import "m" "g" (global (mut anyref))))`),
|
||||
"object");
|
||||
|
||||
assertEq(typeof wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(import "m" "g" (global anyref)))`),
|
||||
"object");
|
||||
|
||||
|
@ -145,7 +145,7 @@ assertEq(typeof wasmCompile(
|
|||
|
||||
assertErrorMessage(() => wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $box (struct (field $val i32)))
|
||||
(global $boxg (export "box") (mut (ref $box)) (ref.null)))`),
|
||||
WebAssembly.CompileError,
|
||||
|
@ -153,7 +153,7 @@ assertErrorMessage(() => wasmCompile(
|
|||
|
||||
assertErrorMessage(() => wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $box (struct (field $val i32)))
|
||||
(global $boxg (export "box") (ref $box) (ref.null)))`),
|
||||
WebAssembly.CompileError,
|
||||
|
@ -161,13 +161,13 @@ assertErrorMessage(() => wasmCompile(
|
|||
|
||||
assertEq(typeof wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(global $boxg (export "box") (mut anyref) (ref.null)))`),
|
||||
"object");
|
||||
|
||||
assertEq(typeof wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(global $boxg (export "box") anyref (ref.null)))`),
|
||||
"object");
|
||||
|
||||
|
@ -175,7 +175,7 @@ assertEq(typeof wasmCompile(
|
|||
|
||||
assertErrorMessage(() => wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $box (struct (field $val i32)))
|
||||
(table (export "tbl") 1 anyfunc)
|
||||
(elem (i32.const 0) $f1)
|
||||
|
@ -185,7 +185,7 @@ assertErrorMessage(() => wasmCompile(
|
|||
|
||||
assertErrorMessage(() => wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $box (struct (field $val i32)))
|
||||
(table (export "tbl") 1 anyfunc)
|
||||
(elem (i32.const 0) $f1)
|
||||
|
@ -195,7 +195,7 @@ assertErrorMessage(() => wasmCompile(
|
|||
|
||||
assertEq(typeof wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(table (export "tbl") 1 anyfunc)
|
||||
(elem (i32.const 0) $f1)
|
||||
(func $f1 (param anyref) (unreachable)))`),
|
||||
|
@ -203,7 +203,7 @@ assertEq(typeof wasmCompile(
|
|||
|
||||
assertEq(typeof wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(table (export "tbl") 1 anyfunc)
|
||||
(elem (i32.const 0) $f1)
|
||||
(func $f1 (result anyref) (ref.null)))`),
|
||||
|
@ -213,7 +213,7 @@ assertEq(typeof wasmCompile(
|
|||
|
||||
assertErrorMessage(() => wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $box (struct (field $val i32)))
|
||||
(import "m" "tbl" (table 1 anyfunc))
|
||||
(elem (i32.const 0) $f1)
|
||||
|
@ -223,7 +223,7 @@ assertErrorMessage(() => wasmCompile(
|
|||
|
||||
assertErrorMessage(() => wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $box (struct (field $val i32)))
|
||||
(import "m" "tbl" (table 1 anyfunc))
|
||||
(elem (i32.const 0) $f1)
|
||||
|
@ -233,7 +233,7 @@ assertErrorMessage(() => wasmCompile(
|
|||
|
||||
assertEq(typeof wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(import "m" "tbl" (table 1 anyfunc))
|
||||
(elem (i32.const 0) $f1)
|
||||
(func $f1 (param anyref) (unreachable)))`),
|
||||
|
@ -241,7 +241,7 @@ assertEq(typeof wasmCompile(
|
|||
|
||||
assertEq(typeof wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(import "m" "tbl" (table 1 anyfunc))
|
||||
(elem (i32.const 0) $f1)
|
||||
(func $f1 (result anyref) (ref.null)))`),
|
||||
|
@ -251,7 +251,7 @@ assertEq(typeof wasmCompile(
|
|||
|
||||
assertErrorMessage(() => wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $box (struct (field $val i32)))
|
||||
(type $fn (func (param (ref $box))))
|
||||
(table (export "tbl") 1 anyfunc)
|
||||
|
@ -262,7 +262,7 @@ assertErrorMessage(() => wasmCompile(
|
|||
|
||||
assertErrorMessage(() => wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $box (struct (field $val i32)))
|
||||
(type $fn (func (result (ref $box))))
|
||||
(table (export "tbl") 1 anyfunc)
|
||||
|
@ -273,7 +273,7 @@ assertErrorMessage(() => wasmCompile(
|
|||
|
||||
assertEq(typeof wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $fn (func (param anyref)))
|
||||
(table (export "tbl") 1 anyfunc)
|
||||
(func (param i32)
|
||||
|
@ -282,7 +282,7 @@ assertEq(typeof wasmCompile(
|
|||
|
||||
assertEq(typeof wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $fn (func (result anyref)))
|
||||
(table (export "tbl") 1 anyfunc)
|
||||
(func (param i32) (result anyref)
|
||||
|
@ -293,7 +293,7 @@ assertEq(typeof wasmCompile(
|
|||
|
||||
assertErrorMessage(() => wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $box (struct (field $val i32)))
|
||||
(type $fn (func (param (ref $box))))
|
||||
(import "m" "tbl" (table 1 anyfunc))
|
||||
|
@ -304,7 +304,7 @@ assertErrorMessage(() => wasmCompile(
|
|||
|
||||
assertErrorMessage(() => wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $box (struct (field $val i32)))
|
||||
(type $fn (func (result (ref $box))))
|
||||
(import "m" "tbl" (table 1 anyfunc))
|
||||
|
@ -315,7 +315,7 @@ assertErrorMessage(() => wasmCompile(
|
|||
|
||||
assertEq(typeof wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $fn (func (param anyref)))
|
||||
(import "m" "tbl" (table 1 anyfunc))
|
||||
(func (param i32)
|
||||
|
@ -324,7 +324,7 @@ assertEq(typeof wasmCompile(
|
|||
|
||||
assertEq(typeof wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $fn (func (result anyref)))
|
||||
(import "m" "tbl" (table 1 anyfunc))
|
||||
(func (param i32) (result anyref)
|
||||
|
@ -336,7 +336,7 @@ assertEq(typeof wasmCompile(
|
|||
{
|
||||
let m = wasmCompile(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $box (struct (field $val i32)))
|
||||
(type $fn (func (param (ref $box)) (result i32)))
|
||||
(table 1 anyfunc)
|
||||
|
|
|
@ -8,7 +8,7 @@ const v2vSigSection = sigSection([{args:[], ret:VoidCode}]);
|
|||
|
||||
function checkInvalid(body, errorMessage) {
|
||||
assertErrorMessage(() => new WebAssembly.Module(
|
||||
moduleWithSections([gcFeatureOptInSection(2),
|
||||
moduleWithSections([gcFeatureOptInSection(3),
|
||||
v2vSigSection,
|
||||
declSection([0]),
|
||||
bodySection([body])])),
|
||||
|
@ -22,7 +22,7 @@ function checkInvalid(body, errorMessage) {
|
|||
{
|
||||
let bin = wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
|
||||
(import $print_lp "" "print_lp" (func))
|
||||
(import $print_rp "" "print_rp" (func))
|
||||
|
@ -119,7 +119,7 @@ function checkInvalid(body, errorMessage) {
|
|||
|
||||
wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $node (struct (field (mut (ref $node)))))
|
||||
(type $nix (struct (field (mut (ref $node))) (field i32)))
|
||||
(func $f (param $p (ref $node)) (param $q (ref $nix))
|
||||
|
@ -129,7 +129,7 @@ wasmEvalText(
|
|||
|
||||
assertEq(wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $node (struct (field i32)))
|
||||
(type $node2 (struct (field i32) (field f32)))
|
||||
(func $f (param $p (ref $node)) (result (ref $node2))
|
||||
|
@ -142,7 +142,7 @@ assertEq(wasmEvalText(
|
|||
|
||||
assertEq(wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $node (struct (field i32)))
|
||||
(type $node2 (struct (field i32) (field f32)))
|
||||
(func $f (param $p (ref $node)) (result (ref $node2))
|
||||
|
@ -157,7 +157,7 @@ assertEq(wasmEvalText(
|
|||
|
||||
assertEq(wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $node (struct (field (mut i32))))
|
||||
(type $node2 (struct (field (mut i32)) (field f32)))
|
||||
(func $f (param $p (ref $node)) (result (ref $node2))
|
||||
|
@ -179,7 +179,7 @@ assertEq(wasmEvalText(
|
|||
|
||||
assertEq(wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
|
||||
(type $node (struct (field i32)))
|
||||
(type $node2a (struct (field i32) (field (ref $node))))
|
||||
|
@ -196,7 +196,7 @@ assertEq(wasmEvalText(
|
|||
|
||||
assertEq(wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
|
||||
(type $node (struct (field i32)))
|
||||
(type $nodeCopy (struct (field i32)))
|
||||
|
@ -217,7 +217,7 @@ assertEq(wasmEvalText(
|
|||
|
||||
assertEq(wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $node (struct (field i32)))
|
||||
(type $node2 (struct (field i32) (field f32)))
|
||||
(type $node3 (struct (field i32) (field f32) (field f64)))
|
||||
|
@ -233,7 +233,7 @@ assertEq(wasmEvalText(
|
|||
|
||||
assertEq(wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $node (struct (field i32)))
|
||||
(type $node2 (struct (field i32) (field f32)))
|
||||
(type $snort (struct (field i32) (field f64)))
|
||||
|
@ -248,7 +248,7 @@ assertEq(wasmEvalText(
|
|||
|
||||
assertEq(wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $node (struct (field i32)))
|
||||
(func $f (param $p anyref) (result (ref $node))
|
||||
(struct.narrow anyref (ref $node) (get_local $p)))
|
||||
|
@ -262,7 +262,7 @@ assertEq(wasmEvalText(
|
|||
|
||||
assertEq(wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $node (struct (field i32)))
|
||||
(func (export "test") (param $p anyref) (result anyref)
|
||||
(struct.narrow anyref (ref $node) (get_local $p))))`).exports.test({hi:37}),
|
||||
|
@ -273,7 +273,7 @@ assertEq(wasmEvalText(
|
|||
{
|
||||
let txt =
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $node (struct (field i32)))
|
||||
(func (export "make") (param $n i32) (result anyref)
|
||||
(struct.new $node (get_local $n)))
|
||||
|
@ -293,7 +293,7 @@ assertEq(wasmEvalText(
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $node (struct (field i32)))
|
||||
(func $f (param $p (ref $node))
|
||||
(struct.set $node 0 (get_local $p) (i32.const 37))))`),
|
||||
|
@ -304,7 +304,7 @@ assertErrorMessage(() => wasmEvalText(
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $node (struct (field (mut i32))))
|
||||
(func $f (param $p (ref $node))
|
||||
(struct.set $node 0 (get_local $p) (f32.const 37))))`),
|
||||
|
@ -315,7 +315,7 @@ assertErrorMessage(() => wasmEvalText(
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $node (struct (field i32)))
|
||||
(func $f (param $p (ref $node)) (result i32)
|
||||
(struct.get $node 1 (get_local $p))))`),
|
||||
|
@ -326,7 +326,7 @@ assertErrorMessage(() => wasmEvalText(
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $node (struct (field (mut i32))))
|
||||
(func $f (param $p (ref $node))
|
||||
(struct.set $node 1 (get_local $p) (i32.const 37))))`),
|
||||
|
@ -337,7 +337,7 @@ assertErrorMessage(() => wasmEvalText(
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $node (struct (field i32)))
|
||||
(type $snort (struct (field f64)))
|
||||
(func $f (param $p (ref $snort)) (result i32)
|
||||
|
@ -349,7 +349,7 @@ assertErrorMessage(() => wasmEvalText(
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $node (struct (field (mut i32))))
|
||||
(type $snort (struct (field f64)))
|
||||
(func $f (param $p (ref $snort)) (result i32)
|
||||
|
@ -361,7 +361,7 @@ assertErrorMessage(() => wasmEvalText(
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $node (struct (field i32)))
|
||||
(type $node2 (struct (field i32) (field f32)))
|
||||
(type $snort (struct (field f64)))
|
||||
|
@ -374,7 +374,7 @@ assertErrorMessage(() => wasmEvalText(
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $node (struct (field i32)))
|
||||
(type $node2 (struct (field (mut i32)) (field f32)))
|
||||
(func $f (param $p (ref $node)) (result (ref $node2))
|
||||
|
@ -384,7 +384,7 @@ assertErrorMessage(() => wasmEvalText(
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $node (struct (field (mut i32))))
|
||||
(type $node2 (struct (field i32) (field f32)))
|
||||
(func $f (param $p (ref $node)) (result (ref $node2))
|
||||
|
@ -396,7 +396,7 @@ assertErrorMessage(() => wasmEvalText(
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $node (struct (field i32)))
|
||||
(func $f (param $p (ref $node)) (result anyref)
|
||||
(struct.narrow i32 anyref (get_local 0))))`),
|
||||
|
@ -405,7 +405,7 @@ assertErrorMessage(() => wasmEvalText(
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $node (struct (field i32)))
|
||||
(func $f (param $p (ref $node)) (result anyref)
|
||||
(struct.narrow anyref i32 (get_local 0))))`),
|
||||
|
@ -416,7 +416,7 @@ assertErrorMessage(() => wasmEvalText(
|
|||
|
||||
checkInvalid(funcBody({locals:[],
|
||||
body:[
|
||||
RefNull,
|
||||
RefNullCode,
|
||||
MiscPrefix, StructNarrow, I32Code, AnyrefCode,
|
||||
DropCode
|
||||
]}),
|
||||
|
@ -424,7 +424,7 @@ checkInvalid(funcBody({locals:[],
|
|||
|
||||
checkInvalid(funcBody({locals:[],
|
||||
body:[
|
||||
RefNull,
|
||||
RefNullCode,
|
||||
MiscPrefix, StructNarrow, AnyrefCode, I32Code,
|
||||
DropCode
|
||||
]}),
|
||||
|
@ -434,7 +434,7 @@ checkInvalid(funcBody({locals:[],
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $node (struct (field i32)))
|
||||
(func $f (param $p (ref $node)) (result anyref)
|
||||
(struct.narrow (ref $node) anyref (get_local 0))))`),
|
||||
|
@ -445,7 +445,7 @@ assertErrorMessage(() => wasmEvalText(
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $node (struct (field i32)))
|
||||
(type $node2 (struct (field i32) (field f32)))
|
||||
(func $f (param $p (ref $node2)) (result anyref)
|
||||
|
@ -458,7 +458,7 @@ assertErrorMessage(() => wasmEvalText(
|
|||
assertErrorMessage(function() {
|
||||
let ins = wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $node (struct (field i32)))
|
||||
(func (export "test")
|
||||
(drop (call $f (ref.null))))
|
||||
|
@ -474,7 +474,7 @@ assertErrorMessage(function() {
|
|||
assertErrorMessage(function() {
|
||||
let ins = wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $node (struct (field (mut i32))))
|
||||
(func (export "test")
|
||||
(call $f (ref.null)))
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
var bin = wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $cons (struct
|
||||
(field $car i32)
|
||||
(field $cdr (ref $cons))))
|
||||
|
@ -69,7 +69,7 @@ assertEq(WebAssembly.validate(bin), true);
|
|||
|
||||
new WebAssembly.Module(wasmTextToBinary(`
|
||||
(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $s (struct))
|
||||
(func $null (param (ref $s)) (result i32)
|
||||
(ref.is_null (get_local 0))))
|
||||
|
@ -79,7 +79,7 @@ new WebAssembly.Module(wasmTextToBinary(`
|
|||
|
||||
new WebAssembly.Module(wasmTextToBinary(`
|
||||
(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $s (struct (field i32)))
|
||||
(func $f (param (ref $s)) (call $g (get_local 0)))
|
||||
(func $g (param anyref) (unreachable)))
|
||||
|
@ -89,7 +89,7 @@ new WebAssembly.Module(wasmTextToBinary(`
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(`
|
||||
(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(func (param (ref $odd)) (unreachable)))
|
||||
`),
|
||||
SyntaxError, /Type label.*not found/);
|
||||
|
@ -99,7 +99,7 @@ SyntaxError, /Type label.*not found/);
|
|||
|
||||
wasmEvalText(`
|
||||
(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $s (struct (field i32)))
|
||||
(type $t (struct (field i32)))
|
||||
(func $f (param (ref $s)) (unreachable))
|
||||
|
@ -108,7 +108,7 @@ wasmEvalText(`
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(`
|
||||
(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $s (struct (field i32)))
|
||||
(type $t (struct (field f32))) ;; Incompatible type
|
||||
(func $f (param (ref $s)) (unreachable))
|
||||
|
@ -118,7 +118,7 @@ WebAssembly.CompileError, /expression has type ref.*but expected ref/);
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(`
|
||||
(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $s (struct (field i32)))
|
||||
(type $t (struct (field (mut i32)))) ;; Incompatible mutability
|
||||
(func $f (param (ref $s)) (unreachable))
|
||||
|
@ -131,7 +131,7 @@ WebAssembly.CompileError, /expression has type ref.*but expected ref/);
|
|||
|
||||
wasmEvalText(`
|
||||
(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $s (struct (field i32)))
|
||||
(type $t (struct (field i32)))
|
||||
(func $f (param (ref $s)) (local (ref $t)) (set_local 1 (get_local 0))))
|
||||
|
@ -139,7 +139,7 @@ wasmEvalText(`
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(`
|
||||
(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $s (struct (field i32)))
|
||||
(type $t (struct (field f32)))
|
||||
(func $f (param (ref $s)) (local (ref $t)) (set_local 1 (get_local 0))))
|
||||
|
@ -148,7 +148,7 @@ WebAssembly.CompileError, /expression has type ref.*but expected ref/);
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(`
|
||||
(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $s (struct (field i32)))
|
||||
(type $t (struct (field (mut i32))))
|
||||
(func $f (param (ref $s)) (unreachable))
|
||||
|
@ -161,7 +161,7 @@ WebAssembly.CompileError, /expression has type ref.*but expected ref/);
|
|||
|
||||
wasmEvalText(`
|
||||
(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $s (struct (field i32)))
|
||||
(type $t (struct (field i32)))
|
||||
(func $f (param (ref $s)) (result (ref $t)) (get_local 0)))
|
||||
|
@ -169,7 +169,7 @@ wasmEvalText(`
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(`
|
||||
(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $s (struct (field i32)))
|
||||
(type $t (struct (field f32)))
|
||||
(func $f (param (ref $s)) (result (ref $t)) (get_local 0)))
|
||||
|
@ -178,7 +178,7 @@ WebAssembly.CompileError, /expression has type ref.*but expected ref/);
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(`
|
||||
(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $s (struct (field i32)))
|
||||
(type $t (struct (field (mut i32))))
|
||||
(func $f (param (ref $s)) (result (ref $t)) (get_local 0)))
|
||||
|
@ -189,7 +189,7 @@ WebAssembly.CompileError, /expression has type ref.*but expected ref/);
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(`
|
||||
(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $x (func (param i32)))
|
||||
(func $f (param (ref $x)) (unreachable)))
|
||||
`),
|
||||
|
@ -197,7 +197,7 @@ SyntaxError, /Type label.*not found/);
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(`
|
||||
(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type (func (param i32)))
|
||||
(func $f (param (ref 0)) (unreachable)))
|
||||
`),
|
||||
|
@ -207,7 +207,7 @@ WebAssembly.CompileError, /does not reference a struct type/);
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(`
|
||||
(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $s (struct (field i32)))
|
||||
(func $f (param anyref) (call $g (get_local 0)))
|
||||
(func $g (param (ref $s)) (unreachable)))
|
||||
|
|
|
@ -17,7 +17,7 @@ const {Module,Instance} = WebAssembly;
|
|||
|
||||
let t =
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(import $check3 "" "check3" (func (param anyref) (param anyref) (param anyref)))
|
||||
(type $typeOfFn0
|
||||
(func (result i32) (param i32) (param anyref) (param i32)
|
||||
|
|
|
@ -28,7 +28,7 @@ const DEBUG = false;
|
|||
|
||||
let t =
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $typeOfFn0
|
||||
(func (result i32) (param i32) (param anyref) (param i32)
|
||||
(param anyref) (param anyref) (param i32)))
|
||||
|
|
|
@ -24,7 +24,7 @@ const DEBUG = false;
|
|||
|
||||
let t =
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(import $mkCons "" "mkCons" (func (result anyref)
|
||||
(param anyref) (param anyref)))
|
||||
(import $mkBoxedInt "" "mkBoxedInt" (func (result anyref)))
|
||||
|
|
|
@ -4,7 +4,7 @@ var conf = getBuildConfiguration();
|
|||
|
||||
var bin = wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
|
||||
(table 2 anyfunc)
|
||||
(elem (i32.const 0) $doit $doitagain)
|
||||
|
@ -226,7 +226,7 @@ assertEq(withfloats._4, 0x1337);
|
|||
|
||||
var stress = wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $node (struct (field i32) (field (ref $node))))
|
||||
(func (export "iota1") (param $n i32) (result anyref)
|
||||
(local $list (ref $node))
|
||||
|
@ -254,7 +254,7 @@ assertEq(the_list, null);
|
|||
{
|
||||
let txt =
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
|
||||
(type $big (struct
|
||||
(field (mut i32))
|
||||
|
@ -314,7 +314,7 @@ assertEq(the_list, null);
|
|||
{
|
||||
let txt =
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
|
||||
(type $big (struct
|
||||
(field (mut i32))
|
||||
|
@ -389,7 +389,7 @@ assertEq(the_list, null);
|
|||
|
||||
var bin = wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
|
||||
(type $cons (struct (field i32) (field (ref $cons))))
|
||||
|
||||
|
@ -432,7 +432,7 @@ assertErrorMessage(() => ins.pop(),
|
|||
{
|
||||
var ins = wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $Node (struct (field i32)))
|
||||
(func (export "mk") (result anyref)
|
||||
(struct.new $Node (i32.const 37)))
|
||||
|
@ -450,7 +450,7 @@ assertErrorMessage(() => ins.pop(),
|
|||
{
|
||||
let ins = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
|
||||
(type $s (struct
|
||||
(field $x i32)
|
||||
|
@ -478,7 +478,7 @@ assertErrorMessage(() => ins.pop(),
|
|||
|
||||
assertErrorMessage(() => wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
|
||||
(type $s (struct (field $x i32)))
|
||||
(type $t (struct (field $x i32)))
|
||||
|
@ -492,7 +492,7 @@ assertErrorMessage(() => wasmTextToBinary(
|
|||
|
||||
assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(`
|
||||
(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $r (struct (field i32)))
|
||||
(func $f (param f64) (result anyref)
|
||||
(struct.new $r (get_local 0)))
|
||||
|
@ -503,7 +503,7 @@ WebAssembly.CompileError, /type mismatch/);
|
|||
|
||||
assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(`
|
||||
(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $r (struct (field i32) (field i32)))
|
||||
(func $f (result anyref)
|
||||
(struct.new $r (i32.const 0)))
|
||||
|
@ -514,7 +514,7 @@ WebAssembly.CompileError, /popping value from empty stack/);
|
|||
|
||||
assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(`
|
||||
(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $r (struct (field i32) (field i32)))
|
||||
(func $f (result anyref)
|
||||
(i32.const 0)
|
||||
|
@ -528,7 +528,7 @@ WebAssembly.CompileError, /unused values/);
|
|||
|
||||
assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(`
|
||||
(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type (func (param i32) (result i32)))
|
||||
(func $f (result anyref)
|
||||
(struct.new 0))
|
||||
|
@ -540,7 +540,7 @@ WebAssembly.CompileError, /not a struct type/);
|
|||
|
||||
wasmEvalText(`
|
||||
(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $p (struct (field i32)))
|
||||
(type $q (struct (field i32)))
|
||||
(func $f (result (ref $p))
|
||||
|
@ -551,7 +551,7 @@ wasmEvalText(`
|
|||
|
||||
wasmEvalText(`
|
||||
(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $s (struct (field i32))))
|
||||
`)
|
||||
|
||||
|
@ -559,7 +559,7 @@ wasmEvalText(`
|
|||
|
||||
wasmEvalText(`
|
||||
(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $s (struct)))
|
||||
`)
|
||||
|
||||
|
@ -567,7 +567,7 @@ wasmEvalText(`
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(`
|
||||
(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $s (struct (field $x i32)))
|
||||
(type $s (struct (field $y i32))))
|
||||
`),
|
||||
|
@ -577,35 +577,35 @@ SyntaxError, /duplicate type name/);
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(`
|
||||
(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $s))
|
||||
`),
|
||||
SyntaxError, /parsing wasm text/);
|
||||
|
||||
assertErrorMessage(() => wasmEvalText(`
|
||||
(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $s (field $x i32)))
|
||||
`),
|
||||
SyntaxError, /bad type definition/);
|
||||
|
||||
assertErrorMessage(() => wasmEvalText(`
|
||||
(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $s (struct (field $x i31))))
|
||||
`),
|
||||
SyntaxError, /parsing wasm text/);
|
||||
|
||||
assertErrorMessage(() => wasmEvalText(`
|
||||
(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $s (struct (fjeld $x i32))))
|
||||
`),
|
||||
SyntaxError, /parsing wasm text/);
|
||||
|
||||
assertErrorMessage(() => wasmEvalText(`
|
||||
(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $s (struct abracadabra)))
|
||||
`),
|
||||
SyntaxError, /parsing wasm text/);
|
||||
|
@ -614,7 +614,7 @@ SyntaxError, /parsing wasm text/);
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(`
|
||||
(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $s (struct))
|
||||
(type $f (func (param i32) (result i32)))
|
||||
(func (type 0) (param i32) (result i32) (unreachable)))
|
||||
|
@ -626,7 +626,7 @@ WebAssembly.CompileError, /signature index references non-signature/);
|
|||
{
|
||||
let ins = wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $s (struct
|
||||
(field i32)
|
||||
(field (mut i64))))
|
||||
|
@ -651,7 +651,7 @@ var bad = new Uint8Array([0x00, 0x61, 0x73, 0x6d,
|
|||
|
||||
0x2a, // GcFeatureOptIn section
|
||||
0x01, // Section size
|
||||
0x02, // Version
|
||||
0x03, // Version
|
||||
|
||||
0x01, // Type section
|
||||
0x03, // Section size
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
{
|
||||
let ins = wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(table (export "t") 10 anyref)
|
||||
(type $dummy (struct (field i32)))
|
||||
(func (export "set_anyref") (param i32) (param anyref)
|
||||
|
@ -37,7 +37,7 @@
|
|||
{
|
||||
let ins = wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(type $S (struct (field i32) (field f64)))
|
||||
(table (export "t") 2 anyref)
|
||||
(func (export "f") (result i32)
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
new WebAssembly.Module(wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(table 10 anyref))`));
|
||||
|
||||
// Wasm: Import table-of-anyref
|
||||
|
@ -16,13 +16,13 @@ new WebAssembly.Module(wasmTextToBinary(
|
|||
|
||||
new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(table (import "m" "t") 10 anyref))`)),
|
||||
{m:{t: new WebAssembly.Table({element:"anyref", initial:10})}});
|
||||
|
||||
new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(import "m" "t" (table 10 anyref)))`)),
|
||||
{m:{t: new WebAssembly.Table({element:"anyref", initial:10})}});
|
||||
|
||||
|
@ -31,7 +31,7 @@ new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
|
|||
{
|
||||
let ins = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(table (export "t") 10 anyref))`)));
|
||||
let t = ins.exports.t;
|
||||
assertEq(t.length, 10);
|
||||
|
@ -44,7 +44,7 @@ new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
|
|||
{
|
||||
let ins = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(table (export "t") 10 anyref))`)));
|
||||
let t = ins.exports.t;
|
||||
let objs = [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}];
|
||||
|
@ -62,7 +62,7 @@ new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
|
|||
{
|
||||
let ins = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(table (export "t") 10 anyref)
|
||||
(func (export "f")
|
||||
(table.copy (i32.const 5) (i32.const 0) (i32.const 3))))`)));
|
||||
|
@ -87,7 +87,7 @@ new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
|
|||
|
||||
assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(func $f1 (result i32) (i32.const 0))
|
||||
(table 10 anyref)
|
||||
(elem (i32.const 0) $f1))`)),
|
||||
|
@ -98,7 +98,7 @@ assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
|||
|
||||
assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(func $f1 (result i32) (i32.const 0))
|
||||
(table 10 anyref)
|
||||
(elem passive $f1)
|
||||
|
@ -112,7 +112,7 @@ assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
|||
assertErrorMessage(
|
||||
() => new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(import "m" "t" (table 10 anyref)))`)),
|
||||
{m:{t: new WebAssembly.Table({element:"anyfunc", initial:10})}}),
|
||||
WebAssembly.LinkError,
|
||||
|
@ -122,7 +122,7 @@ assertErrorMessage(
|
|||
|
||||
assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(table 10 anyref)
|
||||
(type $t (func (param i32) (result i32)))
|
||||
(func (result i32)
|
||||
|
@ -170,7 +170,7 @@ function dummy() { return 37 }
|
|||
{
|
||||
let ins = wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(table (export "t") 10 anyref)
|
||||
(func (export "f") (param i32) (result anyref)
|
||||
(table.get (get_local 0))))`);
|
||||
|
@ -186,7 +186,7 @@ function dummy() { return 37 }
|
|||
|
||||
assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(table 10 anyref)
|
||||
(func (export "f") (param f64) (result anyref)
|
||||
(table.get (get_local 0))))`)),
|
||||
|
@ -206,7 +206,7 @@ assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
|||
|
||||
assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(table 10 anyfunc)
|
||||
(func (export "f") (param i32)
|
||||
(drop (table.get (get_local 0)))))`)),
|
||||
|
@ -229,7 +229,7 @@ assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
|||
{
|
||||
let ins = wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(table (export "t") 10 anyref)
|
||||
(func (export "set_anyref") (param i32) (param anyref)
|
||||
(table.set (get_local 0) (get_local 1)))
|
||||
|
@ -249,7 +249,7 @@ assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
|||
|
||||
assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(table 10 anyref)
|
||||
(func (export "f") (param f64)
|
||||
(table.set (get_local 0) (ref.null))))`)),
|
||||
|
@ -260,7 +260,7 @@ assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
|||
|
||||
assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(table 10 anyref)
|
||||
(func (export "f") (param f64)
|
||||
(table.set (i32.const 0) (get_local 0))))`)),
|
||||
|
@ -273,7 +273,7 @@ assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
|||
|
||||
assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(table 10 anyfunc)
|
||||
(func (export "f") (param anyref)
|
||||
(table.set (i32.const 0) (get_local 0))))`)),
|
||||
|
@ -284,7 +284,7 @@ assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
|||
|
||||
assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(func (export "f") (param anyref)
|
||||
(table.set (i32.const 0) (get_local 0))))`)),
|
||||
WebAssembly.CompileError,
|
||||
|
@ -298,7 +298,7 @@ assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
|||
|
||||
let ins = wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(table (export "t") 10 20 anyref)
|
||||
(func (export "grow") (param i32) (result i32)
|
||||
(table.grow (get_local 0) (ref.null))))`);
|
||||
|
@ -327,7 +327,7 @@ assertEq(ins.exports.t.length, 20)
|
|||
{
|
||||
let ins = wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(table 10 anyref)
|
||||
(func (export "grow") (param i32) (result i32)
|
||||
(table.grow (get_local 0) (ref.null))))`);
|
||||
|
@ -341,7 +341,7 @@ assertEq(ins.exports.t.length, 20)
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2) ;; Required because of the 'anyref' null value below
|
||||
(gc_feature_opt_in 3) ;; Required because of the 'anyref' null value below
|
||||
(table $t 2 anyfunc)
|
||||
(func $f
|
||||
(drop (table.grow (i32.const 1) (ref.null)))))`),
|
||||
|
@ -352,7 +352,7 @@ assertErrorMessage(() => wasmEvalText(
|
|||
|
||||
assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(table 10 anyref)
|
||||
(func (export "f") (param f64)
|
||||
(table.grow (get_local 0) (ref.null))))`)),
|
||||
|
@ -363,7 +363,7 @@ assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
|||
|
||||
assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(func (export "f") (param i32)
|
||||
(table.grow (get_local 0) (ref.null))))`)),
|
||||
WebAssembly.CompileError,
|
||||
|
@ -377,7 +377,7 @@ for (let visibility of ['', '(export "t")', '(import "m" "t")']) {
|
|||
maximum: 20})}};
|
||||
let ins = wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(table ${visibility} 10 20 anyref)
|
||||
(func (export "grow") (param i32) (result i32)
|
||||
(table.grow (get_local 0) (ref.null)))
|
||||
|
|
|
@ -43,7 +43,7 @@ assertEq(ins.g(1, 10), 14);
|
|||
|
||||
var ins = wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(table $t0 (import "m" "t") 2 anyfunc)
|
||||
(table $t1 (export "t1") 2 anyfunc)
|
||||
(table 1 anyref)
|
||||
|
@ -64,7 +64,7 @@ var exp = {m:{t0: new WebAssembly.Table({element:"anyfunc", initial:2}),
|
|||
t3: new WebAssembly.Table({element:"anyref", initial:5})}};
|
||||
var ins = wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
|
||||
(table $t0 (import "m" "t0") 2 anyfunc)
|
||||
(type $id_i32_t (func (param i32) (result i32)))
|
||||
|
@ -113,7 +113,7 @@ var exp = {m:{t0: new WebAssembly.Table({element:"anyref", initial:2}),
|
|||
t1: new WebAssembly.Table({element:"anyref", initial:3})}};
|
||||
var ins = wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
|
||||
(table $t0 (import "m" "t0") 2 anyref)
|
||||
(table $t1 (import "m" "t1") 3 anyref)
|
||||
|
@ -136,7 +136,7 @@ var exp = {m:{t0: new WebAssembly.Table({element:"anyref", initial:2}),
|
|||
t1: new WebAssembly.Table({element:"anyref", initial:3})}};
|
||||
var ins = wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
|
||||
(table $t0 (import "m" "t0") 2 anyref)
|
||||
(table $t1 (import "m" "t1") 3 anyref)
|
||||
|
@ -154,7 +154,7 @@ assertEq(exp.m.t1.get(2), exp.m.t0.get(1));
|
|||
|
||||
var ins = wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(table $t0 2 anyref)
|
||||
(table $t1 2 anyref)
|
||||
(func (export "copy") (param $dest i32) (param $src i32) (param $len i32)
|
||||
|
@ -229,7 +229,7 @@ var exp = {m: {t0: tbl, t1:tbl}};
|
|||
|
||||
var ins = wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(import $t0 "m" "t0" (table 1 anyref))
|
||||
(import $t1 "m" "t1" (table 1 anyref))
|
||||
(table $t2 (export "t2") 1 anyfunc)
|
||||
|
@ -333,7 +333,7 @@ assertErrorMessage(() => ins2.exports.do1(12, 2.0),
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(table $t0 2 anyref)
|
||||
(table $t1 2 anyref)
|
||||
(func $f (result anyref)
|
||||
|
@ -343,7 +343,7 @@ assertErrorMessage(() => wasmEvalText(
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(table $t0 2 anyref)
|
||||
(table $t1 2 anyref)
|
||||
(func $f (param anyref)
|
||||
|
@ -353,7 +353,7 @@ assertErrorMessage(() => wasmEvalText(
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(table $t0 2 anyref)
|
||||
(table $t1 2 anyref)
|
||||
(func $f (param anyref)
|
||||
|
@ -363,7 +363,7 @@ assertErrorMessage(() => wasmEvalText(
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(table $t0 2 anyref)
|
||||
(table $t1 2 anyref)
|
||||
(func $f (param anyref)
|
||||
|
@ -373,7 +373,7 @@ assertErrorMessage(() => wasmEvalText(
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(table $t0 2 anyref)
|
||||
(table $t1 2 anyref)
|
||||
(func $f (result i32)
|
||||
|
@ -383,7 +383,7 @@ assertErrorMessage(() => wasmEvalText(
|
|||
|
||||
assertErrorMessage(() => wasmEvalText(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
(table $t0 2 anyref)
|
||||
(table $t1 2 anyref)
|
||||
(func $f (result i32)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
for ( let prefix of ['', '(table $prefix 0 32 anyfunc)']) {
|
||||
let mod = new WebAssembly.Module(wasmTextToBinary(
|
||||
`(module
|
||||
(gc_feature_opt_in 2)
|
||||
(gc_feature_opt_in 3)
|
||||
${prefix}
|
||||
(table $tbl 0 anyref)
|
||||
(import $item "m" "item" (func (result anyref)))
|
||||
|
|
|
@ -528,20 +528,60 @@ var m = new Module(wasmTextToBinary(`
|
|||
(export "g" $g))
|
||||
`));
|
||||
|
||||
// Active segments are applied in order (this is observable if they overlap).
|
||||
//
|
||||
// Without bulk memory, all range checking for tables and memory happens before
|
||||
// any writes happen, and any OOB will force no writing to happen at all.
|
||||
//
|
||||
// With bulk memory, active segments are applied first for tables and then for
|
||||
// memories. Bounds checking happens for each byte or table element written.
|
||||
// The first OOB aborts the initialization process, leaving written data in
|
||||
// place. Notably, any OOB in table initialization will prevent any memory
|
||||
// initialization from happening at all.
|
||||
|
||||
var npages = 2;
|
||||
var mem = new Memory({initial:npages});
|
||||
var mem8 = new Uint8Array(mem.buffer);
|
||||
var tbl = new Table({initial:2, element:"anyfunc"});
|
||||
|
||||
assertErrorMessage(() => new Instance(m, {a:{mem, tbl, memOff:1, tblOff:2}}), LinkError, /elem segment does not fit/);
|
||||
assertErrorMessage(() => new Instance(m, {a:{mem, tbl, memOff:1, tblOff:2}}),
|
||||
LinkError,
|
||||
/elem segment does not fit/);
|
||||
if (wasmBulkMemSupported()) {
|
||||
// The first active element segment is applied, but the second active
|
||||
// element segment is completely OOB.
|
||||
assertEq(typeof tbl.get(0), "function");
|
||||
assertEq(tbl.get(1), null);
|
||||
} else {
|
||||
assertEq(tbl.get(0), null);
|
||||
assertEq(tbl.get(1), null);
|
||||
}
|
||||
assertEq(mem8[0], 0);
|
||||
assertEq(mem8[1], 0);
|
||||
assertEq(tbl.get(0), null);
|
||||
|
||||
assertErrorMessage(() => new Instance(m, {a:{mem, tbl, memOff:npages*64*1024, tblOff:1}}), LinkError, /data segment does not fit/);
|
||||
assertEq(mem8[0], 0);
|
||||
assertEq(tbl.get(0), null);
|
||||
assertEq(tbl.get(1), null);
|
||||
tbl.set(0, null);
|
||||
tbl.set(1, null);
|
||||
|
||||
assertErrorMessage(() => new Instance(m, {a:{mem, tbl, memOff:npages*64*1024, tblOff:1}}),
|
||||
LinkError,
|
||||
/data segment does not fit/);
|
||||
if (wasmBulkMemSupported()) {
|
||||
// The first and second active element segments are applied fully. The
|
||||
// first active data segment applies, but the second one is completely OOB.
|
||||
assertEq(typeof tbl.get(0), "function");
|
||||
assertEq(typeof tbl.get(1), "function");
|
||||
assertEq(mem8[0], 1);
|
||||
} else {
|
||||
assertEq(tbl.get(0), null);
|
||||
assertEq(tbl.get(1), null);
|
||||
assertEq(mem8[0], 0);
|
||||
}
|
||||
|
||||
tbl.set(0, null);
|
||||
tbl.set(1, null);
|
||||
mem8[0] = 0;
|
||||
|
||||
// Both element and data segments apply successfully without OOB
|
||||
|
||||
var i = new Instance(m, {a:{mem, tbl, memOff:npages*64*1024-1, tblOff:1}});
|
||||
assertEq(mem8[0], 1);
|
||||
|
@ -549,6 +589,52 @@ assertEq(mem8[npages*64*1024-1], 2);
|
|||
assertEq(tbl.get(0), i.exports.f);
|
||||
assertEq(tbl.get(1), i.exports.g);
|
||||
|
||||
// Element segment applies partially and prevents subsequent elem segment and
|
||||
// data segment from being applied.
|
||||
|
||||
if (wasmBulkMemSupported()) {
|
||||
let m = new Module(wasmTextToBinary(
|
||||
`(module
|
||||
(import "" "mem" (memory 1))
|
||||
(import "" "tbl" (table 3 anyfunc))
|
||||
(elem (i32.const 1) $f $g $h) ;; fails after $f and $g
|
||||
(elem (i32.const 0) $f) ;; is not applied
|
||||
(data (i32.const 0) "\\01") ;; is not applied
|
||||
(func $f)
|
||||
(func $g)
|
||||
(func $h))`));
|
||||
let mem = new Memory({initial:1});
|
||||
let tbl = new Table({initial:3, element:"anyfunc"});
|
||||
assertErrorMessage(() => new Instance(m, {"":{mem, tbl}}),
|
||||
LinkError,
|
||||
/elem segment does not fit/);
|
||||
assertEq(tbl.get(0), null);
|
||||
assertEq(typeof tbl.get(1), "function");
|
||||
assertEq(typeof tbl.get(2), "function");
|
||||
let v = new Uint8Array(mem.buffer);
|
||||
assertEq(v[0], 0);
|
||||
}
|
||||
|
||||
// Data segment applies partially and prevents subsequent data segment from
|
||||
// being applied.
|
||||
|
||||
if (wasmBulkMemSupported()) {
|
||||
let m = new Module(wasmTextToBinary(
|
||||
`(module
|
||||
(import "" "mem" (memory 1))
|
||||
(data (i32.const 65534) "\\01\\02\\03") ;; fails after 1 and 2
|
||||
(data (i32.const 0) "\\04") ;; is not applied
|
||||
)`));
|
||||
let mem = new Memory({initial:1});
|
||||
assertErrorMessage(() => new Instance(m, {"":{mem}}),
|
||||
LinkError,
|
||||
/data segment does not fit/);
|
||||
let v = new Uint8Array(mem.buffer);
|
||||
assertEq(v[65534], 1);
|
||||
assertEq(v[65535], 2);
|
||||
assertEq(v[0], 0);
|
||||
}
|
||||
|
||||
// Elem segments on imported tables
|
||||
|
||||
var m = new Module(wasmTextToBinary(`
|
||||
|
@ -730,7 +816,7 @@ assertEq(e.call(), 1090);
|
|||
g.evaluate("function f1() { assertCorrectRealm(); return 123; }");
|
||||
g.mem = new Memory({initial:8});
|
||||
|
||||
// The current_memory builtin asserts cx->realm matches instance->realm so
|
||||
// The memory.size builtin asserts cx->realm matches instance->realm so
|
||||
// we call it here.
|
||||
var i1 = new Instance(new Module(wasmTextToBinary(`
|
||||
(module
|
||||
|
@ -740,8 +826,8 @@ assertEq(e.call(), 1090);
|
|||
(func $test (result i32)
|
||||
(i32.add
|
||||
(i32.add
|
||||
(i32.add (current_memory) (call $imp1))
|
||||
(current_memory))
|
||||
(i32.add (memory.size) (call $imp1))
|
||||
(memory.size))
|
||||
(call $imp2)))
|
||||
(export "impstub" $imp1)
|
||||
(export "test" $test))
|
||||
|
@ -757,7 +843,7 @@ assertEq(e.call(), 1090);
|
|||
(module
|
||||
(import $imp "a" "othertest" (result i32))
|
||||
(import "a" "m" (memory 1))
|
||||
(func (result i32) (i32.add (call $imp) (current_memory)))
|
||||
(func (result i32) (i32.add (call $imp) (memory.size)))
|
||||
(export "test" 1))
|
||||
`;
|
||||
g.i1 = i1;
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
// then we grow mem1
|
||||
wasmEvalText(`(module
|
||||
(memory (import "" "memory") 2 4 shared)
|
||||
(func (export "g") (drop (grow_memory (i32.const 1)))))`,
|
||||
(func (export "g") (drop (memory.grow (i32.const 1)))))`,
|
||||
{"": {memory: mem1}}).exports.g();
|
||||
|
||||
// after growing mem1, mem2 can be accessed at index
|
||||
|
|
|
@ -129,14 +129,14 @@ const WASMPAGE = 65536;
|
|||
}
|
||||
|
||||
|
||||
// basic current_memory and grow_memory operation, with bounds checking near the
|
||||
// basic memory.size and memory.grow operation, with bounds checking near the
|
||||
// valid/invalid boundary
|
||||
|
||||
{
|
||||
let text = `(module
|
||||
(memory (export "memory") 2 4 shared)
|
||||
(func (export "c") (result i32) current_memory)
|
||||
(func (export "g") (result i32) (grow_memory (i32.const 1)))
|
||||
(func (export "c") (result i32) memory.size)
|
||||
(func (export "g") (result i32) (memory.grow (i32.const 1)))
|
||||
(func (export "l") (param i32) (result i32) (i32.load (get_local 0)))
|
||||
(func (export "s") (param i32) (param i32) (i32.store (get_local 0) (get_local 1))))`;
|
||||
let mod = new WebAssembly.Module(wasmTextToBinary(text));
|
||||
|
@ -147,7 +147,7 @@ const WASMPAGE = 65536;
|
|||
let b1 = mem.buffer;
|
||||
assertEq(exp.c(), 2);
|
||||
assertEq(b1.byteLength, WASMPAGE*2);
|
||||
assertEq(mem.buffer === b1, true); // current_memory does not affect buffer
|
||||
assertEq(mem.buffer === b1, true); // memory.size does not affect buffer
|
||||
exp.s(WASMPAGE*2-4, 0x12345678) // access near end
|
||||
assertEq(exp.l(WASMPAGE*2-4), 0x12345678);
|
||||
assertErrorMessage(() => exp.l(WASMPAGE*2), // beyond current end (but below max)
|
||||
|
|
|
@ -311,7 +311,7 @@ function checkPassiveElemSegment(mangle, err) {
|
|||
body.push(1); // Flag: Passive
|
||||
body.push(AnyFuncCode + (mangle == "type" ? 1 : 0)); // always anyfunc
|
||||
body.push(1); // Element count
|
||||
body.push(PlaceholderRefFunc + (mangle == "ref.func" ? 1 : 0)); // always ref.func
|
||||
body.push(RefFuncCode + (mangle == "ref.func" ? 1 : 0)); // always ref.func
|
||||
body.push(0); // func index
|
||||
body.push(EndCode + (mangle == "end" ? 1 : 0));
|
||||
return body;
|
||||
|
@ -332,8 +332,41 @@ function checkPassiveElemSegment(mangle, err) {
|
|||
|
||||
checkPassiveElemSegment("");
|
||||
checkPassiveElemSegment("type", /passive segments can only contain function references/);
|
||||
checkPassiveElemSegment("ref.func", /failed to read ref.func operation/);
|
||||
checkPassiveElemSegment("end", /failed to read end of ref.func expression/);
|
||||
checkPassiveElemSegment("ref.func", /failed to read initializer operation/);
|
||||
checkPassiveElemSegment("end", /failed to read end of initializer expression/);
|
||||
|
||||
// Passive element segments can contain literal null values.
|
||||
|
||||
{
|
||||
let txt =
|
||||
`(module
|
||||
(table (export "t") 10 anyfunc)
|
||||
(elem (i32.const 1) $m)
|
||||
(elem (i32.const 3) $m)
|
||||
(elem (i32.const 6) $m)
|
||||
(elem (i32.const 8) $m)
|
||||
(elem passive $f ref.null $g ref.null $h)
|
||||
(func $m)
|
||||
(func $f)
|
||||
(func $g)
|
||||
(func $h)
|
||||
(func (export "doit") (param $idx i32)
|
||||
(table.init 4 (get_local $idx) (i32.const 0) (i32.const 5))))`;
|
||||
let ins = wasmEvalText(txt);
|
||||
ins.exports.doit(0);
|
||||
ins.exports.doit(5);
|
||||
assertEq(typeof ins.exports.t.get(0), "function");
|
||||
assertEq(ins.exports.t.get(1), null);
|
||||
assertEq(typeof ins.exports.t.get(2), "function");
|
||||
assertEq(ins.exports.t.get(0) == ins.exports.t.get(2), false);
|
||||
assertEq(ins.exports.t.get(3), null);
|
||||
assertEq(typeof ins.exports.t.get(4), "function");
|
||||
assertEq(typeof ins.exports.t.get(5), "function");
|
||||
assertEq(ins.exports.t.get(6), null);
|
||||
assertEq(typeof ins.exports.t.get(7), "function");
|
||||
assertEq(ins.exports.t.get(8), null);
|
||||
assertEq(typeof ins.exports.t.get(9), "function");
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------//
|
||||
//---------------------------------------------------------------------//
|
||||
|
|
|
@ -88,27 +88,27 @@ if (getBuildConfiguration()["arm-simulator"]) {
|
|||
}
|
||||
}
|
||||
|
||||
// current_memory is a callout.
|
||||
// memory.size is a callout.
|
||||
test(`(module
|
||||
(memory 1)
|
||||
(func (export "") (result i32)
|
||||
current_memory
|
||||
memory.size
|
||||
)
|
||||
)`,
|
||||
this,
|
||||
["", ">", "0,>", "<,0,>", "current_memory,0,>", "<,0,>", "0,>", ">", ""],
|
||||
["", ">", "0,>", "<,0,>", "memory.size,0,>", "<,0,>", "0,>", ">", ""],
|
||||
);
|
||||
|
||||
// grow_memory is a callout.
|
||||
// memory.grow is a callout.
|
||||
test(`(module
|
||||
(memory 1)
|
||||
(func (export "") (result i32)
|
||||
i32.const 1
|
||||
grow_memory
|
||||
memory.grow
|
||||
)
|
||||
)`,
|
||||
this,
|
||||
["", ">", "0,>", "<,0,>", "grow_memory,0,>", "<,0,>", "0,>", ">", ""],
|
||||
["", ">", "0,>", "<,0,>", "memory.grow,0,>", "<,0,>", "0,>", ">", ""],
|
||||
);
|
||||
|
||||
// A few math builtins.
|
||||
|
|
|
@ -5,14 +5,14 @@ try {
|
|||
(func $func0
|
||||
(nop)
|
||||
(f64.load offset=59 align=1 (i32.const 0))
|
||||
(current_memory)
|
||||
(current_memory)
|
||||
(current_memory)
|
||||
(current_memory)
|
||||
(current_memory)
|
||||
(current_memory)
|
||||
(current_memory)
|
||||
(current_memory)
|
||||
(memory.size)
|
||||
(memory.size)
|
||||
(memory.size)
|
||||
(memory.size)
|
||||
(memory.size)
|
||||
(memory.size)
|
||||
(memory.size)
|
||||
(memory.size)
|
||||
(i64.rem_s (i64.const 17) (i64.xor (i64.const 17) (i64.xor (i64.const 17) (i64.xor (i64.xor (i64.const 17) (i64.const 17)) (i64.xor (i64.const 17) (i64.const 17))))))
|
||||
|
||||
(i64.rem_s
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Bug 1341650:
|
||||
// - when compiled with Ion, pass the TLS register to current_memory;
|
||||
// - when compiled with Ion, pass the TLS register to memory.size;
|
||||
// - when compiled with Baseline, don't clobber the last stack slot when
|
||||
// calling into current_memory/grow_memory;
|
||||
// calling into memory.size/memory.grow;
|
||||
|
||||
// This toy module starts with an empty memory, then tries to set values at different
|
||||
// indexes, automatically growing memory when that would trigger an out of
|
||||
|
@ -12,11 +12,11 @@ let i = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(`
|
|||
(module
|
||||
(memory $mem (export "mem") 0 65535)
|
||||
|
||||
(func (export "cur_mem") (result i32) (current_memory))
|
||||
(func (export "cur_mem") (result i32) (memory.size))
|
||||
|
||||
(func $maybeGrow (param $i i32) (local $smem i32)
|
||||
;; get current_memory in number of bytes, not pages.
|
||||
current_memory
|
||||
;; get memory.size in number of bytes, not pages.
|
||||
memory.size
|
||||
i64.extend_u/i32
|
||||
i64.const 65536
|
||||
i64.mul
|
||||
|
@ -39,7 +39,7 @@ let i = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(`
|
|||
|
||||
;; subtract to that the size of the current memory in pages;
|
||||
;; that's the amount of pages we want to grow, minus one.
|
||||
current_memory
|
||||
memory.size
|
||||
i64.extend_u/i32
|
||||
|
||||
i64.sub
|
||||
|
@ -50,7 +50,7 @@ let i = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(`
|
|||
|
||||
;; get back to i32 and grow memory.
|
||||
i32.wrap/i64
|
||||
grow_memory
|
||||
memory.grow
|
||||
drop
|
||||
end
|
||||
)
|
||||
|
|
|
@ -16,7 +16,7 @@ wasmFullPass(`(module
|
|||
(func $test (result i32)
|
||||
(i32.store (i32.const 0) (i32.const 1))
|
||||
(i32.store (i32.const 65532) (i32.const 10))
|
||||
(drop (grow_memory (i32.const 99)))
|
||||
(drop (memory.grow (i32.const 99)))
|
||||
(i32.store (i32.const 6553596) (i32.const 100))
|
||||
(i32.add
|
||||
(i32.load (i32.const 0))
|
||||
|
@ -30,7 +30,7 @@ wasmFullPass(`(module
|
|||
var exports = wasmEvalText(`(module
|
||||
(import $imp "" "imp")
|
||||
(memory 1)
|
||||
(func $grow (drop (grow_memory (i32.const 99))))
|
||||
(func $grow (drop (memory.grow (i32.const 99))))
|
||||
(export "grow" $grow)
|
||||
(func $test (result i32)
|
||||
(i32.store (i32.const 0) (i32.const 1))
|
||||
|
@ -57,7 +57,7 @@ var exports1 = wasmEvalText(`(module
|
|||
(import "" "mem" (memory 1))
|
||||
(func $grow
|
||||
(i32.store (i32.const 65532) (i32.const 10))
|
||||
(drop (grow_memory (i32.const 99)))
|
||||
(drop (memory.grow (i32.const 99)))
|
||||
(i32.store (i32.const 6553596) (i32.const 100)))
|
||||
(export "grow" $grow)
|
||||
)`, {"":{mem}}).exports;
|
||||
|
@ -84,9 +84,9 @@ var mem = new Memory({initial:1});
|
|||
new Int32Array(mem.buffer)[0] = 42;
|
||||
var mod = new Module(wasmTextToBinary(`(module
|
||||
(import "" "mem" (memory 1))
|
||||
(func $gm (param i32) (result i32) (grow_memory (get_local 0)))
|
||||
(func $gm (param i32) (result i32) (memory.grow (get_local 0)))
|
||||
(export "grow_memory" $gm)
|
||||
(func $cm (result i32) (current_memory))
|
||||
(func $cm (result i32) (memory.size))
|
||||
(export "current_memory" $cm)
|
||||
(func $ld (param i32) (result i32) (i32.load (get_local 0)))
|
||||
(export "load" $ld)
|
||||
|
|
|
@ -205,13 +205,13 @@ assertEq(tbl.get(0).foo, 42);
|
|||
(function testCrossRealmCall() {
|
||||
var g = newGlobal({sameCompartmentAs: this});
|
||||
|
||||
// The current_memory builtin asserts cx->realm matches instance->realm so
|
||||
// The memory.size builtin asserts cx->realm matches instance->realm so
|
||||
// we call it here.
|
||||
var src = `
|
||||
(module
|
||||
(import "a" "t" (table 3 anyfunc))
|
||||
(import "a" "m" (memory 1))
|
||||
(func $f (result i32) (i32.add (i32.const 3) (current_memory)))
|
||||
(func $f (result i32) (i32.add (i32.const 3) (memory.size)))
|
||||
(elem (i32.const 0) $f))
|
||||
`;
|
||||
g.mem = new Memory({initial:4});
|
||||
|
@ -223,7 +223,7 @@ assertEq(tbl.get(0).foo, 42);
|
|||
(import "a" "t" (table 3 anyfunc))
|
||||
(import "a" "m" (memory 1))
|
||||
(type $v2i (func (result i32)))
|
||||
(func $call (param $i i32) (result i32) (i32.add (call_indirect $v2i (get_local $i)) (current_memory)))
|
||||
(func $call (param $i i32) (result i32) (i32.add (call_indirect $v2i (get_local $i)) (memory.size)))
|
||||
(export "call" $call))
|
||||
`)), {a:{t:g.tbl,m:g.mem}}).exports.call;
|
||||
|
||||
|
|
|
@ -19,5 +19,5 @@ assertEq(validate(wasmTextToBinary(`(module (export "run" 0))`)), false);
|
|||
assertEq(validate(wasmTextToBinary(`(module (func) (export "run" 0))`)), true);
|
||||
|
||||
// Feature-testing proof-of-concept.
|
||||
assertEq(validate(wasmTextToBinary(`(module (memory 1) (func (result i32) (current_memory)))`)), true);
|
||||
assertEq(validate(wasmTextToBinary(`(module (memory 1) (func (result i32) (grow_memory (i32.const 42))))`)), true);
|
||||
assertEq(validate(wasmTextToBinary(`(module (memory 1) (func (result i32) (memory.size)))`)), true);
|
||||
assertEq(validate(wasmTextToBinary(`(module (memory 1) (func (result i32) (memory.grow (i32.const 42))))`)), true);
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#ifndef wasmast_h
|
||||
#define wasmast_h
|
||||
|
||||
#include "mozilla/Variant.h"
|
||||
|
||||
#include "ds/LifoAlloc.h"
|
||||
#include "js/HashTable.h"
|
||||
#include "js/Vector.h"
|
||||
|
@ -41,6 +43,8 @@ using AstVector = mozilla::Vector<T, 0, LifoAllocPolicy<Fallible>>;
|
|||
template <class K, class V, class HP>
|
||||
using AstHashMap = HashMap<K, V, HP, LifoAllocPolicy<Fallible>>;
|
||||
|
||||
using mozilla::Variant;
|
||||
|
||||
typedef AstVector<bool> AstBoolVector;
|
||||
|
||||
class AstName {
|
||||
|
@ -396,20 +400,34 @@ enum class AstExprKind {
|
|||
ComparisonOperator,
|
||||
Const,
|
||||
ConversionOperator,
|
||||
CurrentMemory,
|
||||
#ifdef ENABLE_WASM_BULKMEM_OPS
|
||||
DataOrElemDrop,
|
||||
#endif
|
||||
Drop,
|
||||
ExtraConversionOperator,
|
||||
First,
|
||||
GetGlobal,
|
||||
GetLocal,
|
||||
GrowMemory,
|
||||
If,
|
||||
Load,
|
||||
#ifdef ENABLE_WASM_BULKMEM_OPS
|
||||
MemOrTableCopy,
|
||||
DataOrElemDrop,
|
||||
MemFill,
|
||||
MemOrTableCopy,
|
||||
MemOrTableInit,
|
||||
#endif
|
||||
MemoryGrow,
|
||||
MemorySize,
|
||||
Nop,
|
||||
Pop,
|
||||
RefNull,
|
||||
Return,
|
||||
SetGlobal,
|
||||
SetLocal,
|
||||
#ifdef ENABLE_WASM_GC
|
||||
StructNew,
|
||||
StructGet,
|
||||
StructSet,
|
||||
StructNarrow,
|
||||
#endif
|
||||
#ifdef ENABLE_WASM_GENERALIZED_TABLES
|
||||
TableGet,
|
||||
|
@ -417,18 +435,6 @@ enum class AstExprKind {
|
|||
TableSet,
|
||||
TableSize,
|
||||
#endif
|
||||
#ifdef ENABLE_WASM_GC
|
||||
StructNew,
|
||||
StructGet,
|
||||
StructSet,
|
||||
StructNarrow,
|
||||
#endif
|
||||
Nop,
|
||||
Pop,
|
||||
RefNull,
|
||||
Return,
|
||||
SetGlobal,
|
||||
SetLocal,
|
||||
TeeLocal,
|
||||
Store,
|
||||
TernaryOperator,
|
||||
|
@ -1048,18 +1054,18 @@ class AstStructNarrow : public AstExpr {
|
|||
};
|
||||
#endif
|
||||
|
||||
class AstCurrentMemory final : public AstExpr {
|
||||
class AstMemorySize final : public AstExpr {
|
||||
public:
|
||||
static const AstExprKind Kind = AstExprKind::CurrentMemory;
|
||||
explicit AstCurrentMemory() : AstExpr(Kind, ExprType::I32) {}
|
||||
static const AstExprKind Kind = AstExprKind::MemorySize;
|
||||
explicit AstMemorySize() : AstExpr(Kind, ExprType::I32) {}
|
||||
};
|
||||
|
||||
class AstGrowMemory final : public AstExpr {
|
||||
class AstMemoryGrow final : public AstExpr {
|
||||
AstExpr* operand_;
|
||||
|
||||
public:
|
||||
static const AstExprKind Kind = AstExprKind::GrowMemory;
|
||||
explicit AstGrowMemory(AstExpr* operand)
|
||||
static const AstExprKind Kind = AstExprKind::MemoryGrow;
|
||||
explicit AstMemoryGrow(AstExpr* operand)
|
||||
: AstExpr(Kind, ExprType::I32), operand_(operand) {}
|
||||
|
||||
AstExpr* operand() const { return operand_; }
|
||||
|
@ -1236,14 +1242,18 @@ class AstDataSegment : public AstNode {
|
|||
|
||||
typedef AstVector<AstDataSegment*> AstDataSegmentVector;
|
||||
|
||||
struct AstNullValue { };
|
||||
typedef Variant<AstRef, AstNullValue> AstElem;
|
||||
typedef AstVector<AstElem> AstElemVector;
|
||||
|
||||
class AstElemSegment : public AstNode {
|
||||
AstRef targetTable_;
|
||||
AstExpr* offsetIfActive_;
|
||||
AstRefVector elems_;
|
||||
AstElemVector elems_;
|
||||
|
||||
public:
|
||||
AstElemSegment(AstRef targetTable, AstExpr* offsetIfActive,
|
||||
AstRefVector&& elems)
|
||||
AstElemVector&& elems)
|
||||
: targetTable_(targetTable),
|
||||
offsetIfActive_(offsetIfActive),
|
||||
elems_(std::move(elems)) {}
|
||||
|
@ -1252,8 +1262,8 @@ class AstElemSegment : public AstNode {
|
|||
AstRef& targetTableRef() { return targetTable_; }
|
||||
bool isPassive() const { return offsetIfActive_ == nullptr; }
|
||||
AstExpr* offsetIfActive() const { return offsetIfActive_; }
|
||||
AstRefVector& elems() { return elems_; }
|
||||
const AstRefVector& elems() const { return elems_; }
|
||||
AstElemVector& elems() { return elems_; }
|
||||
const AstElemVector& elems() const { return elems_; }
|
||||
};
|
||||
|
||||
typedef AstVector<AstElemSegment*> AstElemSegmentVector;
|
||||
|
|
|
@ -6880,8 +6880,8 @@ class BaseCompiler final : public BaseCompilerInterface {
|
|||
const MIRTypeVector& sig, ExprType retType,
|
||||
SymbolicAddress builtin,
|
||||
bool pushReturnedValue = true);
|
||||
MOZ_MUST_USE bool emitGrowMemory();
|
||||
MOZ_MUST_USE bool emitCurrentMemory();
|
||||
MOZ_MUST_USE bool emitMemoryGrow();
|
||||
MOZ_MUST_USE bool emitMemorySize();
|
||||
|
||||
MOZ_MUST_USE bool emitRefNull();
|
||||
void emitRefIsNull();
|
||||
|
@ -9834,11 +9834,11 @@ bool BaseCompiler::emitInstanceCall(uint32_t lineOrBytecode,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool BaseCompiler::emitGrowMemory() {
|
||||
bool BaseCompiler::emitMemoryGrow() {
|
||||
uint32_t lineOrBytecode = readCallSiteLineOrBytecode();
|
||||
|
||||
Nothing arg;
|
||||
if (!iter_.readGrowMemory(&arg)) {
|
||||
if (!iter_.readMemoryGrow(&arg)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -9847,13 +9847,13 @@ bool BaseCompiler::emitGrowMemory() {
|
|||
}
|
||||
|
||||
return emitInstanceCall(lineOrBytecode, SigPI_, ExprType::I32,
|
||||
SymbolicAddress::GrowMemory);
|
||||
SymbolicAddress::MemoryGrow);
|
||||
}
|
||||
|
||||
bool BaseCompiler::emitCurrentMemory() {
|
||||
bool BaseCompiler::emitMemorySize() {
|
||||
uint32_t lineOrBytecode = readCallSiteLineOrBytecode();
|
||||
|
||||
if (!iter_.readCurrentMemory()) {
|
||||
if (!iter_.readMemorySize()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -9862,7 +9862,7 @@ bool BaseCompiler::emitCurrentMemory() {
|
|||
}
|
||||
|
||||
return emitInstanceCall(lineOrBytecode, SigP_, ExprType::I32,
|
||||
SymbolicAddress::CurrentMemory);
|
||||
SymbolicAddress::MemorySize);
|
||||
}
|
||||
|
||||
bool BaseCompiler::emitRefNull() {
|
||||
|
@ -10999,6 +10999,12 @@ bool BaseCompiler::emitBody() {
|
|||
CHECK_NEXT(emitGetGlobal());
|
||||
case uint16_t(Op::SetGlobal):
|
||||
CHECK_NEXT(emitSetGlobal());
|
||||
#ifdef ENABLE_WASM_GENERALIZED_TABLES
|
||||
case uint16_t(Op::TableGet):
|
||||
CHECK_NEXT(emitTableGet());
|
||||
case uint16_t(Op::TableSet):
|
||||
CHECK_NEXT(emitTableSet());
|
||||
#endif
|
||||
|
||||
// Select
|
||||
case uint16_t(Op::Select):
|
||||
|
@ -11491,10 +11497,10 @@ bool BaseCompiler::emitBody() {
|
|||
emitConversion(emitExtendI64_32, ValType::I64, ValType::I64));
|
||||
|
||||
// Memory Related
|
||||
case uint16_t(Op::GrowMemory):
|
||||
CHECK_NEXT(emitGrowMemory());
|
||||
case uint16_t(Op::CurrentMemory):
|
||||
CHECK_NEXT(emitCurrentMemory());
|
||||
case uint16_t(Op::MemoryGrow):
|
||||
CHECK_NEXT(emitMemoryGrow());
|
||||
case uint16_t(Op::MemorySize):
|
||||
CHECK_NEXT(emitMemorySize());
|
||||
|
||||
#ifdef ENABLE_WASM_GC
|
||||
case uint16_t(Op::RefEq):
|
||||
|
@ -11596,12 +11602,8 @@ bool BaseCompiler::emitBody() {
|
|||
CHECK_NEXT(emitMemOrTableInit(/*isMem=*/false));
|
||||
#endif // ENABLE_WASM_BULKMEM_OPS
|
||||
#ifdef ENABLE_WASM_GENERALIZED_TABLES
|
||||
case uint16_t(MiscOp::TableGet):
|
||||
CHECK_NEXT(emitTableGet());
|
||||
case uint16_t(MiscOp::TableGrow):
|
||||
CHECK_NEXT(emitTableGrow());
|
||||
case uint16_t(MiscOp::TableSet):
|
||||
CHECK_NEXT(emitTableSet());
|
||||
case uint16_t(MiscOp::TableSize):
|
||||
CHECK_NEXT(emitTableSize());
|
||||
#endif
|
||||
|
|
|
@ -621,12 +621,12 @@ void* wasm::AddressOf(SymbolicAddress imm, ABIFunctionType* abiType) {
|
|||
case SymbolicAddress::ATan2D:
|
||||
*abiType = Args_Double_DoubleDouble;
|
||||
return FuncCast(ecmaAtan2, *abiType);
|
||||
case SymbolicAddress::GrowMemory:
|
||||
case SymbolicAddress::MemoryGrow:
|
||||
*abiType = Args_General2;
|
||||
return FuncCast(Instance::growMemory_i32, *abiType);
|
||||
case SymbolicAddress::CurrentMemory:
|
||||
return FuncCast(Instance::memoryGrow_i32, *abiType);
|
||||
case SymbolicAddress::MemorySize:
|
||||
*abiType = Args_General1;
|
||||
return FuncCast(Instance::currentMemory_i32, *abiType);
|
||||
return FuncCast(Instance::memorySize_i32, *abiType);
|
||||
case SymbolicAddress::WaitI32:
|
||||
*abiType = Args_Int_GeneralGeneralGeneralInt64;
|
||||
return FuncCast(Instance::wait_i32, *abiType);
|
||||
|
@ -767,8 +767,8 @@ bool wasm::NeedsBuiltinThunk(SymbolicAddress sym) {
|
|||
case SymbolicAddress::LogD:
|
||||
case SymbolicAddress::PowD:
|
||||
case SymbolicAddress::ATan2D:
|
||||
case SymbolicAddress::GrowMemory:
|
||||
case SymbolicAddress::CurrentMemory:
|
||||
case SymbolicAddress::MemoryGrow:
|
||||
case SymbolicAddress::MemorySize:
|
||||
case SymbolicAddress::WaitI32:
|
||||
case SymbolicAddress::WaitI64:
|
||||
case SymbolicAddress::Wake:
|
||||
|
|
|
@ -132,8 +132,6 @@ enum class MemoryTableFlags {
|
|||
Default = 0x0,
|
||||
HasMaximum = 0x1,
|
||||
IsShared = 0x2,
|
||||
HasTableIndex =
|
||||
0x4, // UNOFFICIAL. There will be a separate flag for memory.
|
||||
};
|
||||
|
||||
enum class MemoryMasks { AllowUnshared = 0x1, AllowShared = 0x3 };
|
||||
|
@ -172,6 +170,8 @@ enum class Op {
|
|||
TeeLocal = 0x22,
|
||||
GetGlobal = 0x23,
|
||||
SetGlobal = 0x24,
|
||||
TableGet = 0x25, // Generalized table ops,
|
||||
TableSet = 0x26, // per proposal as of February 2019
|
||||
|
||||
// Memory-related operators
|
||||
I32Load = 0x28,
|
||||
|
@ -197,8 +197,8 @@ enum class Op {
|
|||
I64Store8 = 0x3c,
|
||||
I64Store16 = 0x3d,
|
||||
I64Store32 = 0x3e,
|
||||
CurrentMemory = 0x3f,
|
||||
GrowMemory = 0x40,
|
||||
MemorySize = 0x3f,
|
||||
MemoryGrow = 0x40,
|
||||
|
||||
// Constants
|
||||
I32Const = 0x41,
|
||||
|
@ -347,7 +347,9 @@ enum class Op {
|
|||
// GC ops
|
||||
RefNull = 0xd0,
|
||||
RefIsNull = 0xd1,
|
||||
RefEq = 0xd2, // Unofficial
|
||||
RefFunc = 0xd2,
|
||||
|
||||
RefEq = 0xf0, // Unofficial + experimental
|
||||
|
||||
FirstPrefix = 0xfc,
|
||||
MiscPrefix = 0xfc,
|
||||
|
@ -357,11 +359,6 @@ enum class Op {
|
|||
Limit = 0x100
|
||||
};
|
||||
|
||||
// TODO: RefFunc can't be incorporated into the opcode table until we're willing
|
||||
// to handle it generally and we've renumbered RefEq, but we need it to express
|
||||
// passive element segments.
|
||||
constexpr uint16_t PlaceholderRefFunc = 0xd2;
|
||||
|
||||
inline bool IsPrefixByte(uint8_t b) { return b >= uint8_t(Op::FirstPrefix); }
|
||||
|
||||
// Opcodes in the "miscellaneous" opcode space.
|
||||
|
@ -376,8 +373,7 @@ enum class MiscOp {
|
|||
I64TruncSSatF64 = 0x06,
|
||||
I64TruncUSatF64 = 0x07,
|
||||
|
||||
// Bulk memory operations. Note, these are unofficial, but in accordance
|
||||
// with the proposal as of June 2018.
|
||||
// Bulk memory operations, per proposal as of February 2019.
|
||||
MemInit = 0x08,
|
||||
DataDrop = 0x09,
|
||||
MemCopy = 0x0a,
|
||||
|
@ -386,11 +382,10 @@ enum class MiscOp {
|
|||
ElemDrop = 0x0d,
|
||||
TableCopy = 0x0e,
|
||||
|
||||
// Generalized tables (reftypes proposal). Note, these are unofficial.
|
||||
// Generalized table operations, per proposal as of February 2019.
|
||||
TableGrow = 0x0f,
|
||||
TableGet = 0x10,
|
||||
TableSet = 0x11,
|
||||
TableSize = 0x12,
|
||||
TableSize = 0x10,
|
||||
// TableFill = 0x11, // reserved
|
||||
|
||||
// Structure operations. Note, these are unofficial.
|
||||
StructNew = 0x50,
|
||||
|
|
|
@ -40,10 +40,10 @@ bool wasm::CraneliftCanCompile() {
|
|||
|
||||
static inline SymbolicAddress ToSymbolicAddress(BD_SymbolicAddress bd) {
|
||||
switch (bd) {
|
||||
case BD_SymbolicAddress::GrowMemory:
|
||||
return SymbolicAddress::GrowMemory;
|
||||
case BD_SymbolicAddress::CurrentMemory:
|
||||
return SymbolicAddress::CurrentMemory;
|
||||
case BD_SymbolicAddress::MemoryGrow:
|
||||
return SymbolicAddress::MemoryGrow;
|
||||
case BD_SymbolicAddress::MemorySize:
|
||||
return SymbolicAddress::MemorySize;
|
||||
case BD_SymbolicAddress::FloorF32:
|
||||
return SymbolicAddress::FloorF;
|
||||
case BD_SymbolicAddress::FloorF64:
|
||||
|
|
|
@ -1333,10 +1333,10 @@ static const char* ThunkedNativeToDescription(SymbolicAddress func) {
|
|||
return "call to asm.js native f64 Math.pow";
|
||||
case SymbolicAddress::ATan2D:
|
||||
return "call to asm.js native f64 Math.atan2";
|
||||
case SymbolicAddress::GrowMemory:
|
||||
return "call to native grow_memory (in wasm)";
|
||||
case SymbolicAddress::CurrentMemory:
|
||||
return "call to native current_memory (in wasm)";
|
||||
case SymbolicAddress::MemoryGrow:
|
||||
return "call to native memory.grow (in wasm)";
|
||||
case SymbolicAddress::MemorySize:
|
||||
return "call to native memory.size (in wasm)";
|
||||
case SymbolicAddress::WaitI32:
|
||||
return "call to native i32.wait (in wasm)";
|
||||
case SymbolicAddress::WaitI64:
|
||||
|
|
|
@ -352,6 +352,9 @@ bool ModuleGenerator::init(Metadata* maybeAsmJSMetadata) {
|
|||
return false;
|
||||
}
|
||||
for (uint32_t funcIndex : seg->elemFuncIndices) {
|
||||
if (funcIndex == NullFuncIndex) {
|
||||
continue;
|
||||
}
|
||||
exportedFuncs.infallibleEmplaceBack(funcIndex, false);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -312,7 +312,7 @@ Instance::callImport_anyref(Instance* instance, int32_t funcImportIndex,
|
|||
}
|
||||
|
||||
/* static */ uint32_t /* infallible */
|
||||
Instance::growMemory_i32(Instance* instance, uint32_t delta) {
|
||||
Instance::memoryGrow_i32(Instance* instance, uint32_t delta) {
|
||||
MOZ_ASSERT(!instance->isAsmJS());
|
||||
|
||||
JSContext* cx = TlsContext.get();
|
||||
|
@ -328,7 +328,7 @@ Instance::growMemory_i32(Instance* instance, uint32_t delta) {
|
|||
}
|
||||
|
||||
/* static */ uint32_t /* infallible */
|
||||
Instance::currentMemory_i32(Instance* instance) {
|
||||
Instance::memorySize_i32(Instance* instance) {
|
||||
// This invariant must hold when running Wasm code. Assert it here so we can
|
||||
// write tests for cross-realm calls.
|
||||
MOZ_ASSERT(TlsContext.get()->realm() == instance->realm());
|
||||
|
@ -747,31 +747,35 @@ void Instance::initElems(uint32_t tableIndex, const ElemSegment& seg,
|
|||
uint8_t* codeBaseTier = codeBase(tier);
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
uint32_t funcIndex = elemFuncIndices[srcOffset + i];
|
||||
if (funcIndex < funcImports.length()) {
|
||||
FuncImportTls& import = funcImportTls(funcImports[funcIndex]);
|
||||
JSFunction* fun = import.fun;
|
||||
if (IsExportedWasmFunction(fun)) {
|
||||
// This element is a wasm function imported from another
|
||||
// instance. To preserve the === function identity required by
|
||||
// the JS embedding spec, we must set the element to the
|
||||
// imported function's underlying CodeRange.funcTableEntry and
|
||||
// Instance so that future Table.get()s produce the same
|
||||
// function object as was imported.
|
||||
WasmInstanceObject* calleeInstanceObj =
|
||||
if (funcIndex == NullFuncIndex) {
|
||||
table.setNull(dstOffset + i);
|
||||
} else {
|
||||
if (funcIndex < funcImports.length()) {
|
||||
FuncImportTls& import = funcImportTls(funcImports[funcIndex]);
|
||||
JSFunction* fun = import.fun;
|
||||
if (IsExportedWasmFunction(fun)) {
|
||||
// This element is a wasm function imported from another
|
||||
// instance. To preserve the === function identity required by
|
||||
// the JS embedding spec, we must set the element to the
|
||||
// imported function's underlying CodeRange.funcTableEntry and
|
||||
// Instance so that future Table.get()s produce the same
|
||||
// function object as was imported.
|
||||
WasmInstanceObject* calleeInstanceObj =
|
||||
ExportedFunctionToInstanceObject(fun);
|
||||
Instance& calleeInstance = calleeInstanceObj->instance();
|
||||
Tier calleeTier = calleeInstance.code().bestTier();
|
||||
const CodeRange& calleeCodeRange =
|
||||
Instance& calleeInstance = calleeInstanceObj->instance();
|
||||
Tier calleeTier = calleeInstance.code().bestTier();
|
||||
const CodeRange& calleeCodeRange =
|
||||
calleeInstanceObj->getExportedFunctionCodeRange(fun, calleeTier);
|
||||
void* code = calleeInstance.codeBase(calleeTier) +
|
||||
calleeCodeRange.funcTableEntry();
|
||||
table.setAnyFunc(dstOffset + i, code, &calleeInstance);
|
||||
continue;
|
||||
void* code = calleeInstance.codeBase(calleeTier) +
|
||||
calleeCodeRange.funcTableEntry();
|
||||
table.setAnyFunc(dstOffset + i, code, &calleeInstance);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
void* code =
|
||||
void* code =
|
||||
codeBaseTier + codeRanges[funcToCodeRange[funcIndex]].funcTableEntry();
|
||||
table.setAnyFunc(dstOffset + i, code, this);
|
||||
table.setAnyFunc(dstOffset + i, code, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -183,8 +183,8 @@ class Instance {
|
|||
static int32_t callImport_i64(Instance*, int32_t, int32_t, uint64_t*);
|
||||
static int32_t callImport_f64(Instance*, int32_t, int32_t, uint64_t*);
|
||||
static int32_t callImport_anyref(Instance*, int32_t, int32_t, uint64_t*);
|
||||
static uint32_t growMemory_i32(Instance* instance, uint32_t delta);
|
||||
static uint32_t currentMemory_i32(Instance* instance);
|
||||
static uint32_t memoryGrow_i32(Instance* instance, uint32_t delta);
|
||||
static uint32_t memorySize_i32(Instance* instance);
|
||||
static int32_t wait_i32(Instance* instance, uint32_t byteOffset,
|
||||
int32_t value, int64_t timeout);
|
||||
static int32_t wait_i64(Instance* instance, uint32_t byteOffset,
|
||||
|
|
|
@ -2543,7 +2543,7 @@ static bool EmitBinaryMathBuiltinCall(FunctionCompiler& f,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool EmitGrowMemory(FunctionCompiler& f) {
|
||||
static bool EmitMemoryGrow(FunctionCompiler& f) {
|
||||
uint32_t lineOrBytecode = f.readCallSiteLineOrBytecode();
|
||||
|
||||
CallCompileState args;
|
||||
|
@ -2552,7 +2552,7 @@ static bool EmitGrowMemory(FunctionCompiler& f) {
|
|||
}
|
||||
|
||||
MDefinition* delta;
|
||||
if (!f.iter().readGrowMemory(&delta)) {
|
||||
if (!f.iter().readMemoryGrow(&delta)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2563,7 +2563,7 @@ static bool EmitGrowMemory(FunctionCompiler& f) {
|
|||
f.finishCall(&args);
|
||||
|
||||
MDefinition* ret;
|
||||
if (!f.builtinInstanceMethodCall(SymbolicAddress::GrowMemory, lineOrBytecode,
|
||||
if (!f.builtinInstanceMethodCall(SymbolicAddress::MemoryGrow, lineOrBytecode,
|
||||
args, ValType::I32, &ret)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -2572,12 +2572,12 @@ static bool EmitGrowMemory(FunctionCompiler& f) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool EmitCurrentMemory(FunctionCompiler& f) {
|
||||
static bool EmitMemorySize(FunctionCompiler& f) {
|
||||
uint32_t lineOrBytecode = f.readCallSiteLineOrBytecode();
|
||||
|
||||
CallCompileState args;
|
||||
|
||||
if (!f.iter().readCurrentMemory()) {
|
||||
if (!f.iter().readMemorySize()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2588,7 +2588,7 @@ static bool EmitCurrentMemory(FunctionCompiler& f) {
|
|||
f.finishCall(&args);
|
||||
|
||||
MDefinition* ret;
|
||||
if (!f.builtinInstanceMethodCall(SymbolicAddress::CurrentMemory,
|
||||
if (!f.builtinInstanceMethodCall(SymbolicAddress::MemorySize,
|
||||
lineOrBytecode, args, ValType::I32, &ret)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -3165,6 +3165,12 @@ static bool EmitBodyExprs(FunctionCompiler& f) {
|
|||
CHECK(EmitGetGlobal(f));
|
||||
case uint16_t(Op::SetGlobal):
|
||||
CHECK(EmitSetGlobal(f));
|
||||
#ifdef ENABLE_WASM_GENERALIZED_TABLES
|
||||
case uint16_t(Op::TableGet):
|
||||
CHECK(EmitTableGet(f));
|
||||
case uint16_t(Op::TableSet):
|
||||
CHECK(EmitTableSet(f));
|
||||
#endif
|
||||
|
||||
// Memory-related operators
|
||||
case uint16_t(Op::I32Load):
|
||||
|
@ -3213,10 +3219,10 @@ static bool EmitBodyExprs(FunctionCompiler& f) {
|
|||
CHECK(EmitStore(f, ValType::I64, Scalar::Int16));
|
||||
case uint16_t(Op::I64Store32):
|
||||
CHECK(EmitStore(f, ValType::I64, Scalar::Int32));
|
||||
case uint16_t(Op::CurrentMemory):
|
||||
CHECK(EmitCurrentMemory(f));
|
||||
case uint16_t(Op::GrowMemory):
|
||||
CHECK(EmitGrowMemory(f));
|
||||
case uint16_t(Op::MemorySize):
|
||||
CHECK(EmitMemorySize(f));
|
||||
case uint16_t(Op::MemoryGrow):
|
||||
CHECK(EmitMemoryGrow(f));
|
||||
|
||||
// Constants
|
||||
case uint16_t(Op::I32Const):
|
||||
|
@ -3581,12 +3587,8 @@ static bool EmitBodyExprs(FunctionCompiler& f) {
|
|||
CHECK(EmitMemOrTableInit(f, /*isMem=*/false));
|
||||
#endif
|
||||
#ifdef ENABLE_WASM_GENERALIZED_TABLES
|
||||
case uint16_t(MiscOp::TableGet):
|
||||
CHECK(EmitTableGet(f));
|
||||
case uint16_t(MiscOp::TableGrow):
|
||||
CHECK(EmitTableGrow(f));
|
||||
case uint16_t(MiscOp::TableSet):
|
||||
CHECK(EmitTableSet(f));
|
||||
case uint16_t(MiscOp::TableSize):
|
||||
CHECK(EmitTableSize(f));
|
||||
#endif
|
||||
|
|
|
@ -572,9 +572,14 @@ bool Module::initSegments(JSContext* cx, HandleWasmInstanceObject instanceObj,
|
|||
Handle<FunctionVector> funcImports,
|
||||
HandleWasmMemoryObject memoryObj,
|
||||
HandleValVector globalImportValues) const {
|
||||
MOZ_ASSERT_IF(!memoryObj, dataSegments_.empty());
|
||||
|
||||
Instance& instance = instanceObj->instance();
|
||||
const SharedTableVector& tables = instance.tables();
|
||||
|
||||
#ifndef ENABLE_WASM_BULKMEM_OPS
|
||||
// Bulk memory changes the error checking behavior: we may write partial data.
|
||||
|
||||
// Perform all error checks up front so that this function does not perform
|
||||
// partial initialization if an error is reported.
|
||||
|
||||
|
@ -609,21 +614,44 @@ bool Module::initSegments(JSContext* cx, HandleWasmInstanceObject instanceObj,
|
|||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(dataSegments_.empty());
|
||||
}
|
||||
|
||||
// Now that initialization can't fail partway through, write data/elem
|
||||
// segments into memories/tables.
|
||||
#endif
|
||||
|
||||
for (const ElemSegment* seg : elemSegments_) {
|
||||
if (seg->active()) {
|
||||
uint32_t offset = EvaluateInitExpr(globalImportValues, seg->offset());
|
||||
instance.initElems(seg->tableIndex, *seg, offset, 0, seg->length());
|
||||
uint32_t count = seg->length();
|
||||
#ifdef ENABLE_WASM_BULKMEM_OPS
|
||||
uint32_t tableLength = tables[seg->tableIndex]->length();
|
||||
bool fail = false;
|
||||
if (offset > tableLength) {
|
||||
fail = true;
|
||||
count = 0;
|
||||
} else if (tableLength - offset < count) {
|
||||
fail = true;
|
||||
count = tableLength - offset;
|
||||
}
|
||||
#endif
|
||||
if (count) {
|
||||
instance.initElems(seg->tableIndex, *seg, offset, 0, count);
|
||||
}
|
||||
#ifdef ENABLE_WASM_BULKMEM_OPS
|
||||
if (fail) {
|
||||
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_FIT,
|
||||
"elem", "table");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (memoryObj) {
|
||||
#ifdef ENABLE_WASM_BULKMEM_OPS
|
||||
uint32_t memoryLength = memoryObj->volatileMemoryLength();
|
||||
#endif
|
||||
uint8_t* memoryBase =
|
||||
memoryObj->buffer().dataPointerEither().unwrap(/* memcpy */);
|
||||
|
||||
|
@ -632,12 +660,29 @@ bool Module::initSegments(JSContext* cx, HandleWasmInstanceObject instanceObj,
|
|||
continue;
|
||||
}
|
||||
|
||||
// But apply active segments right now.
|
||||
uint32_t offset = EvaluateInitExpr(globalImportValues, seg->offset());
|
||||
memcpy(memoryBase + offset, seg->bytes.begin(), seg->bytes.length());
|
||||
uint32_t count = seg->bytes.length();
|
||||
#ifdef ENABLE_WASM_BULKMEM_OPS
|
||||
bool fail = false;
|
||||
if (offset > memoryLength) {
|
||||
fail = true;
|
||||
count = 0;
|
||||
} else if (memoryLength - offset < count) {
|
||||
fail = true;
|
||||
count = memoryLength - offset;
|
||||
}
|
||||
#endif
|
||||
if (count) {
|
||||
memcpy(memoryBase + offset, seg->bytes.begin(), count);
|
||||
}
|
||||
#ifdef ENABLE_WASM_BULKMEM_OPS
|
||||
if (fail) {
|
||||
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
|
||||
JSMSG_WASM_BAD_FIT, "data", "memory");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(dataSegments_.empty());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -252,6 +252,10 @@ OpKind wasm::Classify(OpBytes op) {
|
|||
return OpKind::GetGlobal;
|
||||
case Op::SetGlobal:
|
||||
return OpKind::SetGlobal;
|
||||
case Op::TableGet:
|
||||
WASM_TABLE_OP(OpKind::TableGet);
|
||||
case Op::TableSet:
|
||||
WASM_TABLE_OP(OpKind::TableSet);
|
||||
case Op::Call:
|
||||
return OpKind::Call;
|
||||
case Op::CallIndirect:
|
||||
|
@ -266,14 +270,16 @@ OpKind wasm::Classify(OpBytes op) {
|
|||
return OpKind::Else;
|
||||
case Op::End:
|
||||
return OpKind::End;
|
||||
case Op::CurrentMemory:
|
||||
return OpKind::CurrentMemory;
|
||||
case Op::GrowMemory:
|
||||
return OpKind::GrowMemory;
|
||||
case Op::MemorySize:
|
||||
return OpKind::MemorySize;
|
||||
case Op::MemoryGrow:
|
||||
return OpKind::MemoryGrow;
|
||||
case Op::RefNull:
|
||||
WASM_REF_OP(OpKind::RefNull);
|
||||
case Op::RefIsNull:
|
||||
WASM_REF_OP(OpKind::Conversion);
|
||||
case Op::RefFunc:
|
||||
WASM_REF_OP(OpKind::RefFunc);
|
||||
case Op::RefEq:
|
||||
WASM_GC_OP(OpKind::Comparison);
|
||||
case Op::MiscPrefix: {
|
||||
|
@ -301,12 +307,8 @@ OpKind wasm::Classify(OpBytes op) {
|
|||
case MiscOp::MemInit:
|
||||
case MiscOp::TableInit:
|
||||
WASM_BULK_OP(OpKind::MemOrTableInit);
|
||||
case MiscOp::TableGet:
|
||||
WASM_TABLE_OP(OpKind::TableGet);
|
||||
case MiscOp::TableGrow:
|
||||
WASM_TABLE_OP(OpKind::TableGrow);
|
||||
case MiscOp::TableSet:
|
||||
WASM_TABLE_OP(OpKind::TableSet);
|
||||
case MiscOp::TableSize:
|
||||
WASM_TABLE_OP(OpKind::TableSize);
|
||||
case MiscOp::StructNew:
|
||||
|
|
|
@ -131,8 +131,8 @@ enum class OpKind {
|
|||
Load,
|
||||
Store,
|
||||
TeeStore,
|
||||
CurrentMemory,
|
||||
GrowMemory,
|
||||
MemorySize,
|
||||
MemoryGrow,
|
||||
Select,
|
||||
GetLocal,
|
||||
SetLocal,
|
||||
|
@ -173,6 +173,7 @@ enum class OpKind {
|
|||
TableSet,
|
||||
TableSize,
|
||||
RefNull,
|
||||
RefFunc,
|
||||
StructNew,
|
||||
StructGet,
|
||||
StructSet,
|
||||
|
@ -416,8 +417,8 @@ class MOZ_STACK_CLASS OpIter : private Policy {
|
|||
LinearMemoryAddress<Value>* addr,
|
||||
Value* value);
|
||||
MOZ_MUST_USE bool readNop();
|
||||
MOZ_MUST_USE bool readCurrentMemory();
|
||||
MOZ_MUST_USE bool readGrowMemory(Value* input);
|
||||
MOZ_MUST_USE bool readMemorySize();
|
||||
MOZ_MUST_USE bool readMemoryGrow(Value* input);
|
||||
MOZ_MUST_USE bool readSelect(StackType* type, Value* trueValue,
|
||||
Value* falseValue, Value* condition);
|
||||
MOZ_MUST_USE bool readGetLocal(const ValTypeVector& locals, uint32_t* id);
|
||||
|
@ -1292,8 +1293,8 @@ inline bool OpIter<Policy>::readNop() {
|
|||
}
|
||||
|
||||
template <typename Policy>
|
||||
inline bool OpIter<Policy>::readCurrentMemory() {
|
||||
MOZ_ASSERT(Classify(op_) == OpKind::CurrentMemory);
|
||||
inline bool OpIter<Policy>::readMemorySize() {
|
||||
MOZ_ASSERT(Classify(op_) == OpKind::MemorySize);
|
||||
|
||||
if (!env_.usesMemory()) {
|
||||
return fail("can't touch memory without memory");
|
||||
|
@ -1312,8 +1313,8 @@ inline bool OpIter<Policy>::readCurrentMemory() {
|
|||
}
|
||||
|
||||
template <typename Policy>
|
||||
inline bool OpIter<Policy>::readGrowMemory(Value* input) {
|
||||
MOZ_ASSERT(Classify(op_) == OpKind::GrowMemory);
|
||||
inline bool OpIter<Policy>::readMemoryGrow(Value* input) {
|
||||
MOZ_ASSERT(Classify(op_) == OpKind::MemoryGrow);
|
||||
|
||||
if (!env_.usesMemory()) {
|
||||
return fail("can't touch memory without memory");
|
||||
|
@ -1572,18 +1573,9 @@ inline bool OpIter<Policy>::readCallIndirect(uint32_t* funcTypeIndex,
|
|||
return fail("signature index out of range");
|
||||
}
|
||||
|
||||
uint8_t flags;
|
||||
if (!readFixedU8(&flags)) {
|
||||
if (!readVarU32(tableIndex)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*tableIndex = 0;
|
||||
if (flags == uint8_t(MemoryTableFlags::HasTableIndex)) {
|
||||
if (!readVarU32(tableIndex)) return false;
|
||||
} else if (flags != uint8_t(MemoryTableFlags::Default)) {
|
||||
return fail("unexpected flags");
|
||||
}
|
||||
|
||||
if (*tableIndex >= env_.tables.length()) {
|
||||
// Special case this for improved user experience.
|
||||
if (!env_.tables.length()) {
|
||||
|
@ -1591,7 +1583,6 @@ inline bool OpIter<Policy>::readCallIndirect(uint32_t* funcTypeIndex,
|
|||
}
|
||||
return fail("table index out of range for call_indirect");
|
||||
}
|
||||
|
||||
if (env_.tables[*tableIndex].kind != TableKind::AnyFunction) {
|
||||
return fail("indirect calls must go through a table of 'anyfunc'");
|
||||
}
|
||||
|
@ -2012,28 +2003,18 @@ inline bool OpIter<Policy>::readTableGet(uint32_t* tableIndex, Value* index) {
|
|||
return false;
|
||||
}
|
||||
|
||||
*tableIndex = 0;
|
||||
|
||||
uint8_t tableFlags;
|
||||
if (!readFixedU8(&tableFlags)) {
|
||||
return fail("unable to read table flags");
|
||||
}
|
||||
if (tableFlags & uint8_t(MemoryTableFlags::HasTableIndex)) {
|
||||
if (!readVarU32(tableIndex)) {
|
||||
return false;
|
||||
}
|
||||
tableFlags ^= uint8_t(MemoryTableFlags::HasTableIndex);
|
||||
}
|
||||
if (tableFlags != uint8_t(MemoryTableFlags::Default)) {
|
||||
return fail("unrecognized table flags");
|
||||
if (!readVarU32(tableIndex)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (*tableIndex >= env_.tables.length()) {
|
||||
return fail("table index out of range for table.get");
|
||||
}
|
||||
|
||||
if (env_.tables[*tableIndex].kind != TableKind::AnyRef) {
|
||||
return fail("table.get only on tables of anyref");
|
||||
}
|
||||
|
||||
if (!env_.gcTypesEnabled()) {
|
||||
return fail("anyref support not enabled");
|
||||
}
|
||||
|
@ -2054,28 +2035,16 @@ inline bool OpIter<Policy>::readTableGrow(uint32_t* tableIndex, Value* delta,
|
|||
return false;
|
||||
}
|
||||
|
||||
*tableIndex = 0;
|
||||
|
||||
uint8_t tableFlags;
|
||||
if (!readFixedU8(&tableFlags)) {
|
||||
return fail("unable to read table flags");
|
||||
if (!readVarU32(tableIndex)) {
|
||||
return false;
|
||||
}
|
||||
if (tableFlags & uint8_t(MemoryTableFlags::HasTableIndex)) {
|
||||
if (!readVarU32(tableIndex)) {
|
||||
return false;
|
||||
}
|
||||
tableFlags ^= uint8_t(MemoryTableFlags::HasTableIndex);
|
||||
}
|
||||
if (tableFlags != uint8_t(MemoryTableFlags::Default)) {
|
||||
return fail("unrecognized table flags");
|
||||
}
|
||||
|
||||
if (*tableIndex >= env_.tables.length()) {
|
||||
return fail("table index out of range for table.grow");
|
||||
}
|
||||
if (env_.tables[*tableIndex].kind != TableKind::AnyRef) {
|
||||
return fail("table.grow only on tables of anyref");
|
||||
}
|
||||
|
||||
if (!env_.gcTypesEnabled()) {
|
||||
return fail("anyref support not enabled");
|
||||
}
|
||||
|
@ -2096,28 +2065,16 @@ inline bool OpIter<Policy>::readTableSet(uint32_t* tableIndex, Value* index,
|
|||
return false;
|
||||
}
|
||||
|
||||
*tableIndex = 0;
|
||||
|
||||
uint8_t tableFlags;
|
||||
if (!readFixedU8(&tableFlags)) {
|
||||
return fail("unable to read table flags");
|
||||
if (!readVarU32(tableIndex)) {
|
||||
return false;
|
||||
}
|
||||
if (tableFlags & uint8_t(MemoryTableFlags::HasTableIndex)) {
|
||||
if (!readVarU32(tableIndex)) {
|
||||
return false;
|
||||
}
|
||||
tableFlags ^= uint8_t(MemoryTableFlags::HasTableIndex);
|
||||
}
|
||||
if (tableFlags != uint8_t(MemoryTableFlags::Default)) {
|
||||
return fail("unrecognized table flags");
|
||||
}
|
||||
|
||||
if (*tableIndex >= env_.tables.length()) {
|
||||
return fail("table index out of range for table.set");
|
||||
}
|
||||
if (env_.tables[*tableIndex].kind != TableKind::AnyRef) {
|
||||
return fail("table.set only on tables of anyref");
|
||||
}
|
||||
|
||||
if (!env_.gcTypesEnabled()) {
|
||||
return fail("anyref support not enabled");
|
||||
}
|
||||
|
@ -2131,20 +2088,9 @@ inline bool OpIter<Policy>::readTableSize(uint32_t* tableIndex) {
|
|||
|
||||
*tableIndex = 0;
|
||||
|
||||
uint8_t tableFlags;
|
||||
if (!readFixedU8(&tableFlags)) {
|
||||
return fail("unable to read table flags");
|
||||
if (!readVarU32(tableIndex)) {
|
||||
return false;
|
||||
}
|
||||
if (tableFlags & uint8_t(MemoryTableFlags::HasTableIndex)) {
|
||||
if (!readVarU32(tableIndex)) {
|
||||
return false;
|
||||
}
|
||||
tableFlags ^= uint8_t(MemoryTableFlags::HasTableIndex);
|
||||
}
|
||||
if (tableFlags != uint8_t(MemoryTableFlags::Default)) {
|
||||
return fail("unrecognized table flags");
|
||||
}
|
||||
|
||||
if (*tableIndex >= env_.tables.length()) {
|
||||
return fail("table index out of range for table.size");
|
||||
}
|
||||
|
|
|
@ -74,10 +74,10 @@ class WasmToken {
|
|||
ComparisonOpcode,
|
||||
Const,
|
||||
ConversionOpcode,
|
||||
CurrentMemory,
|
||||
Data,
|
||||
#ifdef ENABLE_WASM_BULKMEM_OPS
|
||||
DataCount,
|
||||
DataDrop,
|
||||
#endif
|
||||
Drop,
|
||||
Elem,
|
||||
|
@ -97,7 +97,6 @@ class WasmToken {
|
|||
GetGlobal,
|
||||
GetLocal,
|
||||
Global,
|
||||
GrowMemory,
|
||||
If,
|
||||
Import,
|
||||
Index,
|
||||
|
@ -108,10 +107,11 @@ class WasmToken {
|
|||
Loop,
|
||||
#ifdef ENABLE_WASM_BULKMEM_OPS
|
||||
MemCopy,
|
||||
DataDrop,
|
||||
MemFill,
|
||||
MemInit,
|
||||
#endif
|
||||
MemoryGrow,
|
||||
MemorySize,
|
||||
Module,
|
||||
Mutable,
|
||||
Name,
|
||||
|
@ -310,20 +310,25 @@ class WasmToken {
|
|||
case Const:
|
||||
case ConversionOpcode:
|
||||
case ExtraConversionOpcode:
|
||||
case CurrentMemory:
|
||||
#ifdef ENABLE_WASM_BULKMEM_OPS
|
||||
case DataDrop:
|
||||
#endif
|
||||
case Drop:
|
||||
#ifdef ENABLE_WASM_BULKMEM_OPS
|
||||
case ElemDrop:
|
||||
#endif
|
||||
case GetGlobal:
|
||||
case GetLocal:
|
||||
case GrowMemory:
|
||||
case If:
|
||||
case Load:
|
||||
case Loop:
|
||||
#ifdef ENABLE_WASM_BULKMEM_OPS
|
||||
case MemCopy:
|
||||
case DataDrop:
|
||||
case MemFill:
|
||||
case MemInit:
|
||||
#endif
|
||||
case MemoryGrow:
|
||||
case MemorySize:
|
||||
#ifdef ENABLE_WASM_GC
|
||||
case StructNew:
|
||||
case StructGet:
|
||||
|
@ -338,7 +343,6 @@ class WasmToken {
|
|||
case Store:
|
||||
#ifdef ENABLE_WASM_BULKMEM_OPS
|
||||
case TableCopy:
|
||||
case ElemDrop:
|
||||
case TableInit:
|
||||
#endif
|
||||
#ifdef ENABLE_WASM_GENERALIZED_TABLES
|
||||
|
@ -984,7 +988,7 @@ WasmToken WasmTokenStream::next() {
|
|||
return WasmToken(WasmToken::Call, begin, cur_);
|
||||
}
|
||||
if (consume(u"current_memory")) {
|
||||
return WasmToken(WasmToken::CurrentMemory, begin, cur_);
|
||||
return WasmToken(WasmToken::MemorySize, begin, cur_);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1342,7 +1346,7 @@ WasmToken WasmTokenStream::next() {
|
|||
return WasmToken(WasmToken::Global, begin, cur_);
|
||||
}
|
||||
if (consume(u"grow_memory")) {
|
||||
return WasmToken(WasmToken::GrowMemory, begin, cur_);
|
||||
return WasmToken(WasmToken::MemoryGrow, begin, cur_);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -2126,10 +2130,10 @@ WasmToken WasmTokenStream::next() {
|
|||
}
|
||||
#endif
|
||||
if (consume(u"grow")) {
|
||||
return WasmToken(WasmToken::GrowMemory, begin, cur_);
|
||||
return WasmToken(WasmToken::MemoryGrow, begin, cur_);
|
||||
}
|
||||
if (consume(u"size")) {
|
||||
return WasmToken(WasmToken::CurrentMemory, begin, cur_);
|
||||
return WasmToken(WasmToken::MemorySize, begin, cur_);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -3622,13 +3626,13 @@ static AstBranchTable* ParseBranchTable(WasmParseContext& c, bool inParens) {
|
|||
return new (c.lifo) AstBranchTable(*index, def, std::move(table), value);
|
||||
}
|
||||
|
||||
static AstGrowMemory* ParseGrowMemory(WasmParseContext& c, bool inParens) {
|
||||
static AstMemoryGrow* ParseMemoryGrow(WasmParseContext& c, bool inParens) {
|
||||
AstExpr* operand = ParseExpr(c, inParens);
|
||||
if (!operand) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return new (c.lifo) AstGrowMemory(operand);
|
||||
return new (c.lifo) AstMemoryGrow(operand);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WASM_BULKMEM_OPS
|
||||
|
@ -3997,10 +4001,10 @@ static AstExpr* ParseExprBody(WasmParseContext& c, WasmToken token,
|
|||
return ParseUnaryOperator(c, token.op(), inParens);
|
||||
case WasmToken::Nop:
|
||||
return new (c.lifo) AstNop();
|
||||
case WasmToken::CurrentMemory:
|
||||
return new (c.lifo) AstCurrentMemory();
|
||||
case WasmToken::GrowMemory:
|
||||
return ParseGrowMemory(c, inParens);
|
||||
case WasmToken::MemorySize:
|
||||
return new (c.lifo) AstMemorySize();
|
||||
case WasmToken::MemoryGrow:
|
||||
return ParseMemoryGrow(c, inParens);
|
||||
#ifdef ENABLE_WASM_BULKMEM_OPS
|
||||
case WasmToken::MemCopy:
|
||||
return ParseMemOrTableCopy(c, inParens, /*isMem=*/true);
|
||||
|
@ -4916,11 +4920,11 @@ static bool ParseTable(WasmParseContext& c, WasmToken token,
|
|||
if (name.empty()) return false;
|
||||
}
|
||||
|
||||
AstRefVector elems(c.lifo);
|
||||
AstElemVector elems(c.lifo);
|
||||
|
||||
AstRef elem;
|
||||
while (c.ts.getIfRef(&elem)) {
|
||||
if (!elems.append(elem)) {
|
||||
if (!elems.append(AstElem(elem))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -4951,9 +4955,9 @@ static bool ParseTable(WasmParseContext& c, WasmToken token,
|
|||
}
|
||||
|
||||
static AstElemSegment* ParseElemSegment(WasmParseContext& c) {
|
||||
// (elem table-name init-expr ref ...)
|
||||
// (elem init-expr ref ...)
|
||||
// (elem passive ref ...)
|
||||
// (elem table-name init-expr fnref...)
|
||||
// (elem init-expr fnref...)
|
||||
// (elem passive (fnref|ref.null)...)
|
||||
|
||||
AstRef targetTable = AstRef(0);
|
||||
bool hasTableName = c.ts.getIfRef(&targetTable);
|
||||
|
@ -4969,13 +4973,23 @@ static AstElemSegment* ParseElemSegment(WasmParseContext& c) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
AstRefVector elems(c.lifo);
|
||||
AstElemVector elems(c.lifo);
|
||||
|
||||
AstRef elem;
|
||||
while (c.ts.getIfRef(&elem)) {
|
||||
if (!elems.append(elem)) {
|
||||
return nullptr;
|
||||
for (;;) {
|
||||
AstRef elemRef;
|
||||
if (c.ts.getIfRef(&elemRef)) {
|
||||
if (!elems.append(AstElem(elemRef))) {
|
||||
return nullptr;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!offsetIfActive && c.ts.getIf(WasmToken::RefNull)) {
|
||||
if (!elems.append(AstElem(AstNullValue()))) {
|
||||
return nullptr;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return new (c.lifo)
|
||||
|
@ -5490,7 +5504,7 @@ static bool ResolveUnaryOperator(Resolver& r, AstUnaryOperator& b) {
|
|||
return ResolveExpr(r, *b.operand());
|
||||
}
|
||||
|
||||
static bool ResolveGrowMemory(Resolver& r, AstGrowMemory& gm) {
|
||||
static bool ResolveMemoryGrow(Resolver& r, AstMemoryGrow& gm) {
|
||||
return ResolveExpr(r, *gm.operand());
|
||||
}
|
||||
|
||||
|
@ -5697,7 +5711,7 @@ static bool ResolveExpr(Resolver& r, AstExpr& expr) {
|
|||
case AstExprKind::Nop:
|
||||
case AstExprKind::Pop:
|
||||
case AstExprKind::Unreachable:
|
||||
case AstExprKind::CurrentMemory:
|
||||
case AstExprKind::MemorySize:
|
||||
return true;
|
||||
case AstExprKind::RefNull:
|
||||
return ResolveRefNull(r, expr.as<AstRefNull>());
|
||||
|
@ -5748,8 +5762,8 @@ static bool ResolveExpr(Resolver& r, AstExpr& expr) {
|
|||
return ResolveTernaryOperator(r, expr.as<AstTernaryOperator>());
|
||||
case AstExprKind::UnaryOperator:
|
||||
return ResolveUnaryOperator(r, expr.as<AstUnaryOperator>());
|
||||
case AstExprKind::GrowMemory:
|
||||
return ResolveGrowMemory(r, expr.as<AstGrowMemory>());
|
||||
case AstExprKind::MemoryGrow:
|
||||
return ResolveMemoryGrow(r, expr.as<AstMemoryGrow>());
|
||||
case AstExprKind::AtomicCmpXchg:
|
||||
return ResolveAtomicCmpXchg(r, expr.as<AstAtomicCmpXchg>());
|
||||
case AstExprKind::AtomicLoad:
|
||||
|
@ -6018,9 +6032,15 @@ static bool ResolveModule(LifoAlloc& lifo, AstModule* module,
|
|||
!ResolveExpr(r, *segment->offsetIfActive())) {
|
||||
return false;
|
||||
}
|
||||
for (AstRef& ref : segment->elems()) {
|
||||
if (!r.resolveFunction(ref)) {
|
||||
return false;
|
||||
for (AstElem& elemRef : segment->elems()) {
|
||||
if (elemRef.is<AstRef>()) {
|
||||
if (!r.resolveFunction(elemRef.as<AstRef>())) {
|
||||
return false;
|
||||
}
|
||||
} else if (elemRef.is<AstNullValue>()) {
|
||||
// Nothing
|
||||
} else {
|
||||
MOZ_CRASH("Unexpected variant");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6118,14 +6138,6 @@ static bool EncodeCall(Encoder& e, AstCall& c) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool EncodeOneTableIndex(Encoder& e, uint32_t index) {
|
||||
if (index) {
|
||||
return e.writeVarU32(uint32_t(MemoryTableFlags::HasTableIndex)) &&
|
||||
e.writeVarU32(index);
|
||||
}
|
||||
return e.writeVarU32(uint32_t(MemoryTableFlags::Default));
|
||||
}
|
||||
|
||||
static bool EncodeCallIndirect(Encoder& e, AstCallIndirect& c) {
|
||||
if (!EncodeArgs(e, c.args())) {
|
||||
return false;
|
||||
|
@ -6143,7 +6155,7 @@ static bool EncodeCallIndirect(Encoder& e, AstCallIndirect& c) {
|
|||
return false;
|
||||
}
|
||||
|
||||
return EncodeOneTableIndex(e, c.targetTable().index());
|
||||
return e.writeVarU32(c.targetTable().index());
|
||||
}
|
||||
|
||||
static bool EncodeConst(Encoder& e, AstConst& c) {
|
||||
|
@ -6308,8 +6320,8 @@ static bool EncodeBranchTable(Encoder& e, AstBranchTable& bt) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool EncodeCurrentMemory(Encoder& e, AstCurrentMemory& cm) {
|
||||
if (!e.writeOp(Op::CurrentMemory)) {
|
||||
static bool EncodeMemorySize(Encoder& e, AstMemorySize& cm) {
|
||||
if (!e.writeOp(Op::MemorySize)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -6320,12 +6332,12 @@ static bool EncodeCurrentMemory(Encoder& e, AstCurrentMemory& cm) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool EncodeGrowMemory(Encoder& e, AstGrowMemory& gm) {
|
||||
static bool EncodeMemoryGrow(Encoder& e, AstMemoryGrow& gm) {
|
||||
if (!EncodeExpr(e, *gm.operand())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!e.writeOp(Op::GrowMemory)) {
|
||||
if (!e.writeOp(Op::MemoryGrow)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -6398,25 +6410,25 @@ static bool EncodeMemOrTableInit(Encoder& e, AstMemOrTableInit& s) {
|
|||
|
||||
#ifdef ENABLE_WASM_GENERALIZED_TABLES
|
||||
static bool EncodeTableGet(Encoder& e, AstTableGet& s) {
|
||||
return EncodeExpr(e, s.index()) && e.writeOp(MiscOp::TableGet) &&
|
||||
EncodeOneTableIndex(e, s.targetTable().index());
|
||||
return EncodeExpr(e, s.index()) && e.writeOp(Op::TableGet) &&
|
||||
e.writeVarU32(s.targetTable().index());
|
||||
}
|
||||
|
||||
static bool EncodeTableGrow(Encoder& e, AstTableGrow& s) {
|
||||
return EncodeExpr(e, s.delta()) && EncodeExpr(e, s.initValue()) &&
|
||||
e.writeOp(MiscOp::TableGrow) &&
|
||||
EncodeOneTableIndex(e, s.targetTable().index());
|
||||
e.writeVarU32(s.targetTable().index());
|
||||
}
|
||||
|
||||
static bool EncodeTableSet(Encoder& e, AstTableSet& s) {
|
||||
return EncodeExpr(e, s.index()) && EncodeExpr(e, s.value()) &&
|
||||
e.writeOp(MiscOp::TableSet) &&
|
||||
EncodeOneTableIndex(e, s.targetTable().index());
|
||||
e.writeOp(Op::TableSet) &&
|
||||
e.writeVarU32(s.targetTable().index());
|
||||
}
|
||||
|
||||
static bool EncodeTableSize(Encoder& e, AstTableSize& s) {
|
||||
return e.writeOp(MiscOp::TableSize) &&
|
||||
EncodeOneTableIndex(e, s.targetTable().index());
|
||||
e.writeVarU32(s.targetTable().index());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -6550,10 +6562,10 @@ static bool EncodeExpr(Encoder& e, AstExpr& expr) {
|
|||
return EncodeTernaryOperator(e, expr.as<AstTernaryOperator>());
|
||||
case AstExprKind::UnaryOperator:
|
||||
return EncodeUnaryOperator(e, expr.as<AstUnaryOperator>());
|
||||
case AstExprKind::CurrentMemory:
|
||||
return EncodeCurrentMemory(e, expr.as<AstCurrentMemory>());
|
||||
case AstExprKind::GrowMemory:
|
||||
return EncodeGrowMemory(e, expr.as<AstGrowMemory>());
|
||||
case AstExprKind::MemorySize:
|
||||
return EncodeMemorySize(e, expr.as<AstMemorySize>());
|
||||
case AstExprKind::MemoryGrow:
|
||||
return EncodeMemoryGrow(e, expr.as<AstMemoryGrow>());
|
||||
case AstExprKind::AtomicCmpXchg:
|
||||
return EncodeAtomicCmpXchg(e, expr.as<AstAtomicCmpXchg>());
|
||||
case AstExprKind::AtomicLoad:
|
||||
|
@ -7182,17 +7194,28 @@ static bool EncodeElemSegment(Encoder& e, AstElemSegment& segment) {
|
|||
return false;
|
||||
}
|
||||
|
||||
for (const AstRef& elem : segment.elems()) {
|
||||
// Passive segments have an initializer expression, for now restricted to a
|
||||
// function index.
|
||||
if (segment.isPassive() && !e.writeFixedU8(PlaceholderRefFunc)) {
|
||||
return false;
|
||||
}
|
||||
if (!e.writeVarU32(elem.index())) {
|
||||
return false;
|
||||
}
|
||||
if (segment.isPassive() && !e.writeFixedU8(uint8_t(Op::End))) {
|
||||
return false;
|
||||
for (const AstElem& elem : segment.elems()) {
|
||||
if (elem.is<AstRef>()) {
|
||||
const AstRef& ref = elem.as<AstRef>();
|
||||
// Passive segments have an initializer expression, for now restricted to a
|
||||
// function index.
|
||||
if (segment.isPassive() && !e.writeFixedU8(uint8_t(Op::RefFunc))) {
|
||||
return false;
|
||||
}
|
||||
if (!e.writeVarU32(ref.index())) {
|
||||
return false;
|
||||
}
|
||||
if (segment.isPassive() && !e.writeFixedU8(uint8_t(Op::End))) {
|
||||
return false;
|
||||
}
|
||||
} else if (elem.is<AstNullValue>()) {
|
||||
MOZ_ASSERT(segment.isPassive());
|
||||
if (!e.writeFixedU8(uint8_t(Op::RefNull)) ||
|
||||
!e.writeFixedU8(uint8_t(Op::End))) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
MOZ_CRASH("Unexpected variant");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1143,7 +1143,7 @@ typedef Vector<GlobalDesc, 0, SystemAllocPolicy> GlobalDescVector;
|
|||
struct ElemSegment : AtomicRefCounted<ElemSegment> {
|
||||
uint32_t tableIndex;
|
||||
Maybe<InitExpr> offsetIfActive;
|
||||
Uint32Vector elemFuncIndices;
|
||||
Uint32Vector elemFuncIndices; // Element may be NullFuncIndex
|
||||
|
||||
bool active() const { return !!offsetIfActive; }
|
||||
|
||||
|
@ -1154,6 +1154,11 @@ struct ElemSegment : AtomicRefCounted<ElemSegment> {
|
|||
WASM_DECLARE_SERIALIZABLE(ElemSegment)
|
||||
};
|
||||
|
||||
// NullFuncIndex represents the case when an element segment (of type anyfunc)
|
||||
// contains a null element.
|
||||
constexpr uint32_t NullFuncIndex = UINT32_MAX;
|
||||
static_assert(NullFuncIndex > MaxFuncs, "Invariant");
|
||||
|
||||
typedef RefPtr<ElemSegment> MutableElemSegment;
|
||||
typedef SerializableRefPtr<const ElemSegment> SharedElemSegment;
|
||||
typedef Vector<SharedElemSegment, 0, SystemAllocPolicy> ElemSegmentVector;
|
||||
|
@ -2048,8 +2053,8 @@ enum class SymbolicAddress {
|
|||
Uint64ToDouble,
|
||||
Int64ToFloat32,
|
||||
Int64ToDouble,
|
||||
GrowMemory,
|
||||
CurrentMemory,
|
||||
MemoryGrow,
|
||||
MemorySize,
|
||||
WaitI32,
|
||||
WaitI64,
|
||||
Wake,
|
||||
|
|
|
@ -534,6 +534,16 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env,
|
|||
uint32_t unused;
|
||||
CHECK(iter.readSetGlobal(&unused, ¬hing));
|
||||
}
|
||||
#ifdef ENABLE_WASM_GENERALIZED_TABLES
|
||||
case uint16_t(Op::TableGet): {
|
||||
uint32_t unusedTableIndex;
|
||||
CHECK(iter.readTableGet(&unusedTableIndex, ¬hing));
|
||||
}
|
||||
case uint16_t(Op::TableSet): {
|
||||
uint32_t unusedTableIndex;
|
||||
CHECK(iter.readTableSet(&unusedTableIndex, ¬hing, ¬hing));
|
||||
}
|
||||
#endif
|
||||
case uint16_t(Op::Select): {
|
||||
StackType unused;
|
||||
CHECK(iter.readSelect(&unused, ¬hing, ¬hing, ¬hing));
|
||||
|
@ -780,10 +790,10 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env,
|
|||
LinearMemoryAddress<Nothing> addr;
|
||||
CHECK(iter.readStore(ValType::F64, 8, &addr, ¬hing));
|
||||
}
|
||||
case uint16_t(Op::GrowMemory):
|
||||
CHECK(iter.readGrowMemory(¬hing));
|
||||
case uint16_t(Op::CurrentMemory):
|
||||
CHECK(iter.readCurrentMemory());
|
||||
case uint16_t(Op::MemoryGrow):
|
||||
CHECK(iter.readMemoryGrow(¬hing));
|
||||
case uint16_t(Op::MemorySize):
|
||||
CHECK(iter.readMemorySize());
|
||||
case uint16_t(Op::Br): {
|
||||
uint32_t unusedDepth;
|
||||
ExprType unusedType;
|
||||
|
@ -860,18 +870,10 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env,
|
|||
}
|
||||
#endif
|
||||
#ifdef ENABLE_WASM_GENERALIZED_TABLES
|
||||
case uint16_t(MiscOp::TableGet): {
|
||||
uint32_t unusedTableIndex;
|
||||
CHECK(iter.readTableGet(&unusedTableIndex, ¬hing));
|
||||
}
|
||||
case uint16_t(MiscOp::TableGrow): {
|
||||
uint32_t unusedTableIndex;
|
||||
CHECK(iter.readTableGrow(&unusedTableIndex, ¬hing, ¬hing));
|
||||
}
|
||||
case uint16_t(MiscOp::TableSet): {
|
||||
uint32_t unusedTableIndex;
|
||||
CHECK(iter.readTableSet(&unusedTableIndex, ¬hing, ¬hing));
|
||||
}
|
||||
case uint16_t(MiscOp::TableSize): {
|
||||
uint32_t unusedTableIndex;
|
||||
CHECK(iter.readTableSize(&unusedTableIndex));
|
||||
|
@ -1372,21 +1374,26 @@ static bool DecodeGCFeatureOptInSection(Decoder& d, ModuleEnvironment* env) {
|
|||
// For documentation of what's in the various versions, see
|
||||
// https://github.com/lars-t-hansen/moz-gc-experiments
|
||||
//
|
||||
// Version 1 is complete.
|
||||
// Version 2 is in progress.
|
||||
// Version 1 is complete and obsolete.
|
||||
// Version 2 is incomplete but obsolete.
|
||||
// Version 3 is in progress.
|
||||
|
||||
switch (version) {
|
||||
case 1:
|
||||
return d.fail(
|
||||
"Wasm GC feature version 1 is no longer supported by this engine.\n"
|
||||
"The current version is 2, which is not backward-compatible:\n"
|
||||
" - The old encoding of ref.null is no longer accepted.");
|
||||
case 2:
|
||||
return d.fail(
|
||||
"Wasm GC feature versions 1 and 2 are no longer supported by this engine.\n"
|
||||
"The current version is 3, which is not backward-compatible with earlier\n"
|
||||
"versions:\n"
|
||||
" - The v1 encoding of ref.null is no longer accepted.\n"
|
||||
" - The v2 encodings of ref.eq, table.get, table.set, and table.size\n"
|
||||
" are no longer accepted.\n");
|
||||
case 3:
|
||||
break;
|
||||
default:
|
||||
return d.fail(
|
||||
"The specified Wasm GC feature version is unknown.\n"
|
||||
"The current version is 2.");
|
||||
"The current version is 3.");
|
||||
}
|
||||
|
||||
env->gcFeatureOptIn = true;
|
||||
|
@ -2310,33 +2317,44 @@ static bool DecodeElemSection(Decoder& d, ModuleEnvironment* env) {
|
|||
// required Ref.Func and End here.
|
||||
|
||||
for (uint32_t i = 0; i < numElems; i++) {
|
||||
bool needIndex = true;
|
||||
|
||||
if (initializerKind == InitializerKind::Passive) {
|
||||
OpBytes op;
|
||||
if (!d.readOp(&op) || op.b0 != PlaceholderRefFunc) {
|
||||
return d.fail("failed to read ref.func operation");
|
||||
if (!d.readOp(&op)) {
|
||||
return d.fail("failed to read initializer operation");
|
||||
}
|
||||
switch (op.b0) {
|
||||
case uint16_t(Op::RefFunc):
|
||||
break;
|
||||
case uint16_t(Op::RefNull):
|
||||
needIndex = false;
|
||||
break;
|
||||
default:
|
||||
return d.fail("failed to read initializer operation");
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t funcIndex;
|
||||
if (!d.readVarU32(&funcIndex)) {
|
||||
return d.fail("failed to read element function index");
|
||||
}
|
||||
|
||||
if (funcIndex >= env->numFuncs()) {
|
||||
return d.fail("table element out of range");
|
||||
}
|
||||
|
||||
uint32_t funcIndex = NullFuncIndex;
|
||||
if (needIndex) {
|
||||
if (!d.readVarU32(&funcIndex)) {
|
||||
return d.fail("failed to read element function index");
|
||||
}
|
||||
if (funcIndex >= env->numFuncs()) {
|
||||
return d.fail("table element out of range");
|
||||
}
|
||||
#ifdef WASM_PRIVATE_REFTYPES
|
||||
if (exportedTable &&
|
||||
!FuncTypeIsJSCompatible(d, *env->funcTypes[funcIndex])) {
|
||||
return false;
|
||||
}
|
||||
if (exportedTable &&
|
||||
!FuncTypeIsJSCompatible(d, *env->funcTypes[funcIndex])) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (initializerKind == InitializerKind::Passive) {
|
||||
OpBytes end;
|
||||
if (!d.readOp(&end) || end.b0 != uint16_t(Op::End)) {
|
||||
return d.fail("failed to read end of ref.func expression");
|
||||
return d.fail("failed to read end of initializer expression");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -160,8 +160,8 @@ struct BD_ValType {
|
|||
// enum is hardcoded in wasm2clif.rs.
|
||||
|
||||
enum class BD_SymbolicAddress {
|
||||
GrowMemory,
|
||||
CurrentMemory,
|
||||
MemoryGrow,
|
||||
MemorySize,
|
||||
FloorF32,
|
||||
FloorF64,
|
||||
CeilF32,
|
||||
|
|
|
@ -690,10 +690,10 @@ impl<'a, 'b, 'c> FuncEnvironment for TransEnv<'a, 'b, 'c> {
|
|||
_heap: ir::Heap,
|
||||
val: ir::Value,
|
||||
) -> WasmResult<ir::Value> {
|
||||
// We emit a call to `uint32_t growMemory_i32(Instance* instance, uint32_t delta)` via a
|
||||
// We emit a call to `uint32_t memoryGrow_i32(Instance* instance, uint32_t delta)` via a
|
||||
// stub.
|
||||
let (fnref, sigref) =
|
||||
self.symbolic_funcref(pos.func, bd::SymbolicAddress::GrowMemory, || {
|
||||
self.symbolic_funcref(pos.func, bd::SymbolicAddress::MemoryGrow, || {
|
||||
let mut sig = ir::Signature::new(CallConv::Baldrdash);
|
||||
sig.params.push(ir::AbiParam::new(native_pointer_type()));
|
||||
sig.params.push(ir::AbiParam::new(ir::types::I32).uext());
|
||||
|
@ -705,7 +705,7 @@ impl<'a, 'b, 'c> FuncEnvironment for TransEnv<'a, 'b, 'c> {
|
|||
sig
|
||||
});
|
||||
|
||||
// Get the instance pointer needed by `growMemory_i32`.
|
||||
// Get the instance pointer needed by `memoryGrow_i32`.
|
||||
let instance = self.load_instance(&mut pos);
|
||||
let vmctx = pos
|
||||
.func
|
||||
|
@ -727,9 +727,9 @@ impl<'a, 'b, 'c> FuncEnvironment for TransEnv<'a, 'b, 'c> {
|
|||
_index: MemoryIndex,
|
||||
_heap: ir::Heap,
|
||||
) -> WasmResult<ir::Value> {
|
||||
// We emit a call to `uint32_t currentMemory_i32(Instance* instance)` via a stub.
|
||||
// We emit a call to `uint32_t memorySize_i32(Instance* instance)` via a stub.
|
||||
let (fnref, sigref) =
|
||||
self.symbolic_funcref(pos.func, bd::SymbolicAddress::CurrentMemory, || {
|
||||
self.symbolic_funcref(pos.func, bd::SymbolicAddress::MemorySize, || {
|
||||
let mut sig = ir::Signature::new(CallConv::Baldrdash);
|
||||
sig.params.push(ir::AbiParam::new(native_pointer_type()));
|
||||
sig.params.push(ir::AbiParam::special(
|
||||
|
@ -740,7 +740,7 @@ impl<'a, 'b, 'c> FuncEnvironment for TransEnv<'a, 'b, 'c> {
|
|||
sig
|
||||
});
|
||||
|
||||
// Get the instance pointer needed by `currentMemory_i32`.
|
||||
// Get the instance pointer needed by `memorySize_i32`.
|
||||
let instance = self.load_instance(&mut pos);
|
||||
let vmctx = pos
|
||||
.func
|
||||
|
|
Загрузка…
Ссылка в новой задаче