Merge mozilla-inbound to mozilla-central. a=merge

This commit is contained in:
Cosmin Sabou 2019-02-18 17:52:30 +02:00
Родитель ba95495155 a8a53fe9a5
Коммит a625f06db9
59 изменённых файлов: 772 добавлений и 589 удалений

Просмотреть файл

@ -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, &nothing));
}
#ifdef ENABLE_WASM_GENERALIZED_TABLES
case uint16_t(Op::TableGet): {
uint32_t unusedTableIndex;
CHECK(iter.readTableGet(&unusedTableIndex, &nothing));
}
case uint16_t(Op::TableSet): {
uint32_t unusedTableIndex;
CHECK(iter.readTableSet(&unusedTableIndex, &nothing, &nothing));
}
#endif
case uint16_t(Op::Select): {
StackType unused;
CHECK(iter.readSelect(&unused, &nothing, &nothing, &nothing));
@ -780,10 +790,10 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env,
LinearMemoryAddress<Nothing> addr;
CHECK(iter.readStore(ValType::F64, 8, &addr, &nothing));
}
case uint16_t(Op::GrowMemory):
CHECK(iter.readGrowMemory(&nothing));
case uint16_t(Op::CurrentMemory):
CHECK(iter.readCurrentMemory());
case uint16_t(Op::MemoryGrow):
CHECK(iter.readMemoryGrow(&nothing));
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, &nothing));
}
case uint16_t(MiscOp::TableGrow): {
uint32_t unusedTableIndex;
CHECK(iter.readTableGrow(&unusedTableIndex, &nothing, &nothing));
}
case uint16_t(MiscOp::TableSet): {
uint32_t unusedTableIndex;
CHECK(iter.readTableSet(&unusedTableIndex, &nothing, &nothing));
}
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