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.
This commit is contained in:
Lars T Hansen
2018-12-18 17:26:32 +01:00
parent 03518be2a4
commit 2e1b5941e2
44 changed files with 235 additions and 156 deletions

View File

@@ -286,7 +286,7 @@ void LoadContextOptions(const char* aPrefName, void* /* aClosure */) {
.setWasmForceCranelift(
GetWorkerPref<bool>(NS_LITERAL_CSTRING("wasm_cranelift")))
#endif
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
.setWasmGc(GetWorkerPref<bool>(NS_LITERAL_CSTRING("wasm_gc")))
#endif
.setWasmVerbose(GetWorkerPref<bool>(NS_LITERAL_CSTRING("wasm_verbose")))

View File

@@ -100,4 +100,5 @@ if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
CXXFLAGS += ['-Wno-error=shadow']
if CONFIG['NIGHTLY_BUILD']:
DEFINES['ENABLE_WASM_REFTYPES'] = True
DEFINES['ENABLE_WASM_GC'] = True

View File

@@ -670,9 +670,19 @@ static bool WasmBulkMemSupported(JSContext* cx, unsigned argc, Value* vp) {
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) {
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;
}
@@ -681,7 +691,7 @@ static bool WasmGeneralizedTables(JSContext* cx, unsigned argc, Value* vp) {
#ifdef ENABLE_WASM_GENERALIZED_TABLES
// Generalized tables depend on anyref, though not currently on (ref T)
// types nor on structures or other GC-proposal features.
bool isSupported = wasm::HasGcSupport(cx);
bool isSupported = wasm::HasReftypesSupport(cx);
#else
bool isSupported = false;
#endif
@@ -5957,9 +5967,13 @@ gc::ZealModeHelpText),
" 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. "),
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,
"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,
"wasmGeneralizedTables(bool)",

View File

@@ -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
// conversions that leaves the value unchanged. There are many cases,

View File

