forked from mirrors/gecko-dev
This does the following: - It introduces a controlling ifdef ENABLE_WASM_REFTYPES that enables exactly those features that are in the reftypes proposal, excluding those in the gc proposal. Any remaining features (namely, ref.eq, (ref T) types, struct types) are still under ENABLE_WASM_GC control. ENABLE_WASM_GC requires ENABLE_WASM_REFTYPES and this is checked. - It introduces a new TestingFunctions predicate, wasmReftypesEnabled, that distinguishes reftype-proposal support from gc-proposal support. We keep wasmGcEnabled to test for gc-proposal support. - It segregates test cases so that gc-proposal relevant tests are in their own files, and tests relevant to the reftypes-proposal are now guarded by wasmReftypesEnabled. - It renames the predicate HasGcSupport() as HasReftypesSupport(), since that is what the predicate tests for. - It has a drive-by fix for the DEBUG-only function wasm::Classify() to properly put ref.null and ref.is_null under ifdef control. Reftypes will soon be enabled unconditionally in Nightly (once we can trace pointers from Ion frames) while gc-types will remain conditional until Ion supports all the new instructions for struct types. Therefore: - The command line switch and about:config option are still called --wasm-gc and j.o.wasm_gc, respectively, which is fine since they will fairly soon control only gc-proposal features. - Internal names still use "Gc" rather than "Reftypes", eg, HasGcTypes, wasmGc_, and so on. This is most appropriate since it reduces the scope of the patch and these names will pertain mainly to the gc feature in the future. --HG-- extra : rebase_source : 51cf3bfe67da594e89195472e4ce1ccfa36c146d
159 lines
4.5 KiB
JavaScript
159 lines
4.5 KiB
JavaScript
// |jit-test| skip-if: !wasmReftypesEnabled()
|
|
|
|
// Moving a JS value through a wasm anyref is a pair of boxing/unboxing
|
|
// conversions that leaves the value unchanged. There are many cases,
|
|
// along these axes:
|
|
//
|
|
// - global variables
|
|
// - tables
|
|
// - function parameters and returns
|
|
// - struct fields [for the gc feature], see anyref-boxing-struct.js
|
|
|
|
let VALUES = [null,
|
|
undefined,
|
|
true,
|
|
false,
|
|
{x:1337},
|
|
["abracadabra"],
|
|
1337,
|
|
13.37,
|
|
"hi",
|
|
Symbol("status"),
|
|
() => 1337];
|
|
|
|
// Global variables can receive values via several mechanisms:
|
|
//
|
|
// - on initialization when created from JS
|
|
// - on initialization when created in Wasm, from an imported global
|
|
// - through the "value" property if the value is mutable
|
|
// - through the set_global wasm instruction, ditto
|
|
//
|
|
// Their values can be obtained in several ways:
|
|
//
|
|
// - through the "value" property
|
|
// - through the get_global wasm instruction
|
|
// - read when other globals are initialized from them
|
|
|
|
// Set via initialization and read via 'value'
|
|
|
|
for (let v of VALUES)
|
|
{
|
|
let g = new WebAssembly.Global({value: "anyref"}, v);
|
|
assertEq(g.value, v);
|
|
}
|
|
|
|
// Set via 'value' and read via 'value'
|
|
|
|
for (let v of VALUES)
|
|
{
|
|
let g = new WebAssembly.Global({value: "anyref", mutable: true});
|
|
g.value = v;
|
|
assertEq(g.value, v);
|
|
}
|
|
|
|
// Set via initialization, then read via get_global and returned
|
|
|
|
for (let v of VALUES)
|
|
{
|
|
let g = new WebAssembly.Global({value: "anyref"}, v);
|
|
let ins = wasmEvalText(
|
|
`(module
|
|
(gc_feature_opt_in 2)
|
|
(import $glob "m" "g" (global anyref))
|
|
(func (export "f") (result anyref)
|
|
(get_global $glob)))`,
|
|
{m:{g}});
|
|
assertEq(ins.exports.f(), v);
|
|
}
|
|
|
|
// Set via set_global, then read via 'value'
|
|
|
|
for (let v of VALUES)
|
|
{
|
|
let g = new WebAssembly.Global({value: "anyref", mutable: true});
|
|
let ins = wasmEvalText(
|
|
`(module
|
|
(gc_feature_opt_in 2)
|
|
(import $glob "m" "g" (global (mut anyref)))
|
|
(func (export "f") (param $v anyref)
|
|
(set_global $glob (get_local $v))))`,
|
|
{m:{g}});
|
|
ins.exports.f(v);
|
|
assertEq(g.value, v);
|
|
}
|
|
|
|
// Tables of anyref can receive values via several mechanisms:
|
|
//
|
|
// - through WebAssembly.Table.prototype.set()
|
|
// - through the table.set, table.copy, and table.grow instructions
|
|
// - unimplemented: through table.fill
|
|
// - unimplemented: through WebAssembly.Table.prototype.grow()
|
|
//
|
|
// Their values can be read in several ways:
|
|
//
|
|
// - through WebAssembly.Table.prototype.get()
|
|
// - through the table.get and table.copy instructions
|
|
//
|
|
// (Note, tables are always initialized to null when created from JS)
|
|
|
|
// .set() and .get()
|
|
|
|
for (let v of VALUES)
|
|
{
|
|
let t = new WebAssembly.Table({element: "anyref", initial: 10});
|
|
t.set(3, v);
|
|
assertEq(t.get(3), v);
|
|
}
|
|
|
|
// write with table.set, read with .get()
|
|
|
|
for (let v of VALUES)
|
|
{
|
|
let t = new WebAssembly.Table({element: "anyref", initial: 10});
|
|
let ins = wasmEvalText(
|
|
`(module
|
|
(gc_feature_opt_in 2)
|
|
(import $t "m" "t" (table 10 anyref))
|
|
(func (export "f") (param $v anyref)
|
|
(table.set $t (i32.const 3) (get_local $v))))`,
|
|
{m:{t}});
|
|
ins.exports.f(v);
|
|
assertEq(t.get(3), v);
|
|
}
|
|
|
|
// write with .set(), read with table.get
|
|
|
|
for (let v of VALUES)
|
|
{
|
|
let t = new WebAssembly.Table({element: "anyref", initial: 10});
|
|
let ins = wasmEvalText(
|
|
`(module
|
|
(gc_feature_opt_in 2)
|
|
(import $t "m" "t" (table 10 anyref))
|
|
(func (export "f") (result anyref)
|
|
(table.get $t (i32.const 3))))`,
|
|
{m:{t}});
|
|
t.set(3, v);
|
|
assertEq(ins.exports.f(), v);
|
|
}
|
|
|
|
// Imported JS functions can receive anyref values as parameters and return
|
|
// them.
|
|
|
|
for (let v of VALUES)
|
|
{
|
|
let returner = function () { return v; };
|
|
let receiver = function (w) { assertEq(w, v); };
|
|
let ins = wasmEvalText(
|
|
`(module
|
|
(gc_feature_opt_in 2)
|
|
(import $returner "m" "returner" (func (result anyref)))
|
|
(import $receiver "m" "receiver" (func (param anyref)))
|
|
(func (export "test_returner") (result anyref)
|
|
(call $returner))
|
|
(func (export "test_receiver") (param $v anyref)
|
|
(call $receiver (get_local $v))))`,
|
|
{m:{returner, receiver}});
|
|
assertEq(ins.exports.test_returner(), v);
|
|
ins.exports.test_receiver(v);
|
|
}
|