fune/js/src/jit-test/tests/wasm/gc/anyref-boxing.js
Lars T Hansen d66fb136aa Bug 1508561 - Disentangle support for reftypes and gc. r=jseward
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
2018-12-18 17:26:32 +01:00

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);
}