@@ -1,4 +1,4 @@
// |jit-test| skip-if: !wasmGcEnabled() || typeof WebAssembly.Global !== 'function'
// |jit-test| skip-if: !wasmReftypesEnabled() || typeof WebAssembly.Global !== 'function'
// Dummy object.
function Baguette(calories) {

View File

@@ -1,4 +1,4 @@
// |jit-test| skip-if: !wasmGcEnabled()
// |jit-test| skip-if: !wasmReftypesEnabled()
const { startProfiling, endProfiling, assertEqPreciseStacks, isSingleStepProfilingEnabled } = WasmHelpers;

View File

@@ -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
// we're interested in and eager JS compilation can upset the test.

View File

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

View File

@@ -1,4 +1,4 @@
// |jit-test| skip-if: !wasmGcEnabled()
// |jit-test| skip-if: !wasmReftypesEnabled()
gczeal(14, 1);
let { exports } = wasmEvalText(`(module

View File

@@ -1,5 +1,4 @@
// |jit-test| skip-if: !wasmGcEnabled()
// Ensure that if gc types aren't enabled, test cases properly fail.
// |jit-test| skip-if: !wasmReftypesEnabled()
// Dummy constructor.
function Baguette(calories) {
@@ -90,25 +89,11 @@ let { exports } = wasmEvalText(`(module
get_local 0
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_spill(), 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.

View File

@@ -1,4 +1,4 @@
// |jit-test| skip-if: !wasmGcEnabled()
// |jit-test| skip-if: !wasmReftypesEnabled()
load(libdir + "wasm-binary.js");

View File

@@ -1,4 +1,4 @@
// |jit-test| skip-if: !wasmGcEnabled() || !wasmDebuggingIsSupported()
// |jit-test| skip-if: !wasmReftypesEnabled() || !wasmDebuggingIsSupported()
(function() {
let g = newGlobal();

View File

@@ -0,0 +1,4 @@
// |jit-test| skip-if: wasmGcEnabled()
assertErrorMessage(() => wasmEvalText(`(module (func (param (ref 0)) (unreachable)))`),
WebAssembly.CompileError, /reference types not enabled/);

View File

@@ -1,4 +1,4 @@
// |jit-test| skip-if: wasmGcEnabled()
// |jit-test| skip-if: wasmReftypesEnabled()
const { CompileError, validate } = WebAssembly;

View File

@@ -1,4 +1,4 @@
// |jit-test| skip-if: !wasmGcEnabled()
// |jit-test| skip-if: !wasmReftypesEnabled()
enableShellAllocationMetadataBuilder();
gczeal(9, 1);

View File

@@ -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/);

View File

@@ -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
@@ -44,19 +46,6 @@ assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
WebAssembly.CompileError,
/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.
new WebAssembly.Module(wasmTextToBinary(
@@ -137,26 +126,3 @@ assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
WebAssembly.CompileError,
/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/);

View File

@@ -1,4 +1,4 @@
// |jit-test| skip-if: !wasmGcEnabled()
// |jit-test| skip-if: !wasmReftypesEnabled()
// Attempt to test intercalls from ion to baseline and back.
//

View File

@@ -1,8 +1,4 @@
if (!wasmGcEnabled()) {
assertErrorMessage(() => wasmEvalText(`(module (func (param (ref 0)) (unreachable)))`),
WebAssembly.CompileError, /reference types not enabled/);
quit(0);
}
// |jit-test| skip-if: !wasmGcEnabled()
// Parsing and resolving.

View File

@@ -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
// in wasm that lead to JS allocation. Does not test any timeout or interrupt

View File

@@ -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
// allocation. The structure is

View File

@@ -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
// held live -- at least for a short while -- only by references from the wasm

View File

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

View File

@@ -223,7 +223,6 @@ assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
/table index out of range for table.get/);
// 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
@@ -232,23 +231,15 @@ assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
`(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))))`);
(table.set (get_local 0) (ref.null))))`);
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/);
@@ -378,22 +369,6 @@ assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(
WebAssembly.CompileError,
/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
for (let visibility of ['', '(export "t")', '(import "m" "t")']) {

View File

@@ -211,7 +211,7 @@ JitCompileOptions::JitCompileOptions()
: cloneSingletons_(false),
profilerSlowAssertionsEnabled_(false),
offThreadCompilationAvailable_(false)
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
,
wasmGcEnabled_(false)
#endif
@@ -224,7 +224,7 @@ JitCompileOptions::JitCompileOptions(JSContext* cx) {
cx->runtime()->geckoProfiler().enabled() &&
cx->runtime()->geckoProfiler().slowAssertionsEnabled();
offThreadCompilationAvailable_ = OffThreadCompilationAvailable(cx);
#ifdef ENABLE_WASM_GC
wasmGcEnabled_ = wasm::HasGcSupport(cx);
#ifdef ENABLE_WASM_REFTYPES
wasmGcEnabled_ = wasm::HasReftypesSupport(cx);
#endif
}

View File

@@ -130,7 +130,7 @@ class JitCompileOptions {
return offThreadCompilationAvailable_;
}
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
bool wasmGcEnabled() const { return wasmGcEnabled_; }
#endif
@@ -138,7 +138,7 @@ class JitCompileOptions {
bool cloneSingletons_;
bool profilerSlowAssertionsEnabled_;
bool offThreadCompilationAvailable_;
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
bool wasmGcEnabled_;
#endif
};

View File

@@ -6,10 +6,20 @@
# Nightly-only features
if CONFIG['NIGHTLY_BUILD']:
# TypedObject
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_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
# 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
# Some huge-mapping optimization instead of bounds checks on supported

View File

@@ -398,7 +398,7 @@ class JS_PUBLIC_API ContextOptions {
#ifdef ENABLE_WASM_CRANELIFT
wasmForceCranelift_(false),
#endif
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
wasmGc_(false),
#endif
testWasmAwaitTier2_(false),
@@ -489,7 +489,7 @@ class JS_PUBLIC_API ContextOptions {
return *this;
}
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
bool wasmGc() const { return wasmGc_; }
ContextOptions& setWasmGc(bool flag) {
wasmGc_ = flag;
@@ -580,7 +580,7 @@ class JS_PUBLIC_API ContextOptions {
setWasm(false);
setWasmBaseline(false);
setWasmIon(false);
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
setWasmGc(false);
#endif
setNativeRegExp(false);
@@ -597,7 +597,7 @@ class JS_PUBLIC_API ContextOptions {
#ifdef ENABLE_WASM_CRANELIFT
bool wasmForceCranelift_ : 1;
#endif
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
bool wasmGc_ : 1;
#endif
bool testWasmAwaitTier2_ : 1;

View File

@@ -494,7 +494,7 @@ static bool enableWasmIon = false;
#ifdef ENABLE_WASM_CRANELIFT
static bool wasmForceCranelift = false;
#endif
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
static bool enableWasmGc = false;
#endif
static bool enableWasmVerbose = false;
@@ -10173,7 +10173,7 @@ static bool SetContextOptions(JSContext* cx, const OptionParser& op) {
#ifdef ENABLE_WASM_CRANELIFT
wasmForceCranelift = op.getBoolOption("wasm-force-cranelift");
#endif
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
enableWasmGc = op.getBoolOption("wasm-gc");
#ifdef ENABLE_WASM_CRANELIFT
if (enableWasmGc && wasmForceCranelift) {
@@ -10202,7 +10202,7 @@ static bool SetContextOptions(JSContext* cx, const OptionParser& op) {
#ifdef ENABLE_WASM_CRANELIFT
.setWasmForceCranelift(wasmForceCranelift)
#endif
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
.setWasmGc(enableWasmGc)
#endif
.setWasmVerbose(enableWasmVerbose)
@@ -10529,7 +10529,7 @@ static void SetWorkerContextOptions(JSContext* cx) {
#ifdef ENABLE_WASM_CRANELIFT
.setWasmForceCranelift(wasmForceCranelift)
#endif
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
.setWasmGc(enableWasmGc)
#endif
.setWasmVerbose(enableWasmVerbose)
@@ -10932,7 +10932,7 @@ int main(int argc, char** argv, char** envp) {
!op.addBoolOption('\0', "test-wasm-await-tier2",
"Forcibly activate tiering and block "
"instantiation on completion of tier2")
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
|| !op.addBoolOption('\0', "wasm-gc", "Enable wasm GC features")
#else
|| !op.addBoolOption('\0', "wasm-gc", "No-op")

View File

@@ -1292,7 +1292,7 @@ class AstModule : public AstNode {
NameVector funcImportNames_;
AstTableVector tables_;
AstMemoryVector memories_;
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
uint32_t gcFeatureOptIn_;
#endif
ExportVector exports_;
@@ -1313,7 +1313,7 @@ class AstModule : public AstNode {
funcImportNames_(lifo),
tables_(lifo),
memories_(lifo),
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
gcFeatureOptIn_(0),
#endif
exports_(lifo),
@@ -1328,7 +1328,7 @@ class AstModule : public AstNode {
}
bool hasMemory() const { return !!memories_.length(); }
const AstMemoryVector& memories() const { return memories_; }
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
bool addGcFeatureOptIn(uint32_t version) {
gcFeatureOptIn_ = version;
return true;

View File

@@ -11454,6 +11454,8 @@ bool BaseCompiler::emitBody() {
}
CHECK_NEXT(
emitComparison(emitCompareRef, ValType::AnyRef, Assembler::Equal));
#endif
#ifdef ENABLE_WASM_REFTYPES
case uint16_t(Op::RefNull):
if (env_.gcTypesEnabled() == HasGcTypes::False) {
return iter_.unrecognizedOpcode(&op);

View File

@@ -74,11 +74,7 @@ uint32_t wasm::ObservedCPUFeatures() {
CompileArgs::CompileArgs(JSContext* cx, ScriptedCaller&& scriptedCaller)
: scriptedCaller(std::move(scriptedCaller)) {
#ifdef ENABLE_WASM_GC
bool gcEnabled = HasGcSupport(cx);
#else
bool gcEnabled = false;
#endif
bool gcEnabled = HasReftypesSupport(cx);
baselineEnabled = cx->options().wasmBaseline();
ionEnabled = cx->options().wasmIon();

View File

@@ -3650,6 +3650,8 @@ static bool EmitBodyExprs(FunctionCompiler& f) {
#ifdef ENABLE_WASM_GC
case uint16_t(Op::RefEq):
#endif
#ifdef ENABLE_WASM_REFTYPES
case uint16_t(Op::RefNull):
case uint16_t(Op::RefIsNull):
// Not yet supported

View File

@@ -57,13 +57,13 @@ using mozilla::RangedPtr;
extern mozilla::Atomic<bool> fuzzingSafe;
bool wasm::HasGcSupport(JSContext* cx) {
bool wasm::HasReftypesSupport(JSContext* cx) {
#ifdef ENABLE_WASM_CRANELIFT
if (cx->options().wasmForceCranelift()) {
return false;
}
#endif
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
return cx->options().wasmGc() && cx->options().wasmBaseline();
#else
return false;
@@ -2060,7 +2060,7 @@ bool WasmTableObject::isNewborn() const {
tableKind = TableKind::AnyFunction;
#ifdef ENABLE_WASM_GENERALIZED_TABLES
} else if (StringEqualsAscii(elementLinearStr, "anyref")) {
if (!HasGcSupport(cx)) {
if (!HasReftypesSupport(cx)) {
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
JSMSG_WASM_BAD_ELEMENT);
return false;
@@ -2472,8 +2472,8 @@ const Class WasmGlobalObject::class_ = {
globalType = ValType::F32;
} else if (StringEqualsAscii(typeLinearStr, "f64")) {
globalType = ValType::F64;
#ifdef ENABLE_WASM_GC
} else if (HasGcSupport(cx) &&
#ifdef ENABLE_WASM_REFTYPES
} else if (HasReftypesSupport(cx) &&
StringEqualsAscii(typeLinearStr, "anyref")) {
globalType = ValType::AnyRef;
#endif

View File

@@ -56,7 +56,7 @@ bool HasCachingSupport(JSContext* cx);
// Returns true if WebAssembly as configured by compile-time flags and run-time
// 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
// and links the module's imports with the given import object.

View File

@@ -23,15 +23,24 @@ using namespace js::jit;
using namespace js::wasm;
#ifdef ENABLE_WASM_GENERALIZED_TABLES
// Actually we depend only on the reftypes proposal; this guard will change once
// reftypes and GC are pried apart properly.
#ifndef ENABLE_WASM_GC
#error "Generalized tables require the GC feature"
#ifndef ENABLE_WASM_REFTYPES
#error "Generalized tables require the reftypes feature"
#endif
#endif
#ifdef ENABLE_WASM_GC
#ifndef ENABLE_WASM_REFTYPES
#error "GC types require the reftypes feature"
#endif
#endif
#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
#define WASM_GC_OP(code) return code
#else
@@ -172,7 +181,6 @@ OpKind wasm::Classify(OpBytes op) {
case Op::F64Le:
case Op::F64Gt:
case Op::F64Ge:
case Op::RefEq:
return OpKind::Comparison;
case Op::I32Eqz:
case Op::I32WrapI64:
@@ -201,7 +209,6 @@ OpKind wasm::Classify(OpBytes op) {
case Op::F64ConvertUI64:
case Op::F64ReinterpretI64:
case Op::F64PromoteF32:
case Op::RefIsNull:
case Op::I32Extend8S:
case Op::I32Extend16S:
case Op::I64Extend8S:
@@ -264,7 +271,11 @@ OpKind wasm::Classify(OpBytes op) {
case Op::GrowMemory:
return OpKind::GrowMemory;
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: {
switch (MiscOp(op.b1)) {
case MiscOp::Limit:

View File

@@ -222,7 +222,7 @@ static const unsigned NonVolatileRegsPushSize =
NonVolatileRegs.fpus().getPushSizeInBytes();
#endif
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
static const unsigned NumExtraPushed = 2; // tls and argv
#else
static const unsigned NumExtraPushed = 1; // argv
@@ -346,7 +346,7 @@ static bool GenerateInterpEntry(MacroAssembler& masm, const FuncExport& fe,
WasmTlsReg);
}
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
WasmPush(masm, WasmTlsReg);
#endif
@@ -403,7 +403,7 @@ static bool GenerateInterpEntry(MacroAssembler& masm, const FuncExport& fe,
// Recover the 'argv' pointer which was saved before aligning the stack.
WasmPop(masm, argv);
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
WasmPop(masm, WasmTlsReg);
#endif

View File

@@ -88,7 +88,7 @@ class WasmToken {
Field,
Float,
Func,
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
GcFeatureOptIn,
#endif
GetGlobal,
@@ -365,7 +365,7 @@ class WasmToken {
case Field:
case Float:
case Func:
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
case GcFeatureOptIn:
#endif
case Global:
@@ -1308,7 +1308,7 @@ WasmToken WasmTokenStream::next() {
break;
case 'g':
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
if (consume(u"gc_feature_opt_in")) {
return WasmToken(WasmToken::GcFeatureOptIn, begin, cur_);
}
@@ -4532,7 +4532,7 @@ static bool ParseMemory(WasmParseContext& c, AstModule* module) {
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
// be 1 byte, and that byte is a nonzero varint7 carrying the version number
// being opted into.
@@ -5076,7 +5076,7 @@ static AstModule* ParseModule(const char16_t* text, uintptr_t stackLimit,
}
break;
}
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
case WasmToken::GcFeatureOptIn: {
if (!ParseGcFeatureOptIn(c, module)) {
return nullptr;
@@ -6560,7 +6560,7 @@ static bool EncodeExpr(Encoder& e, AstExpr& expr) {
/*****************************************************************************/
// wasm AST binary serialization
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
static bool EncodeGcFeatureOptInSection(Encoder& e, AstModule& module) {
uint32_t optInVersion = module.gcFeatureOptIn();
if (!optInVersion) {
@@ -7158,7 +7158,7 @@ static bool EncodeModule(AstModule& module, Uint32Vector* offsets,
return false;
}
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
if (!EncodeGcFeatureOptInSection(e, module)) {
return false;
}

View File

@@ -981,6 +981,8 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env,
CHECK(iter.readComparison(ValType::AnyRef, &nothing, &nothing));
break;
}
#endif
#ifdef ENABLE_WASM_REFTYPES
case uint16_t(Op::RefNull): {
if (env.gcTypesEnabled() == HasGcTypes::False) {
return iter.unrecognizedOpcode(&op);
@@ -1414,7 +1416,7 @@ static bool DecodeStructType(Decoder& d, ModuleEnvironment* env,
return true;
}
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
static bool DecodeGCFeatureOptInSection(Decoder& d, ModuleEnvironment* env) {
MaybeSectionRange range;
if (!d.startSection(SectionId::GcFeatureOptIn, env, &range, "type")) {
@@ -2416,7 +2418,7 @@ bool wasm::DecodeModuleEnvironment(Decoder& d, ModuleEnvironment* env) {
return false;
}
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
if (!DecodeGCFeatureOptInSection(d, env)) {
return false;
}
@@ -2790,9 +2792,9 @@ bool wasm::Validate(JSContext* cx, const ShareableBytes& bytecode,
UniqueChars* error) {
Decoder d(bytecode.bytes, 0, error);
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
HasGcTypes gcTypesConfigured =
HasGcSupport(cx) ? HasGcTypes::True : HasGcTypes::False;
HasReftypesSupport(cx) ? HasGcTypes::True : HasGcTypes::False;
#else
HasGcTypes gcTypesConfigured = HasGcTypes::False;
#endif

View File

@@ -144,7 +144,7 @@ struct ModuleEnvironment {
// Module fields decoded from the module environment (or initialized while
// 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
// section. This variable will be removed eventually, allowing it to be
// replaced everywhere by the value HasGcTypes::True.
@@ -185,7 +185,7 @@ struct ModuleEnvironment {
sharedMemoryEnabled(sharedMemoryEnabled),
gcTypesConfigured(gcTypesConfigured),
compilerEnv(compilerEnv),
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
gcFeatureOptIn(HasGcTypes::False),
#endif
memoryUsage(MemoryUsage::None),

View File

@@ -774,7 +774,7 @@ static void ReloadPrefsCallback(const char* pref, XPCJSContext* xpccx) {
bool useWasmCranelift =
Preferences::GetBool(JS_OPTIONS_DOT_STR "wasm_cranelift");
#endif
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
bool useWasmGc = Preferences::GetBool(JS_OPTIONS_DOT_STR "wasm_gc");
#endif
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
.setWasmForceCranelift(useWasmCranelift)
#endif
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
.setWasmGc(useWasmGc)
#endif
.setWasmVerbose(useWasmVerbose)

View File

@@ -64,4 +64,5 @@ if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
CXXFLAGS += ['-Wno-shadow', '-Werror=format']
if CONFIG['NIGHTLY_BUILD']:
DEFINES['ENABLE_WASM_REFTYPES'] = True
DEFINES['ENABLE_WASM_GC'] = True

View File

@@ -1467,7 +1467,7 @@ pref("javascript.options.wasm_baselinejit", true);
#ifdef ENABLE_WASM_CRANELIFT
pref("javascript.options.wasm_cranelift", false);
#endif
#ifdef ENABLE_WASM_GC
#ifdef ENABLE_WASM_REFTYPES
pref("javascript.options.wasm_gc", false);
#endif
pref("javascript.options.native_regexp", true);

View File

@@ -46,6 +46,7 @@ if CONFIG['MOZ_ENABLE_WEBRENDER']:
DEFINES['MOZ_ENABLE_WEBRENDER'] = True
if CONFIG['NIGHTLY_BUILD']:
DEFINES['ENABLE_WASM_REFTYPES'] = True
DEFINES['ENABLE_WASM_GC'] = True
FINAL_TARGET_PP_FILES += [