зеркало из https://github.com/mozilla/gecko-dev.git
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
This commit is contained in:
Родитель
3311ddda7f
Коммит
d66fb136aa
|
@ -286,7 +286,7 @@ void LoadContextOptions(const char* aPrefName, void* /* aClosure */) {
|
||||||
.setWasmForceCranelift(
|
.setWasmForceCranelift(
|
||||||
GetWorkerPref<bool>(NS_LITERAL_CSTRING("wasm_cranelift")))
|
GetWorkerPref<bool>(NS_LITERAL_CSTRING("wasm_cranelift")))
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
.setWasmGc(GetWorkerPref<bool>(NS_LITERAL_CSTRING("wasm_gc")))
|
.setWasmGc(GetWorkerPref<bool>(NS_LITERAL_CSTRING("wasm_gc")))
|
||||||
#endif
|
#endif
|
||||||
.setWasmVerbose(GetWorkerPref<bool>(NS_LITERAL_CSTRING("wasm_verbose")))
|
.setWasmVerbose(GetWorkerPref<bool>(NS_LITERAL_CSTRING("wasm_verbose")))
|
||||||
|
|
|
@ -100,4 +100,5 @@ if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||||
CXXFLAGS += ['-Wno-error=shadow']
|
CXXFLAGS += ['-Wno-error=shadow']
|
||||||
|
|
||||||
if CONFIG['NIGHTLY_BUILD']:
|
if CONFIG['NIGHTLY_BUILD']:
|
||||||
|
DEFINES['ENABLE_WASM_REFTYPES'] = True
|
||||||
DEFINES['ENABLE_WASM_GC'] = True
|
DEFINES['ENABLE_WASM_GC'] = True
|
||||||
|
|
|
@ -670,9 +670,19 @@ static bool WasmBulkMemSupported(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool WasmReftypesEnabled(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
|
args.rval().setBoolean(wasm::HasReftypesSupport(cx));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool WasmGcEnabled(JSContext* cx, unsigned argc, Value* vp) {
|
static bool WasmGcEnabled(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
CallArgs args = CallArgsFromVp(argc, vp);
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
args.rval().setBoolean(wasm::HasGcSupport(cx));
|
#ifdef ENABLE_WASM_GC
|
||||||
|
args.rval().setBoolean(wasm::HasReftypesSupport(cx));
|
||||||
|
#else
|
||||||
|
args.rval().setBoolean(false);
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -681,7 +691,7 @@ static bool WasmGeneralizedTables(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
#ifdef ENABLE_WASM_GENERALIZED_TABLES
|
#ifdef ENABLE_WASM_GENERALIZED_TABLES
|
||||||
// Generalized tables depend on anyref, though not currently on (ref T)
|
// Generalized tables depend on anyref, though not currently on (ref T)
|
||||||
// types nor on structures or other GC-proposal features.
|
// types nor on structures or other GC-proposal features.
|
||||||
bool isSupported = wasm::HasGcSupport(cx);
|
bool isSupported = wasm::HasReftypesSupport(cx);
|
||||||
#else
|
#else
|
||||||
bool isSupported = false;
|
bool isSupported = false;
|
||||||
#endif
|
#endif
|
||||||
|
@ -5957,9 +5967,13 @@ gc::ZealModeHelpText),
|
||||||
" Returns a boolean indicating whether a given module has finished compiled code for tier2. \n"
|
" Returns a boolean indicating whether a given module has finished compiled code for tier2. \n"
|
||||||
"This will return true early if compilation isn't two-tiered. "),
|
"This will return true early if compilation isn't two-tiered. "),
|
||||||
|
|
||||||
|
JS_FN_HELP("wasmReftypesEnabled", WasmReftypesEnabled, 1, 0,
|
||||||
|
"wasmReftypesEnabled(bool)",
|
||||||
|
" Returns a boolean indicating whether the WebAssembly reftypes proposal is enabled."),
|
||||||
|
|
||||||
JS_FN_HELP("wasmGcEnabled", WasmGcEnabled, 1, 0,
|
JS_FN_HELP("wasmGcEnabled", WasmGcEnabled, 1, 0,
|
||||||
"wasmGcEnabled(bool)",
|
"wasmGcEnabled(bool)",
|
||||||
" Returns a boolean indicating whether the WebAssembly GC support is enabled."),
|
" Returns a boolean indicating whether the WebAssembly GC types proposal is enabled."),
|
||||||
|
|
||||||
JS_FN_HELP("wasmGeneralizedTables", WasmGeneralizedTables, 1, 0,
|
JS_FN_HELP("wasmGeneralizedTables", WasmGeneralizedTables, 1, 0,
|
||||||
"wasmGeneralizedTables(bool)",
|
"wasmGeneralizedTables(bool)",
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// |jit-test| skip-if: !wasmGcEnabled()
|
// |jit-test| skip-if: !wasmReftypesEnabled()
|
||||||
|
|
||||||
// Moving a JS value through a wasm anyref is a pair of boxing/unboxing
|
// Moving a JS value through a wasm anyref is a pair of boxing/unboxing
|
||||||
// conversions that leaves the value unchanged. There are many cases,
|
// conversions that leaves the value unchanged. There are many cases,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// |jit-test| skip-if: !wasmGcEnabled() || typeof WebAssembly.Global !== 'function'
|
// |jit-test| skip-if: !wasmReftypesEnabled() || typeof WebAssembly.Global !== 'function'
|
||||||
|
|
||||||
// Dummy object.
|
// Dummy object.
|
||||||
function Baguette(calories) {
|
function Baguette(calories) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// |jit-test| skip-if: !wasmGcEnabled()
|
// |jit-test| skip-if: !wasmReftypesEnabled()
|
||||||
|
|
||||||
const { startProfiling, endProfiling, assertEqPreciseStacks, isSingleStepProfilingEnabled } = WasmHelpers;
|
const { startProfiling, endProfiling, assertEqPreciseStacks, isSingleStepProfilingEnabled } = WasmHelpers;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// |jit-test| skip-if: !wasmGcEnabled()
|
// |jit-test| skip-if: !wasmReftypesEnabled()
|
||||||
|
|
||||||
// Do not run the test if we're jit-compiling JS, since it's the wasm frames
|
// Do not run the test if we're jit-compiling JS, since it's the wasm frames
|
||||||
// we're interested in and eager JS compilation can upset the test.
|
// we're interested in and eager JS compilation can upset the test.
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
// |jit-test| skip-if: !wasmGcEnabled()
|
||||||
|
//
|
||||||
|
// ref.eq is part of the gc feature, not the reftypes feature.
|
||||||
|
|
||||||
|
let { exports } = wasmEvalText(`(module
|
||||||
|
(gc_feature_opt_in 2)
|
||||||
|
|
||||||
|
(func (export "ref_eq") (param $a anyref) (param $b anyref) (result i32)
|
||||||
|
(ref.eq (get_local $a) (get_local $b)))
|
||||||
|
|
||||||
|
(func (export "ref_eq_for_control") (param $a anyref) (param $b anyref) (result f64)
|
||||||
|
(if f64 (ref.eq (get_local $a) (get_local $b))
|
||||||
|
(f64.const 5.0)
|
||||||
|
(f64.const 3.0))))`);
|
||||||
|
|
||||||
|
assertEq(exports.ref_eq(null, null), 1);
|
||||||
|
assertEq(exports.ref_eq(null, {}), 0);
|
||||||
|
assertEq(exports.ref_eq(this, this), 1);
|
||||||
|
assertEq(exports.ref_eq_for_control(null, null), 5);
|
||||||
|
assertEq(exports.ref_eq_for_control(null, {}), 3);
|
||||||
|
assertEq(exports.ref_eq_for_control(this, this), 5);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// |jit-test| skip-if: !wasmGcEnabled()
|
// |jit-test| skip-if: !wasmReftypesEnabled()
|
||||||
|
|
||||||
gczeal(14, 1);
|
gczeal(14, 1);
|
||||||
let { exports } = wasmEvalText(`(module
|
let { exports } = wasmEvalText(`(module
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// |jit-test| skip-if: !wasmGcEnabled()
|
// |jit-test| skip-if: !wasmReftypesEnabled()
|
||||||
// Ensure that if gc types aren't enabled, test cases properly fail.
|
|
||||||
|
|
||||||
// Dummy constructor.
|
// Dummy constructor.
|
||||||
function Baguette(calories) {
|
function Baguette(calories) {
|
||||||
|
@ -90,25 +89,11 @@ let { exports } = wasmEvalText(`(module
|
||||||
get_local 0
|
get_local 0
|
||||||
ref.is_null
|
ref.is_null
|
||||||
)
|
)
|
||||||
|
|
||||||
(func (export "ref_eq") (param $a anyref) (param $b anyref) (result i32)
|
|
||||||
(ref.eq (get_local $a) (get_local $b)))
|
|
||||||
|
|
||||||
(func (export "ref_eq_for_control") (param $a anyref) (param $b anyref) (result f64)
|
|
||||||
(if f64 (ref.eq (get_local $a) (get_local $b))
|
|
||||||
(f64.const 5.0)
|
|
||||||
(f64.const 3.0)))
|
|
||||||
)`);
|
)`);
|
||||||
|
|
||||||
assertEq(exports.is_null(), 1);
|
assertEq(exports.is_null(), 1);
|
||||||
assertEq(exports.is_null_spill(), 1);
|
assertEq(exports.is_null_spill(), 1);
|
||||||
assertEq(exports.is_null_local(), 1);
|
assertEq(exports.is_null_local(), 1);
|
||||||
assertEq(exports.ref_eq(null, null), 1);
|
|
||||||
assertEq(exports.ref_eq(null, {}), 0);
|
|
||||||
assertEq(exports.ref_eq(this, this), 1);
|
|
||||||
assertEq(exports.ref_eq_for_control(null, null), 5);
|
|
||||||
assertEq(exports.ref_eq_for_control(null, {}), 3);
|
|
||||||
assertEq(exports.ref_eq_for_control(this, this), 5);
|
|
||||||
|
|
||||||
// Anyref param and result in wasm functions.
|
// Anyref param and result in wasm functions.
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// |jit-test| skip-if: !wasmGcEnabled()
|
// |jit-test| skip-if: !wasmReftypesEnabled()
|
||||||
|
|
||||||
load(libdir + "wasm-binary.js");
|
load(libdir + "wasm-binary.js");
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// |jit-test| skip-if: !wasmGcEnabled() || !wasmDebuggingIsSupported()
|
// |jit-test| skip-if: !wasmReftypesEnabled() || !wasmDebuggingIsSupported()
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
let g = newGlobal();
|
let g = newGlobal();
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
// |jit-test| skip-if: wasmGcEnabled()
|
||||||
|
|
||||||
|
assertErrorMessage(() => wasmEvalText(`(module (func (param (ref 0)) (unreachable)))`),
|
||||||
|
WebAssembly.CompileError, /reference types not enabled/);
|
|
@ -1,4 +1,4 @@
|
||||||
// |jit-test| skip-if: wasmGcEnabled()
|
// |jit-test| skip-if: wasmReftypesEnabled()
|
||||||
|
|
||||||
const { CompileError, validate } = WebAssembly;
|
const { CompileError, validate } = WebAssembly;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// |jit-test| skip-if: !wasmGcEnabled()
|
// |jit-test| skip-if: !wasmReftypesEnabled()
|
||||||
|
|
||||||
enableShellAllocationMetadataBuilder();
|
enableShellAllocationMetadataBuilder();
|
||||||
gczeal(9, 1);
|
gczeal(9, 1);
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
// |jit-test| skip-if: !wasmGcEnabled()
|
||||||
|
//
|
||||||
|
// Struct types are only available if we opt in, so test that.
|
||||||
|
|
||||||
|
let CURRENT_VERSION = 2;
|
||||||
|
|
||||||
|
new WebAssembly.Module(wasmTextToBinary(
|
||||||
|
`(module
|
||||||
|
(gc_feature_opt_in ${CURRENT_VERSION})
|
||||||
|
(type (struct (field i32))))`));
|
||||||
|
|
||||||
|
assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
||||||
|
`(module
|
||||||
|
(type (struct (field i32))))`)),
|
||||||
|
WebAssembly.CompileError,
|
||||||
|
/Structure types not enabled/);
|
||||||
|
|
||||||
|
assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
||||||
|
`(module
|
||||||
|
(func (struct.new 0)))`)),
|
||||||
|
WebAssembly.CompileError,
|
||||||
|
/unrecognized opcode/);
|
||||||
|
|
||||||
|
assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
||||||
|
`(module
|
||||||
|
(func (struct.get 0 0)))`)),
|
||||||
|
WebAssembly.CompileError,
|
||||||
|
/unrecognized opcode/);
|
||||||
|
|
||||||
|
assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
||||||
|
`(module
|
||||||
|
(func (struct.set 0 0)))`)),
|
||||||
|
WebAssembly.CompileError,
|
||||||
|
/unrecognized opcode/);
|
||||||
|
|
||||||
|
assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
||||||
|
`(module
|
||||||
|
(func (struct.narrow anyref anyref)))`)),
|
||||||
|
WebAssembly.CompileError,
|
||||||
|
/unrecognized opcode/);
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
// |jit-test| skip-if: !wasmGcEnabled()
|
// |jit-test| skip-if: !wasmReftypesEnabled()
|
||||||
|
//
|
||||||
|
// Also see gc-feature-opt-in-struct.js for tests that use the struct feature.
|
||||||
|
|
||||||
// Version numbers
|
// Version numbers
|
||||||
|
|
||||||
|
@ -44,19 +46,6 @@ assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
||||||
WebAssembly.CompileError,
|
WebAssembly.CompileError,
|
||||||
/GC feature version is unknown/);
|
/GC feature version is unknown/);
|
||||||
|
|
||||||
// Struct types are only available if we opt in.
|
|
||||||
|
|
||||||
new WebAssembly.Module(wasmTextToBinary(
|
|
||||||
`(module
|
|
||||||
(gc_feature_opt_in ${CURRENT_VERSION})
|
|
||||||
(type (struct (field i32))))`));
|
|
||||||
|
|
||||||
assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
|
||||||
`(module
|
|
||||||
(type (struct (field i32))))`)),
|
|
||||||
WebAssembly.CompileError,
|
|
||||||
/Structure types not enabled/);
|
|
||||||
|
|
||||||
// Parameters of ref type are only available if we opt in.
|
// Parameters of ref type are only available if we opt in.
|
||||||
|
|
||||||
new WebAssembly.Module(wasmTextToBinary(
|
new WebAssembly.Module(wasmTextToBinary(
|
||||||
|
@ -137,26 +126,3 @@ assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
||||||
WebAssembly.CompileError,
|
WebAssembly.CompileError,
|
||||||
/unrecognized opcode/);
|
/unrecognized opcode/);
|
||||||
|
|
||||||
assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
|
||||||
`(module
|
|
||||||
(func (struct.new 0)))`)),
|
|
||||||
WebAssembly.CompileError,
|
|
||||||
/unrecognized opcode/);
|
|
||||||
|
|
||||||
assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
|
||||||
`(module
|
|
||||||
(func (struct.get 0 0)))`)),
|
|
||||||
WebAssembly.CompileError,
|
|
||||||
/unrecognized opcode/);
|
|
||||||
|
|
||||||
assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
|
||||||
`(module
|
|
||||||
(func (struct.set 0 0)))`)),
|
|
||||||
WebAssembly.CompileError,
|
|
||||||
/unrecognized opcode/);
|
|
||||||
|
|
||||||
assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
|
||||||
`(module
|
|
||||||
(func (struct.narrow anyref anyref)))`)),
|
|
||||||
WebAssembly.CompileError,
|
|
||||||
/unrecognized opcode/);
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// |jit-test| skip-if: !wasmGcEnabled()
|
// |jit-test| skip-if: !wasmReftypesEnabled()
|
||||||
|
|
||||||
// Attempt to test intercalls from ion to baseline and back.
|
// Attempt to test intercalls from ion to baseline and back.
|
||||||
//
|
//
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
if (!wasmGcEnabled()) {
|
// |jit-test| skip-if: !wasmGcEnabled()
|
||||||
assertErrorMessage(() => wasmEvalText(`(module (func (param (ref 0)) (unreachable)))`),
|
|
||||||
WebAssembly.CompileError, /reference types not enabled/);
|
|
||||||
quit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parsing and resolving.
|
// Parsing and resolving.
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// |jit-test| skip-if: !wasmGcEnabled()
|
// |jit-test| skip-if: !wasmReftypesEnabled()
|
||||||
|
|
||||||
// Tests wasm frame tracing. Only tests for direct and indirect call chains
|
// Tests wasm frame tracing. Only tests for direct and indirect call chains
|
||||||
// in wasm that lead to JS allocation. Does not test any timeout or interrupt
|
// in wasm that lead to JS allocation. Does not test any timeout or interrupt
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// |jit-test| skip-if: !wasmGcEnabled()
|
// |jit-test| skip-if: !wasmReftypesEnabled()
|
||||||
|
|
||||||
// Tests wasm frame tracing in the presence of interrupt handlers that perform
|
// Tests wasm frame tracing in the presence of interrupt handlers that perform
|
||||||
// allocation. The structure is
|
// allocation. The structure is
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// |jit-test| skip-if: !wasmGcEnabled()
|
// |jit-test| skip-if: !wasmReftypesEnabled()
|
||||||
|
|
||||||
// Generates a bunch of numbers-on-the-heap, and tries to ensure that they are
|
// Generates a bunch of numbers-on-the-heap, and tries to ensure that they are
|
||||||
// held live -- at least for a short while -- only by references from the wasm
|
// held live -- at least for a short while -- only by references from the wasm
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
// |jit-test| skip-if: !wasmGeneralizedTables() || !wasmGcEnabled()
|
||||||
|
|
||||||
|
// table.set in bounds with i32 x anyref - works, no value generated
|
||||||
|
// table.set with (ref T) - works
|
||||||
|
// table.set with null - works
|
||||||
|
// table.set out of bounds - fails
|
||||||
|
|
||||||
|
{
|
||||||
|
let ins = wasmEvalText(
|
||||||
|
`(module
|
||||||
|
(gc_feature_opt_in 2)
|
||||||
|
(table (export "t") 10 anyref)
|
||||||
|
(type $dummy (struct (field i32)))
|
||||||
|
(func (export "set_anyref") (param i32) (param anyref)
|
||||||
|
(table.set (get_local 0) (get_local 1)))
|
||||||
|
(func (export "set_null") (param i32)
|
||||||
|
(table.set (get_local 0) (ref.null)))
|
||||||
|
(func (export "set_ref") (param i32) (param anyref)
|
||||||
|
(table.set (get_local 0) (struct.narrow anyref (ref $dummy) (get_local 1))))
|
||||||
|
(func (export "make_struct") (result anyref)
|
||||||
|
(struct.new $dummy (i32.const 37))))`);
|
||||||
|
let x = {};
|
||||||
|
ins.exports.set_anyref(3, x);
|
||||||
|
assertEq(ins.exports.t.get(3), x);
|
||||||
|
ins.exports.set_null(3);
|
||||||
|
assertEq(ins.exports.t.get(3), null);
|
||||||
|
let dummy = ins.exports.make_struct();
|
||||||
|
ins.exports.set_ref(5, dummy);
|
||||||
|
assertEq(ins.exports.t.get(5), dummy);
|
||||||
|
|
||||||
|
assertErrorMessage(() => ins.exports.set_anyref(10, x), RangeError, /index out of bounds/);
|
||||||
|
assertErrorMessage(() => ins.exports.set_anyref(-1, x), RangeError, /index out of bounds/);
|
||||||
|
}
|
||||||
|
|
||||||
|
// table.grow on table of anyref with non-null ref value
|
||||||
|
|
||||||
|
{
|
||||||
|
let ins = wasmEvalText(
|
||||||
|
`(module
|
||||||
|
(gc_feature_opt_in 2)
|
||||||
|
(type $S (struct (field i32) (field f64)))
|
||||||
|
(table (export "t") 2 anyref)
|
||||||
|
(func (export "f") (result i32)
|
||||||
|
(table.grow (i32.const 1) (struct.new $S (i32.const 0) (f64.const 3.14)))))`);
|
||||||
|
assertEq(ins.exports.t.length, 2);
|
||||||
|
assertEq(ins.exports.f(), 2);
|
||||||
|
assertEq(ins.exports.t.length, 3);
|
||||||
|
assertEq(typeof ins.exports.t.get(2), "object");
|
||||||
|
}
|
||||||
|
|
|
@ -223,7 +223,6 @@ assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
||||||
/table index out of range for table.get/);
|
/table index out of range for table.get/);
|
||||||
|
|
||||||
// table.set in bounds with i32 x anyref - works, no value generated
|
// table.set in bounds with i32 x anyref - works, no value generated
|
||||||
// table.set with (ref T) - works
|
|
||||||
// table.set with null - works
|
// table.set with null - works
|
||||||
// table.set out of bounds - fails
|
// table.set out of bounds - fails
|
||||||
|
|
||||||
|
@ -232,23 +231,15 @@ assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
||||||
`(module
|
`(module
|
||||||
(gc_feature_opt_in 2)
|
(gc_feature_opt_in 2)
|
||||||
(table (export "t") 10 anyref)
|
(table (export "t") 10 anyref)
|
||||||
(type $dummy (struct (field i32)))
|
|
||||||
(func (export "set_anyref") (param i32) (param anyref)
|
(func (export "set_anyref") (param i32) (param anyref)
|
||||||
(table.set (get_local 0) (get_local 1)))
|
(table.set (get_local 0) (get_local 1)))
|
||||||
(func (export "set_null") (param i32)
|
(func (export "set_null") (param i32)
|
||||||
(table.set (get_local 0) (ref.null)))
|
(table.set (get_local 0) (ref.null))))`);
|
||||||
(func (export "set_ref") (param i32) (param anyref)
|
|
||||||
(table.set (get_local 0) (struct.narrow anyref (ref $dummy) (get_local 1))))
|
|
||||||
(func (export "make_struct") (result anyref)
|
|
||||||
(struct.new $dummy (i32.const 37))))`);
|
|
||||||
let x = {};
|
let x = {};
|
||||||
ins.exports.set_anyref(3, x);
|
ins.exports.set_anyref(3, x);
|
||||||
assertEq(ins.exports.t.get(3), x);
|
assertEq(ins.exports.t.get(3), x);
|
||||||
ins.exports.set_null(3);
|
ins.exports.set_null(3);
|
||||||
assertEq(ins.exports.t.get(3), null);
|
assertEq(ins.exports.t.get(3), null);
|
||||||
let dummy = ins.exports.make_struct();
|
|
||||||
ins.exports.set_ref(5, dummy);
|
|
||||||
assertEq(ins.exports.t.get(5), dummy);
|
|
||||||
|
|
||||||
assertErrorMessage(() => ins.exports.set_anyref(10, x), RangeError, /index out of bounds/);
|
assertErrorMessage(() => ins.exports.set_anyref(10, x), RangeError, /index out of bounds/);
|
||||||
assertErrorMessage(() => ins.exports.set_anyref(-1, x), RangeError, /index out of bounds/);
|
assertErrorMessage(() => ins.exports.set_anyref(-1, x), RangeError, /index out of bounds/);
|
||||||
|
@ -378,22 +369,6 @@ assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
|
||||||
WebAssembly.CompileError,
|
WebAssembly.CompileError,
|
||||||
/table index out of range for table.grow/);
|
/table index out of range for table.grow/);
|
||||||
|
|
||||||
// table.grow on table of anyref with non-null ref value
|
|
||||||
|
|
||||||
{
|
|
||||||
let ins = wasmEvalText(
|
|
||||||
`(module
|
|
||||||
(gc_feature_opt_in 2)
|
|
||||||
(type $S (struct (field i32) (field f64)))
|
|
||||||
(table (export "t") 2 anyref)
|
|
||||||
(func (export "f") (result i32)
|
|
||||||
(table.grow (i32.const 1) (struct.new $S (i32.const 0) (f64.const 3.14)))))`);
|
|
||||||
assertEq(ins.exports.t.length, 2);
|
|
||||||
assertEq(ins.exports.f(), 2);
|
|
||||||
assertEq(ins.exports.t.length, 3);
|
|
||||||
assertEq(typeof ins.exports.t.get(2), "object");
|
|
||||||
}
|
|
||||||
|
|
||||||
// table.size on table of anyref
|
// table.size on table of anyref
|
||||||
|
|
||||||
for (let visibility of ['', '(export "t")', '(import "m" "t")']) {
|
for (let visibility of ['', '(export "t")', '(import "m" "t")']) {
|
||||||
|
|
|
@ -211,7 +211,7 @@ JitCompileOptions::JitCompileOptions()
|
||||||
: cloneSingletons_(false),
|
: cloneSingletons_(false),
|
||||||
profilerSlowAssertionsEnabled_(false),
|
profilerSlowAssertionsEnabled_(false),
|
||||||
offThreadCompilationAvailable_(false)
|
offThreadCompilationAvailable_(false)
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
,
|
,
|
||||||
wasmGcEnabled_(false)
|
wasmGcEnabled_(false)
|
||||||
#endif
|
#endif
|
||||||
|
@ -224,7 +224,7 @@ JitCompileOptions::JitCompileOptions(JSContext* cx) {
|
||||||
cx->runtime()->geckoProfiler().enabled() &&
|
cx->runtime()->geckoProfiler().enabled() &&
|
||||||
cx->runtime()->geckoProfiler().slowAssertionsEnabled();
|
cx->runtime()->geckoProfiler().slowAssertionsEnabled();
|
||||||
offThreadCompilationAvailable_ = OffThreadCompilationAvailable(cx);
|
offThreadCompilationAvailable_ = OffThreadCompilationAvailable(cx);
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
wasmGcEnabled_ = wasm::HasGcSupport(cx);
|
wasmGcEnabled_ = wasm::HasReftypesSupport(cx);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,7 +130,7 @@ class JitCompileOptions {
|
||||||
return offThreadCompilationAvailable_;
|
return offThreadCompilationAvailable_;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
bool wasmGcEnabled() const { return wasmGcEnabled_; }
|
bool wasmGcEnabled() const { return wasmGcEnabled_; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -138,7 +138,7 @@ class JitCompileOptions {
|
||||||
bool cloneSingletons_;
|
bool cloneSingletons_;
|
||||||
bool profilerSlowAssertionsEnabled_;
|
bool profilerSlowAssertionsEnabled_;
|
||||||
bool offThreadCompilationAvailable_;
|
bool offThreadCompilationAvailable_;
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
bool wasmGcEnabled_;
|
bool wasmGcEnabled_;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,10 +6,20 @@
|
||||||
|
|
||||||
# Nightly-only features
|
# Nightly-only features
|
||||||
if CONFIG['NIGHTLY_BUILD']:
|
if CONFIG['NIGHTLY_BUILD']:
|
||||||
|
# TypedObject
|
||||||
DEFINES['ENABLE_BINARYDATA'] = True
|
DEFINES['ENABLE_BINARYDATA'] = True
|
||||||
|
# The evolving bulk-copy proposal - mem.fill, mem.copy,
|
||||||
|
# table.copy, etc
|
||||||
DEFINES['ENABLE_WASM_BULKMEM_OPS'] = True
|
DEFINES['ENABLE_WASM_BULKMEM_OPS'] = True
|
||||||
DEFINES['ENABLE_WASM_GC'] = True
|
# Support the evolving reftypes proposal - anyref, funcref, null,
|
||||||
|
# and a few other things
|
||||||
|
DEFINES['ENABLE_WASM_REFTYPES'] = True
|
||||||
|
# Support table of anyref, multiple tables - requires reftypes
|
||||||
DEFINES['ENABLE_WASM_GENERALIZED_TABLES'] = True
|
DEFINES['ENABLE_WASM_GENERALIZED_TABLES'] = True
|
||||||
|
# Support the evolving gc types proposal (struct types, etc)
|
||||||
|
DEFINES['ENABLE_WASM_GC'] = True
|
||||||
|
# Prevent (ref T) types from being exposed to JS content so that
|
||||||
|
# wasm need do no typechecking at the JS/wasm boundary
|
||||||
DEFINES['WASM_PRIVATE_REFTYPES'] = True
|
DEFINES['WASM_PRIVATE_REFTYPES'] = True
|
||||||
|
|
||||||
# Some huge-mapping optimization instead of bounds checks on supported
|
# Some huge-mapping optimization instead of bounds checks on supported
|
||||||
|
|
|
@ -398,7 +398,7 @@ class JS_PUBLIC_API ContextOptions {
|
||||||
#ifdef ENABLE_WASM_CRANELIFT
|
#ifdef ENABLE_WASM_CRANELIFT
|
||||||
wasmForceCranelift_(false),
|
wasmForceCranelift_(false),
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
wasmGc_(false),
|
wasmGc_(false),
|
||||||
#endif
|
#endif
|
||||||
testWasmAwaitTier2_(false),
|
testWasmAwaitTier2_(false),
|
||||||
|
@ -489,7 +489,7 @@ class JS_PUBLIC_API ContextOptions {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
bool wasmGc() const { return wasmGc_; }
|
bool wasmGc() const { return wasmGc_; }
|
||||||
ContextOptions& setWasmGc(bool flag) {
|
ContextOptions& setWasmGc(bool flag) {
|
||||||
wasmGc_ = flag;
|
wasmGc_ = flag;
|
||||||
|
@ -580,7 +580,7 @@ class JS_PUBLIC_API ContextOptions {
|
||||||
setWasm(false);
|
setWasm(false);
|
||||||
setWasmBaseline(false);
|
setWasmBaseline(false);
|
||||||
setWasmIon(false);
|
setWasmIon(false);
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
setWasmGc(false);
|
setWasmGc(false);
|
||||||
#endif
|
#endif
|
||||||
setNativeRegExp(false);
|
setNativeRegExp(false);
|
||||||
|
@ -597,7 +597,7 @@ class JS_PUBLIC_API ContextOptions {
|
||||||
#ifdef ENABLE_WASM_CRANELIFT
|
#ifdef ENABLE_WASM_CRANELIFT
|
||||||
bool wasmForceCranelift_ : 1;
|
bool wasmForceCranelift_ : 1;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
bool wasmGc_ : 1;
|
bool wasmGc_ : 1;
|
||||||
#endif
|
#endif
|
||||||
bool testWasmAwaitTier2_ : 1;
|
bool testWasmAwaitTier2_ : 1;
|
||||||
|
|
|
@ -494,7 +494,7 @@ static bool enableWasmIon = false;
|
||||||
#ifdef ENABLE_WASM_CRANELIFT
|
#ifdef ENABLE_WASM_CRANELIFT
|
||||||
static bool wasmForceCranelift = false;
|
static bool wasmForceCranelift = false;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
static bool enableWasmGc = false;
|
static bool enableWasmGc = false;
|
||||||
#endif
|
#endif
|
||||||
static bool enableWasmVerbose = false;
|
static bool enableWasmVerbose = false;
|
||||||
|
@ -10173,7 +10173,7 @@ static bool SetContextOptions(JSContext* cx, const OptionParser& op) {
|
||||||
#ifdef ENABLE_WASM_CRANELIFT
|
#ifdef ENABLE_WASM_CRANELIFT
|
||||||
wasmForceCranelift = op.getBoolOption("wasm-force-cranelift");
|
wasmForceCranelift = op.getBoolOption("wasm-force-cranelift");
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
enableWasmGc = op.getBoolOption("wasm-gc");
|
enableWasmGc = op.getBoolOption("wasm-gc");
|
||||||
#ifdef ENABLE_WASM_CRANELIFT
|
#ifdef ENABLE_WASM_CRANELIFT
|
||||||
if (enableWasmGc && wasmForceCranelift) {
|
if (enableWasmGc && wasmForceCranelift) {
|
||||||
|
@ -10202,7 +10202,7 @@ static bool SetContextOptions(JSContext* cx, const OptionParser& op) {
|
||||||
#ifdef ENABLE_WASM_CRANELIFT
|
#ifdef ENABLE_WASM_CRANELIFT
|
||||||
.setWasmForceCranelift(wasmForceCranelift)
|
.setWasmForceCranelift(wasmForceCranelift)
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
.setWasmGc(enableWasmGc)
|
.setWasmGc(enableWasmGc)
|
||||||
#endif
|
#endif
|
||||||
.setWasmVerbose(enableWasmVerbose)
|
.setWasmVerbose(enableWasmVerbose)
|
||||||
|
@ -10529,7 +10529,7 @@ static void SetWorkerContextOptions(JSContext* cx) {
|
||||||
#ifdef ENABLE_WASM_CRANELIFT
|
#ifdef ENABLE_WASM_CRANELIFT
|
||||||
.setWasmForceCranelift(wasmForceCranelift)
|
.setWasmForceCranelift(wasmForceCranelift)
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
.setWasmGc(enableWasmGc)
|
.setWasmGc(enableWasmGc)
|
||||||
#endif
|
#endif
|
||||||
.setWasmVerbose(enableWasmVerbose)
|
.setWasmVerbose(enableWasmVerbose)
|
||||||
|
@ -10932,7 +10932,7 @@ int main(int argc, char** argv, char** envp) {
|
||||||
!op.addBoolOption('\0', "test-wasm-await-tier2",
|
!op.addBoolOption('\0', "test-wasm-await-tier2",
|
||||||
"Forcibly activate tiering and block "
|
"Forcibly activate tiering and block "
|
||||||
"instantiation on completion of tier2")
|
"instantiation on completion of tier2")
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
|| !op.addBoolOption('\0', "wasm-gc", "Enable wasm GC features")
|
|| !op.addBoolOption('\0', "wasm-gc", "Enable wasm GC features")
|
||||||
#else
|
#else
|
||||||
|| !op.addBoolOption('\0', "wasm-gc", "No-op")
|
|| !op.addBoolOption('\0', "wasm-gc", "No-op")
|
||||||
|
|
|
@ -1292,7 +1292,7 @@ class AstModule : public AstNode {
|
||||||
NameVector funcImportNames_;
|
NameVector funcImportNames_;
|
||||||
AstTableVector tables_;
|
AstTableVector tables_;
|
||||||
AstMemoryVector memories_;
|
AstMemoryVector memories_;
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
uint32_t gcFeatureOptIn_;
|
uint32_t gcFeatureOptIn_;
|
||||||
#endif
|
#endif
|
||||||
ExportVector exports_;
|
ExportVector exports_;
|
||||||
|
@ -1313,7 +1313,7 @@ class AstModule : public AstNode {
|
||||||
funcImportNames_(lifo),
|
funcImportNames_(lifo),
|
||||||
tables_(lifo),
|
tables_(lifo),
|
||||||
memories_(lifo),
|
memories_(lifo),
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
gcFeatureOptIn_(0),
|
gcFeatureOptIn_(0),
|
||||||
#endif
|
#endif
|
||||||
exports_(lifo),
|
exports_(lifo),
|
||||||
|
@ -1328,7 +1328,7 @@ class AstModule : public AstNode {
|
||||||
}
|
}
|
||||||
bool hasMemory() const { return !!memories_.length(); }
|
bool hasMemory() const { return !!memories_.length(); }
|
||||||
const AstMemoryVector& memories() const { return memories_; }
|
const AstMemoryVector& memories() const { return memories_; }
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
bool addGcFeatureOptIn(uint32_t version) {
|
bool addGcFeatureOptIn(uint32_t version) {
|
||||||
gcFeatureOptIn_ = version;
|
gcFeatureOptIn_ = version;
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -11454,6 +11454,8 @@ bool BaseCompiler::emitBody() {
|
||||||
}
|
}
|
||||||
CHECK_NEXT(
|
CHECK_NEXT(
|
||||||
emitComparison(emitCompareRef, ValType::AnyRef, Assembler::Equal));
|
emitComparison(emitCompareRef, ValType::AnyRef, Assembler::Equal));
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
case uint16_t(Op::RefNull):
|
case uint16_t(Op::RefNull):
|
||||||
if (env_.gcTypesEnabled() == HasGcTypes::False) {
|
if (env_.gcTypesEnabled() == HasGcTypes::False) {
|
||||||
return iter_.unrecognizedOpcode(&op);
|
return iter_.unrecognizedOpcode(&op);
|
||||||
|
|
|
@ -74,11 +74,7 @@ uint32_t wasm::ObservedCPUFeatures() {
|
||||||
|
|
||||||
CompileArgs::CompileArgs(JSContext* cx, ScriptedCaller&& scriptedCaller)
|
CompileArgs::CompileArgs(JSContext* cx, ScriptedCaller&& scriptedCaller)
|
||||||
: scriptedCaller(std::move(scriptedCaller)) {
|
: scriptedCaller(std::move(scriptedCaller)) {
|
||||||
#ifdef ENABLE_WASM_GC
|
bool gcEnabled = HasReftypesSupport(cx);
|
||||||
bool gcEnabled = HasGcSupport(cx);
|
|
||||||
#else
|
|
||||||
bool gcEnabled = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
baselineEnabled = cx->options().wasmBaseline();
|
baselineEnabled = cx->options().wasmBaseline();
|
||||||
ionEnabled = cx->options().wasmIon();
|
ionEnabled = cx->options().wasmIon();
|
||||||
|
|
|
@ -3650,6 +3650,8 @@ static bool EmitBodyExprs(FunctionCompiler& f) {
|
||||||
|
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_GC
|
||||||
case uint16_t(Op::RefEq):
|
case uint16_t(Op::RefEq):
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
case uint16_t(Op::RefNull):
|
case uint16_t(Op::RefNull):
|
||||||
case uint16_t(Op::RefIsNull):
|
case uint16_t(Op::RefIsNull):
|
||||||
// Not yet supported
|
// Not yet supported
|
||||||
|
|
|
@ -57,13 +57,13 @@ using mozilla::RangedPtr;
|
||||||
|
|
||||||
extern mozilla::Atomic<bool> fuzzingSafe;
|
extern mozilla::Atomic<bool> fuzzingSafe;
|
||||||
|
|
||||||
bool wasm::HasGcSupport(JSContext* cx) {
|
bool wasm::HasReftypesSupport(JSContext* cx) {
|
||||||
#ifdef ENABLE_WASM_CRANELIFT
|
#ifdef ENABLE_WASM_CRANELIFT
|
||||||
if (cx->options().wasmForceCranelift()) {
|
if (cx->options().wasmForceCranelift()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
return cx->options().wasmGc() && cx->options().wasmBaseline();
|
return cx->options().wasmGc() && cx->options().wasmBaseline();
|
||||||
#else
|
#else
|
||||||
return false;
|
return false;
|
||||||
|
@ -2060,7 +2060,7 @@ bool WasmTableObject::isNewborn() const {
|
||||||
tableKind = TableKind::AnyFunction;
|
tableKind = TableKind::AnyFunction;
|
||||||
#ifdef ENABLE_WASM_GENERALIZED_TABLES
|
#ifdef ENABLE_WASM_GENERALIZED_TABLES
|
||||||
} else if (StringEqualsAscii(elementLinearStr, "anyref")) {
|
} else if (StringEqualsAscii(elementLinearStr, "anyref")) {
|
||||||
if (!HasGcSupport(cx)) {
|
if (!HasReftypesSupport(cx)) {
|
||||||
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
|
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
|
||||||
JSMSG_WASM_BAD_ELEMENT);
|
JSMSG_WASM_BAD_ELEMENT);
|
||||||
return false;
|
return false;
|
||||||
|
@ -2472,8 +2472,8 @@ const Class WasmGlobalObject::class_ = {
|
||||||
globalType = ValType::F32;
|
globalType = ValType::F32;
|
||||||
} else if (StringEqualsAscii(typeLinearStr, "f64")) {
|
} else if (StringEqualsAscii(typeLinearStr, "f64")) {
|
||||||
globalType = ValType::F64;
|
globalType = ValType::F64;
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
} else if (HasGcSupport(cx) &&
|
} else if (HasReftypesSupport(cx) &&
|
||||||
StringEqualsAscii(typeLinearStr, "anyref")) {
|
StringEqualsAscii(typeLinearStr, "anyref")) {
|
||||||
globalType = ValType::AnyRef;
|
globalType = ValType::AnyRef;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -56,7 +56,7 @@ bool HasCachingSupport(JSContext* cx);
|
||||||
// Returns true if WebAssembly as configured by compile-time flags and run-time
|
// Returns true if WebAssembly as configured by compile-time flags and run-time
|
||||||
// options can support reference types and stack walking.
|
// options can support reference types and stack walking.
|
||||||
|
|
||||||
bool HasGcSupport(JSContext* cx);
|
bool HasReftypesSupport(JSContext* cx);
|
||||||
|
|
||||||
// Compiles the given binary wasm module given the ArrayBufferObject
|
// Compiles the given binary wasm module given the ArrayBufferObject
|
||||||
// and links the module's imports with the given import object.
|
// and links the module's imports with the given import object.
|
||||||
|
|
|
@ -23,15 +23,24 @@ using namespace js::jit;
|
||||||
using namespace js::wasm;
|
using namespace js::wasm;
|
||||||
|
|
||||||
#ifdef ENABLE_WASM_GENERALIZED_TABLES
|
#ifdef ENABLE_WASM_GENERALIZED_TABLES
|
||||||
// Actually we depend only on the reftypes proposal; this guard will change once
|
#ifndef ENABLE_WASM_REFTYPES
|
||||||
// reftypes and GC are pried apart properly.
|
#error "Generalized tables require the reftypes feature"
|
||||||
#ifndef ENABLE_WASM_GC
|
#endif
|
||||||
#error "Generalized tables require the GC feature"
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_WASM_GC
|
||||||
|
#ifndef ENABLE_WASM_REFTYPES
|
||||||
|
#error "GC types require the reftypes feature"
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
||||||
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
|
#define WASM_REF_OP(code) return code
|
||||||
|
#else
|
||||||
|
#define WASM_REF_OP(code) break
|
||||||
|
#endif
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_GC
|
||||||
#define WASM_GC_OP(code) return code
|
#define WASM_GC_OP(code) return code
|
||||||
#else
|
#else
|
||||||
|
@ -172,7 +181,6 @@ OpKind wasm::Classify(OpBytes op) {
|
||||||
case Op::F64Le:
|
case Op::F64Le:
|
||||||
case Op::F64Gt:
|
case Op::F64Gt:
|
||||||
case Op::F64Ge:
|
case Op::F64Ge:
|
||||||
case Op::RefEq:
|
|
||||||
return OpKind::Comparison;
|
return OpKind::Comparison;
|
||||||
case Op::I32Eqz:
|
case Op::I32Eqz:
|
||||||
case Op::I32WrapI64:
|
case Op::I32WrapI64:
|
||||||
|
@ -201,7 +209,6 @@ OpKind wasm::Classify(OpBytes op) {
|
||||||
case Op::F64ConvertUI64:
|
case Op::F64ConvertUI64:
|
||||||
case Op::F64ReinterpretI64:
|
case Op::F64ReinterpretI64:
|
||||||
case Op::F64PromoteF32:
|
case Op::F64PromoteF32:
|
||||||
case Op::RefIsNull:
|
|
||||||
case Op::I32Extend8S:
|
case Op::I32Extend8S:
|
||||||
case Op::I32Extend16S:
|
case Op::I32Extend16S:
|
||||||
case Op::I64Extend8S:
|
case Op::I64Extend8S:
|
||||||
|
@ -264,7 +271,11 @@ OpKind wasm::Classify(OpBytes op) {
|
||||||
case Op::GrowMemory:
|
case Op::GrowMemory:
|
||||||
return OpKind::GrowMemory;
|
return OpKind::GrowMemory;
|
||||||
case Op::RefNull:
|
case Op::RefNull:
|
||||||
WASM_GC_OP(OpKind::RefNull);
|
WASM_REF_OP(OpKind::RefNull);
|
||||||
|
case Op::RefIsNull:
|
||||||
|
WASM_REF_OP(OpKind::Conversion);
|
||||||
|
case Op::RefEq:
|
||||||
|
WASM_GC_OP(OpKind::Comparison);
|
||||||
case Op::MiscPrefix: {
|
case Op::MiscPrefix: {
|
||||||
switch (MiscOp(op.b1)) {
|
switch (MiscOp(op.b1)) {
|
||||||
case MiscOp::Limit:
|
case MiscOp::Limit:
|
||||||
|
|
|
@ -222,7 +222,7 @@ static const unsigned NonVolatileRegsPushSize =
|
||||||
NonVolatileRegs.fpus().getPushSizeInBytes();
|
NonVolatileRegs.fpus().getPushSizeInBytes();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
static const unsigned NumExtraPushed = 2; // tls and argv
|
static const unsigned NumExtraPushed = 2; // tls and argv
|
||||||
#else
|
#else
|
||||||
static const unsigned NumExtraPushed = 1; // argv
|
static const unsigned NumExtraPushed = 1; // argv
|
||||||
|
@ -346,7 +346,7 @@ static bool GenerateInterpEntry(MacroAssembler& masm, const FuncExport& fe,
|
||||||
WasmTlsReg);
|
WasmTlsReg);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
WasmPush(masm, WasmTlsReg);
|
WasmPush(masm, WasmTlsReg);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -403,7 +403,7 @@ static bool GenerateInterpEntry(MacroAssembler& masm, const FuncExport& fe,
|
||||||
// Recover the 'argv' pointer which was saved before aligning the stack.
|
// Recover the 'argv' pointer which was saved before aligning the stack.
|
||||||
WasmPop(masm, argv);
|
WasmPop(masm, argv);
|
||||||
|
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
WasmPop(masm, WasmTlsReg);
|
WasmPop(masm, WasmTlsReg);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -88,7 +88,7 @@ class WasmToken {
|
||||||
Field,
|
Field,
|
||||||
Float,
|
Float,
|
||||||
Func,
|
Func,
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
GcFeatureOptIn,
|
GcFeatureOptIn,
|
||||||
#endif
|
#endif
|
||||||
GetGlobal,
|
GetGlobal,
|
||||||
|
@ -365,7 +365,7 @@ class WasmToken {
|
||||||
case Field:
|
case Field:
|
||||||
case Float:
|
case Float:
|
||||||
case Func:
|
case Func:
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
case GcFeatureOptIn:
|
case GcFeatureOptIn:
|
||||||
#endif
|
#endif
|
||||||
case Global:
|
case Global:
|
||||||
|
@ -1308,7 +1308,7 @@ WasmToken WasmTokenStream::next() {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'g':
|
case 'g':
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
if (consume(u"gc_feature_opt_in")) {
|
if (consume(u"gc_feature_opt_in")) {
|
||||||
return WasmToken(WasmToken::GcFeatureOptIn, begin, cur_);
|
return WasmToken(WasmToken::GcFeatureOptIn, begin, cur_);
|
||||||
}
|
}
|
||||||
|
@ -4532,7 +4532,7 @@ static bool ParseMemory(WasmParseContext& c, AstModule* module) {
|
||||||
return module->addMemory(name, memory);
|
return module->addMemory(name, memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
// Custom section for experimental work. The size of this section should always
|
// Custom section for experimental work. The size of this section should always
|
||||||
// be 1 byte, and that byte is a nonzero varint7 carrying the version number
|
// be 1 byte, and that byte is a nonzero varint7 carrying the version number
|
||||||
// being opted into.
|
// being opted into.
|
||||||
|
@ -5076,7 +5076,7 @@ static AstModule* ParseModule(const char16_t* text, uintptr_t stackLimit,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
case WasmToken::GcFeatureOptIn: {
|
case WasmToken::GcFeatureOptIn: {
|
||||||
if (!ParseGcFeatureOptIn(c, module)) {
|
if (!ParseGcFeatureOptIn(c, module)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -6560,7 +6560,7 @@ static bool EncodeExpr(Encoder& e, AstExpr& expr) {
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
// wasm AST binary serialization
|
// wasm AST binary serialization
|
||||||
|
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
static bool EncodeGcFeatureOptInSection(Encoder& e, AstModule& module) {
|
static bool EncodeGcFeatureOptInSection(Encoder& e, AstModule& module) {
|
||||||
uint32_t optInVersion = module.gcFeatureOptIn();
|
uint32_t optInVersion = module.gcFeatureOptIn();
|
||||||
if (!optInVersion) {
|
if (!optInVersion) {
|
||||||
|
@ -7158,7 +7158,7 @@ static bool EncodeModule(AstModule& module, Uint32Vector* offsets,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
if (!EncodeGcFeatureOptInSection(e, module)) {
|
if (!EncodeGcFeatureOptInSection(e, module)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -981,6 +981,8 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env,
|
||||||
CHECK(iter.readComparison(ValType::AnyRef, ¬hing, ¬hing));
|
CHECK(iter.readComparison(ValType::AnyRef, ¬hing, ¬hing));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
case uint16_t(Op::RefNull): {
|
case uint16_t(Op::RefNull): {
|
||||||
if (env.gcTypesEnabled() == HasGcTypes::False) {
|
if (env.gcTypesEnabled() == HasGcTypes::False) {
|
||||||
return iter.unrecognizedOpcode(&op);
|
return iter.unrecognizedOpcode(&op);
|
||||||
|
@ -1414,7 +1416,7 @@ static bool DecodeStructType(Decoder& d, ModuleEnvironment* env,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
static bool DecodeGCFeatureOptInSection(Decoder& d, ModuleEnvironment* env) {
|
static bool DecodeGCFeatureOptInSection(Decoder& d, ModuleEnvironment* env) {
|
||||||
MaybeSectionRange range;
|
MaybeSectionRange range;
|
||||||
if (!d.startSection(SectionId::GcFeatureOptIn, env, &range, "type")) {
|
if (!d.startSection(SectionId::GcFeatureOptIn, env, &range, "type")) {
|
||||||
|
@ -2416,7 +2418,7 @@ bool wasm::DecodeModuleEnvironment(Decoder& d, ModuleEnvironment* env) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
if (!DecodeGCFeatureOptInSection(d, env)) {
|
if (!DecodeGCFeatureOptInSection(d, env)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -2790,9 +2792,9 @@ bool wasm::Validate(JSContext* cx, const ShareableBytes& bytecode,
|
||||||
UniqueChars* error) {
|
UniqueChars* error) {
|
||||||
Decoder d(bytecode.bytes, 0, error);
|
Decoder d(bytecode.bytes, 0, error);
|
||||||
|
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
HasGcTypes gcTypesConfigured =
|
HasGcTypes gcTypesConfigured =
|
||||||
HasGcSupport(cx) ? HasGcTypes::True : HasGcTypes::False;
|
HasReftypesSupport(cx) ? HasGcTypes::True : HasGcTypes::False;
|
||||||
#else
|
#else
|
||||||
HasGcTypes gcTypesConfigured = HasGcTypes::False;
|
HasGcTypes gcTypesConfigured = HasGcTypes::False;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -144,7 +144,7 @@ struct ModuleEnvironment {
|
||||||
|
|
||||||
// Module fields decoded from the module environment (or initialized while
|
// Module fields decoded from the module environment (or initialized while
|
||||||
// validating an asm.js module) and immutable during compilation:
|
// validating an asm.js module) and immutable during compilation:
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
// `gcFeatureOptIn` reflects the presence in a module of a GcFeatureOptIn
|
// `gcFeatureOptIn` reflects the presence in a module of a GcFeatureOptIn
|
||||||
// section. This variable will be removed eventually, allowing it to be
|
// section. This variable will be removed eventually, allowing it to be
|
||||||
// replaced everywhere by the value HasGcTypes::True.
|
// replaced everywhere by the value HasGcTypes::True.
|
||||||
|
@ -185,7 +185,7 @@ struct ModuleEnvironment {
|
||||||
sharedMemoryEnabled(sharedMemoryEnabled),
|
sharedMemoryEnabled(sharedMemoryEnabled),
|
||||||
gcTypesConfigured(gcTypesConfigured),
|
gcTypesConfigured(gcTypesConfigured),
|
||||||
compilerEnv(compilerEnv),
|
compilerEnv(compilerEnv),
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
gcFeatureOptIn(HasGcTypes::False),
|
gcFeatureOptIn(HasGcTypes::False),
|
||||||
#endif
|
#endif
|
||||||
memoryUsage(MemoryUsage::None),
|
memoryUsage(MemoryUsage::None),
|
||||||
|
|
|
@ -774,7 +774,7 @@ static void ReloadPrefsCallback(const char* pref, XPCJSContext* xpccx) {
|
||||||
bool useWasmCranelift =
|
bool useWasmCranelift =
|
||||||
Preferences::GetBool(JS_OPTIONS_DOT_STR "wasm_cranelift");
|
Preferences::GetBool(JS_OPTIONS_DOT_STR "wasm_cranelift");
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
bool useWasmGc = Preferences::GetBool(JS_OPTIONS_DOT_STR "wasm_gc");
|
bool useWasmGc = Preferences::GetBool(JS_OPTIONS_DOT_STR "wasm_gc");
|
||||||
#endif
|
#endif
|
||||||
bool useWasmVerbose = Preferences::GetBool(JS_OPTIONS_DOT_STR "wasm_verbose");
|
bool useWasmVerbose = Preferences::GetBool(JS_OPTIONS_DOT_STR "wasm_verbose");
|
||||||
|
@ -867,7 +867,7 @@ static void ReloadPrefsCallback(const char* pref, XPCJSContext* xpccx) {
|
||||||
#ifdef ENABLE_WASM_CRANELIFT
|
#ifdef ENABLE_WASM_CRANELIFT
|
||||||
.setWasmForceCranelift(useWasmCranelift)
|
.setWasmForceCranelift(useWasmCranelift)
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
.setWasmGc(useWasmGc)
|
.setWasmGc(useWasmGc)
|
||||||
#endif
|
#endif
|
||||||
.setWasmVerbose(useWasmVerbose)
|
.setWasmVerbose(useWasmVerbose)
|
||||||
|
|
|
@ -64,4 +64,5 @@ if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||||
CXXFLAGS += ['-Wno-shadow', '-Werror=format']
|
CXXFLAGS += ['-Wno-shadow', '-Werror=format']
|
||||||
|
|
||||||
if CONFIG['NIGHTLY_BUILD']:
|
if CONFIG['NIGHTLY_BUILD']:
|
||||||
|
DEFINES['ENABLE_WASM_REFTYPES'] = True
|
||||||
DEFINES['ENABLE_WASM_GC'] = True
|
DEFINES['ENABLE_WASM_GC'] = True
|
||||||
|
|
|
@ -1467,7 +1467,7 @@ pref("javascript.options.wasm_baselinejit", true);
|
||||||
#ifdef ENABLE_WASM_CRANELIFT
|
#ifdef ENABLE_WASM_CRANELIFT
|
||||||
pref("javascript.options.wasm_cranelift", false);
|
pref("javascript.options.wasm_cranelift", false);
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_WASM_GC
|
#ifdef ENABLE_WASM_REFTYPES
|
||||||
pref("javascript.options.wasm_gc", false);
|
pref("javascript.options.wasm_gc", false);
|
||||||
#endif
|
#endif
|
||||||
pref("javascript.options.native_regexp", true);
|
pref("javascript.options.native_regexp", true);
|
||||||
|
|
|
@ -46,6 +46,7 @@ if CONFIG['MOZ_ENABLE_WEBRENDER']:
|
||||||
DEFINES['MOZ_ENABLE_WEBRENDER'] = True
|
DEFINES['MOZ_ENABLE_WEBRENDER'] = True
|
||||||
|
|
||||||
if CONFIG['NIGHTLY_BUILD']:
|
if CONFIG['NIGHTLY_BUILD']:
|
||||||
|
DEFINES['ENABLE_WASM_REFTYPES'] = True
|
||||||
DEFINES['ENABLE_WASM_GC'] = True
|
DEFINES['ENABLE_WASM_GC'] = True
|
||||||
|
|
||||||
FINAL_TARGET_PP_FILES += [
|
FINAL_TARGET_PP_FILES += [
|
||||||
|
|
Загрузка…
Ссылка в новой задаче