зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1511958 - Implement i64<>JavaScript’s BigInt conversions proposal (part 2, runtime flag and testing function)
This is part 2 of a series of revs that split up D41710 (for Wasm I64 to BigInt conversion) into smaller revs. This rev depends on the compile-time flag added in D43177 and adds a runtime flag to JSContext options that will toggle whether I64 to BigInt conversion is used. The flag will get used mostly in WasmInstance.cpp, but it also needs to be used to toggle I64 error checks in both Ion inlining code and in Wasm stub generation code. To pass that information along, the flag is also put in CompileArgs for WasmCompile and then copied to wasm module metadata (so that it can be read from lazy stub generation code). Differential Revision: https://phabricator.services.mozilla.com/D43179
This commit is contained in:
Родитель
e77b837ae6
Коммит
7c2c17a2e7
|
@ -27,6 +27,9 @@ class JS_PUBLIC_API ContextOptions {
|
|||
wasmCranelift_(false),
|
||||
wasmGc_(false),
|
||||
testWasmAwaitTier2_(false),
|
||||
#ifdef ENABLE_WASM_BIGINT
|
||||
enableWasmBigInt_(false),
|
||||
#endif
|
||||
throwOnAsmJSValidationFailure_(false),
|
||||
asyncStack_(true),
|
||||
throwOnDebuggeeWouldRun_(true),
|
||||
|
@ -90,6 +93,14 @@ class JS_PUBLIC_API ContextOptions {
|
|||
return *this;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WASM_BIGINT
|
||||
bool isWasmBigIntEnabled() const { return enableWasmBigInt_; }
|
||||
ContextOptions& setWasmBigIntEnabled(bool flag) {
|
||||
enableWasmBigInt_ = flag;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool wasmGc() const { return wasmGc_; }
|
||||
// Defined out-of-line because it depends on a compile-time option
|
||||
ContextOptions& setWasmGc(bool flag);
|
||||
|
@ -178,6 +189,9 @@ class JS_PUBLIC_API ContextOptions {
|
|||
bool wasmCranelift_ : 1;
|
||||
bool wasmGc_ : 1;
|
||||
bool testWasmAwaitTier2_ : 1;
|
||||
#ifdef ENABLE_WASM_BIGINT
|
||||
bool enableWasmBigInt_ : 1;
|
||||
#endif
|
||||
bool throwOnAsmJSValidationFailure_ : 1;
|
||||
bool asyncStack_ : 1;
|
||||
bool throwOnDebuggeeWouldRun_ : 1;
|
||||
|
|
|
@ -795,6 +795,12 @@ static bool WasmMultiValueEnabled(JSContext* cx, unsigned argc, Value* vp) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool WasmBigIntEnabled(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
args.rval().setBoolean(wasm::HasI64BigIntSupport(cx));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool WasmDebugSupport(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
args.rval().setBoolean(cx->options().wasmBaseline() &&
|
||||
|
@ -6641,6 +6647,10 @@ gc::ZealModeHelpText),
|
|||
"wasmMultiValueEnabled()",
|
||||
" Returns a boolean indicating whether the WebAssembly multi-value proposal is enabled."),
|
||||
|
||||
JS_FN_HELP("wasmBigIntEnabled", WasmBigIntEnabled, 1, 0,
|
||||
"wasmBigIntEnabled()",
|
||||
" Returns a boolean indicating whether the WebAssembly I64 to BigInt proposal is enabled."),
|
||||
|
||||
JS_FN_HELP("wasmDebugSupport", WasmDebugSupport, 1, 0,
|
||||
"wasmDebugSupport()",
|
||||
" Returns a boolean indicating whether the WebAssembly compilers support debugging."),
|
||||
|
|
|
@ -486,6 +486,9 @@ bool shell::enableWasmGc = false;
|
|||
#endif
|
||||
bool shell::enableWasmVerbose = false;
|
||||
bool shell::enableTestWasmAwaitTier2 = false;
|
||||
#ifdef ENABLE_WASM_BIGINT
|
||||
bool shell::enableWasmBigInt = false;
|
||||
#endif
|
||||
bool shell::enableAsyncStacks = false;
|
||||
bool shell::enableStreams = false;
|
||||
bool shell::enableReadableByteStreams = false;
|
||||
|
@ -10228,6 +10231,9 @@ static bool SetContextOptions(JSContext* cx, const OptionParser& op) {
|
|||
enableReadableByteStreams = op.getBoolOption("enable-readable-byte-streams");
|
||||
enableBYOBStreamReaders = op.getBoolOption("enable-byob-stream-readers");
|
||||
enableWritableStreams = op.getBoolOption("enable-writable-streams");
|
||||
#ifdef ENABLE_WASM_BIGINT
|
||||
enableWasmBigInt = op.getBoolOption("wasm-bigint");
|
||||
#endif
|
||||
enableFields = !op.getBoolOption("disable-experimental-fields");
|
||||
enableAwaitFix = op.getBoolOption("enable-experimental-await-fix");
|
||||
enableWeakRefs = op.getBoolOption("enable-weak-refs");
|
||||
|
@ -10246,6 +10252,9 @@ static bool SetContextOptions(JSContext* cx, const OptionParser& op) {
|
|||
#endif
|
||||
.setWasmVerbose(enableWasmVerbose)
|
||||
.setTestWasmAwaitTier2(enableTestWasmAwaitTier2)
|
||||
#ifdef ENABLE_WASM_BIGINT
|
||||
.setWasmBigIntEnabled(enableWasmBigInt)
|
||||
#endif
|
||||
.setAsyncStack(enableAsyncStacks);
|
||||
|
||||
if (const char* str = op.getStringOption("cache-ir-stubs")) {
|
||||
|
@ -10570,6 +10579,9 @@ static void SetWorkerContextOptions(JSContext* cx) {
|
|||
#endif
|
||||
#ifdef ENABLE_WASM_GC
|
||||
.setWasmGc(enableWasmGc)
|
||||
#endif
|
||||
#ifdef ENABLE_WASM_BIGINT
|
||||
.setWasmBigIntEnabled(enableWasmBigInt)
|
||||
#endif
|
||||
.setWasmVerbose(enableWasmVerbose)
|
||||
.setTestWasmAwaitTier2(enableTestWasmAwaitTier2);
|
||||
|
@ -10978,6 +10990,12 @@ int main(int argc, char** argv, char** envp) {
|
|||
"Enable WebAssembly verbose logging") ||
|
||||
!op.addBoolOption('\0', "disable-wasm-huge-memory",
|
||||
"Disable WebAssembly huge memory") ||
|
||||
#ifdef ENABLE_WASM_BIGINT
|
||||
!op.addBoolOption('\0', "wasm-bigint",
|
||||
"Enable WebAssembly BigInt conversions") ||
|
||||
#else
|
||||
!op.addBoolOption('\0', "wasm-bigint", "No-op") ||
|
||||
#endif
|
||||
!op.addBoolOption('\0', "test-wasm-await-tier2",
|
||||
"Forcibly activate tiering and block "
|
||||
"instantiation on completion of tier2") ||
|
||||
|
|
|
@ -112,6 +112,9 @@ extern bool enableWasmGc;
|
|||
#endif
|
||||
extern bool enableWasmVerbose;
|
||||
extern bool enableTestWasmAwaitTier2;
|
||||
#ifdef ENABLE_WASM_BIGINT
|
||||
extern bool enableWasmBigInt;
|
||||
#endif
|
||||
extern bool enableAsyncStacks;
|
||||
extern bool enableStreams;
|
||||
extern bool enableReadableByteStreams;
|
||||
|
|
|
@ -1352,7 +1352,8 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidatorShared {
|
|||
arrayViews_(cx),
|
||||
compilerEnv_(CompileMode::Once, Tier::Optimized, OptimizedBackend::Ion,
|
||||
DebugEnabled::False, /* ref types */ false,
|
||||
/* gc types */ false, /* huge memory */ false),
|
||||
/* gc types */ false, /* huge memory */ false,
|
||||
/* bigint */ false),
|
||||
env_(&compilerEnv_, Shareable::False, ModuleKind::AsmJS) {
|
||||
compilerEnv_.computeParameters(/* gc types */ false);
|
||||
env_.minMemoryLength = RoundUpToNextValidAsmJSHeapLength(0);
|
||||
|
|
|
@ -668,6 +668,8 @@ bool LazyStubTier::createMany(const Uint32Vector& funcExportIndices,
|
|||
const FuncExportVector& funcExports = metadata.funcExports;
|
||||
uint8_t* moduleSegmentBase = codeTier.segment().base();
|
||||
|
||||
bool bigIntEnabled = codeTier.code().metadata().bigIntEnabled;
|
||||
|
||||
CodeRangeVector codeRanges;
|
||||
DebugOnly<uint32_t> numExpectedRanges = 0;
|
||||
for (uint32_t funcExportIndex : funcExportIndices) {
|
||||
|
@ -679,7 +681,7 @@ bool LazyStubTier::createMany(const Uint32Vector& funcExportIndices,
|
|||
Maybe<ImmPtr> callee;
|
||||
callee.emplace(calleePtr, ImmPtr::NoCheckToken());
|
||||
if (!GenerateEntryStubs(masm, funcExportIndex, fe, callee,
|
||||
/* asmjs */ false, &codeRanges)) {
|
||||
/* asmjs */ false, bigIntEnabled, &codeRanges)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -355,6 +355,9 @@ struct Metadata : public ShareableBase<Metadata>, public MetadataCacheablePod {
|
|||
FuncReturnTypesVector debugFuncReturnTypes;
|
||||
ModuleHash debugHash;
|
||||
|
||||
// Feature flag that gets copied from ModuleEnvironment for BigInt support.
|
||||
bool bigIntEnabled;
|
||||
|
||||
explicit Metadata(ModuleKind kind = ModuleKind::Wasm)
|
||||
: MetadataCacheablePod(kind), debugEnabled(false), debugHash() {}
|
||||
virtual ~Metadata() {}
|
||||
|
|
|
@ -92,6 +92,12 @@ SharedCompileArgs CompileArgs::build(JSContext* cx,
|
|||
bool gc = false;
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_WASM_BIGINT
|
||||
bool bigInt = cx->options().isWasmBigIntEnabled();
|
||||
#else
|
||||
bool bigInt = false;
|
||||
#endif
|
||||
|
||||
// Debug information such as source view or debug traps will require
|
||||
// additional memory and permanently stay in baseline code, so we try to
|
||||
// only enable it when a developer actually cares: when the debugger tab
|
||||
|
@ -145,6 +151,7 @@ SharedCompileArgs CompileArgs::build(JSContext* cx,
|
|||
target->forceTiering = forceTiering;
|
||||
target->gcEnabled = gc;
|
||||
target->hugeMemory = wasm::IsHugeMemoryEnabled();
|
||||
target->bigIntEnabled = bigInt;
|
||||
|
||||
return target;
|
||||
}
|
||||
|
@ -441,7 +448,7 @@ CompilerEnvironment::CompilerEnvironment(CompileMode mode, Tier tier,
|
|||
DebugEnabled debugEnabled,
|
||||
bool refTypesConfigured,
|
||||
bool gcTypesConfigured,
|
||||
bool hugeMemory)
|
||||
bool hugeMemory, bool bigIntConfigured)
|
||||
: state_(InitialWithModeTierDebug),
|
||||
mode_(mode),
|
||||
tier_(tier),
|
||||
|
@ -450,7 +457,8 @@ CompilerEnvironment::CompilerEnvironment(CompileMode mode, Tier tier,
|
|||
refTypes_(refTypesConfigured),
|
||||
gcTypes_(gcTypesConfigured),
|
||||
multiValues_(true),
|
||||
hugeMemory_(hugeMemory) {}
|
||||
hugeMemory_(hugeMemory),
|
||||
bigInt_(bigIntConfigured) {}
|
||||
|
||||
void CompilerEnvironment::computeParameters(bool gcFeatureOptIn) {
|
||||
MOZ_ASSERT(state_ == InitialWithModeTierDebug);
|
||||
|
@ -476,6 +484,7 @@ void CompilerEnvironment::computeParameters(Decoder& d, bool gcFeatureOptIn) {
|
|||
bool craneliftEnabled = args_->craneliftEnabled;
|
||||
bool forceTiering = args_->forceTiering;
|
||||
bool hugeMemory = args_->hugeMemory;
|
||||
bool bigIntEnabled = args_->bigIntEnabled;
|
||||
|
||||
bool hasSecondTier = ionEnabled || craneliftEnabled;
|
||||
MOZ_ASSERT_IF(gcEnabled || debugEnabled, baselineEnabled);
|
||||
|
@ -508,6 +517,7 @@ void CompilerEnvironment::computeParameters(Decoder& d, bool gcFeatureOptIn) {
|
|||
refTypes_ = !craneliftEnabled;
|
||||
multiValues_ = !craneliftEnabled;
|
||||
hugeMemory_ = hugeMemory;
|
||||
bigInt_ = bigIntEnabled && !craneliftEnabled;
|
||||
state_ = Computed;
|
||||
}
|
||||
|
||||
|
@ -608,6 +618,7 @@ void wasm::CompileTier2(const CompileArgs& args, const Bytes& bytecode,
|
|||
|
||||
bool gcTypesConfigured = false; // No optimized backend support yet
|
||||
bool refTypesConfigured = !args.craneliftEnabled;
|
||||
bool bigIntConfigured = args.bigIntEnabled && !args.craneliftEnabled;
|
||||
OptimizedBackend optimizedBackend = args.craneliftEnabled
|
||||
? OptimizedBackend::Cranelift
|
||||
: OptimizedBackend::Ion;
|
||||
|
@ -615,7 +626,7 @@ void wasm::CompileTier2(const CompileArgs& args, const Bytes& bytecode,
|
|||
CompilerEnvironment compilerEnv(CompileMode::Tier2, Tier::Optimized,
|
||||
optimizedBackend, DebugEnabled::False,
|
||||
refTypesConfigured, gcTypesConfigured,
|
||||
args.hugeMemory);
|
||||
args.hugeMemory, bigIntConfigured);
|
||||
|
||||
ModuleEnvironment env(&compilerEnv, args.sharedMemoryEnabled
|
||||
? Shareable::True
|
||||
|
|
|
@ -58,6 +58,7 @@ struct CompileArgs : ShareableBase<CompileArgs> {
|
|||
bool forceTiering;
|
||||
bool gcEnabled;
|
||||
bool hugeMemory;
|
||||
bool bigIntEnabled;
|
||||
|
||||
// CompileArgs has two constructors:
|
||||
//
|
||||
|
@ -80,7 +81,8 @@ struct CompileArgs : ShareableBase<CompileArgs> {
|
|||
sharedMemoryEnabled(false),
|
||||
forceTiering(false),
|
||||
gcEnabled(false),
|
||||
hugeMemory(false) {}
|
||||
hugeMemory(false),
|
||||
bigIntEnabled(false) {}
|
||||
};
|
||||
|
||||
// Return the estimated compiled (machine) code size for the given bytecode size
|
||||
|
|
|
@ -1086,6 +1086,7 @@ SharedMetadata ModuleGenerator::finishMetadata(const Bytes& bytecode) {
|
|||
metadata_->moduleName = env_->moduleName;
|
||||
metadata_->funcNames = std::move(env_->funcNames);
|
||||
metadata_->omitsBoundsChecks = env_->hugeMemoryEnabled();
|
||||
metadata_->bigIntEnabled = env_->bigIntEnabled();
|
||||
|
||||
// Copy over additional debug information.
|
||||
|
||||
|
|
|
@ -103,6 +103,19 @@ bool wasm::HasMultiValueSupport(JSContext* cx) {
|
|||
#endif
|
||||
}
|
||||
|
||||
bool wasm::HasI64BigIntSupport(JSContext* cx) {
|
||||
#ifdef ENABLE_WASM_CRANELIFT
|
||||
if (cx->options().wasmCranelift()) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#ifdef ENABLE_WASM_BIGINT
|
||||
return cx->options().isWasmBigIntEnabled();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool wasm::HasCompilerSupport(JSContext* cx) {
|
||||
#if !MOZ_LITTLE_ENDIAN || defined(JS_CODEGEN_NONE)
|
||||
return false;
|
||||
|
|
|
@ -73,6 +73,11 @@ bool HasGcSupport(JSContext* cx);
|
|||
|
||||
bool HasMultiValueSupport(JSContext* cx);
|
||||
|
||||
// Returns true if WebAssembly as configured by compile-time flags and run-time
|
||||
// options can support I64 to BigInt conversion.
|
||||
|
||||
bool HasI64BigIntSupport(JSContext* cx);
|
||||
|
||||
// Compiles the given binary wasm module given the ArrayBufferObject
|
||||
// and links the module's imports with the given import object.
|
||||
|
||||
|
|
|
@ -838,7 +838,7 @@ static void GenerateJitEntryThrow(MacroAssembler& masm, unsigned frameSize) {
|
|||
|
||||
static bool GenerateJitEntry(MacroAssembler& masm, size_t funcExportIndex,
|
||||
const FuncExport& fe, const Maybe<ImmPtr>& funcPtr,
|
||||
Offsets* offsets) {
|
||||
bool bigIntEnabled, Offsets* offsets) {
|
||||
AssertExpectedSP(masm);
|
||||
|
||||
RegisterOrSP sp = masm.getStackPointer();
|
||||
|
@ -870,7 +870,7 @@ static bool GenerateJitEntry(MacroAssembler& masm, size_t funcExportIndex,
|
|||
|
||||
GenerateJitEntryLoadTls(masm, frameSize);
|
||||
|
||||
if (fe.funcType().hasI64ArgOrRet()) {
|
||||
if (fe.funcType().hasI64ArgOrRet() && !bigIntEnabled) {
|
||||
CallSymbolicAddress(masm, !fe.hasEagerStubs(),
|
||||
SymbolicAddress::ReportInt64JSCall);
|
||||
GenerateJitEntryThrow(masm, frameSize);
|
||||
|
@ -2461,7 +2461,8 @@ static bool GenerateDebugTrapStub(MacroAssembler& masm, Label* throwLabel,
|
|||
|
||||
bool wasm::GenerateEntryStubs(MacroAssembler& masm, size_t funcExportIndex,
|
||||
const FuncExport& fe, const Maybe<ImmPtr>& callee,
|
||||
bool isAsmJS, CodeRangeVector* codeRanges) {
|
||||
bool isAsmJS, bool bigIntEnabled,
|
||||
CodeRangeVector* codeRanges) {
|
||||
MOZ_ASSERT(!callee == fe.hasEagerStubs());
|
||||
MOZ_ASSERT_IF(isAsmJS, fe.hasEagerStubs());
|
||||
|
||||
|
@ -2478,7 +2479,8 @@ bool wasm::GenerateEntryStubs(MacroAssembler& masm, size_t funcExportIndex,
|
|||
return true;
|
||||
}
|
||||
|
||||
if (!GenerateJitEntry(masm, funcExportIndex, fe, callee, &offsets)) {
|
||||
if (!GenerateJitEntry(masm, funcExportIndex, fe, callee, bigIntEnabled,
|
||||
&offsets)) {
|
||||
return false;
|
||||
}
|
||||
if (!codeRanges->emplaceBack(CodeRange::JitEntry, fe.funcIndex(), offsets)) {
|
||||
|
@ -2539,7 +2541,7 @@ bool wasm::GenerateStubs(const ModuleEnvironment& env,
|
|||
continue;
|
||||
}
|
||||
if (!GenerateEntryStubs(masm, i, fe, noAbsolute, env.isAsmJS(),
|
||||
&code->codeRanges)) {
|
||||
env.bigIntEnabled(), &code->codeRanges)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -259,7 +259,7 @@ extern bool GenerateEntryStubs(jit::MacroAssembler& masm,
|
|||
size_t funcExportIndex,
|
||||
const FuncExport& funcExport,
|
||||
const Maybe<jit::ImmPtr>& callee, bool isAsmJS,
|
||||
CodeRangeVector* codeRanges);
|
||||
bool bigIntEnabled, CodeRangeVector* codeRanges);
|
||||
|
||||
extern void GenerateTrapExitMachineState(jit::MachineState* machine,
|
||||
size_t* numWords);
|
||||
|
|
|
@ -2966,10 +2966,12 @@ bool wasm::Validate(JSContext* cx, const ShareableBytes& bytecode,
|
|||
bool gcTypesConfigured = HasGcSupport(cx);
|
||||
bool refTypesConfigured = HasReftypesSupport(cx);
|
||||
bool hugeMemory = false;
|
||||
bool bigIntConfigured = HasI64BigIntSupport(cx);
|
||||
|
||||
CompilerEnvironment compilerEnv(
|
||||
CompileMode::Once, Tier::Optimized, OptimizedBackend::Ion,
|
||||
DebugEnabled::False, refTypesConfigured, gcTypesConfigured, hugeMemory);
|
||||
CompilerEnvironment compilerEnv(CompileMode::Once, Tier::Optimized,
|
||||
OptimizedBackend::Ion, DebugEnabled::False,
|
||||
refTypesConfigured, gcTypesConfigured,
|
||||
hugeMemory, bigIntConfigured);
|
||||
ModuleEnvironment env(
|
||||
&compilerEnv,
|
||||
cx->realm()->creationOptions().getSharedMemoryAndAtomicsEnabled()
|
||||
|
|
|
@ -73,6 +73,7 @@ struct CompilerEnvironment {
|
|||
bool gcTypes_;
|
||||
bool multiValues_;
|
||||
bool hugeMemory_;
|
||||
bool bigInt_;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -87,7 +88,8 @@ struct CompilerEnvironment {
|
|||
CompilerEnvironment(CompileMode mode, Tier tier,
|
||||
OptimizedBackend optimizedBackend,
|
||||
DebugEnabled debugEnabled, bool refTypesConfigured,
|
||||
bool gcTypesConfigured, bool hugeMemory);
|
||||
bool gcTypesConfigured, bool hugeMemory,
|
||||
bool bigIntConfigured);
|
||||
|
||||
// Compute any remaining compilation parameters.
|
||||
void computeParameters(Decoder& d, bool gcFeatureOptIn);
|
||||
|
@ -130,6 +132,10 @@ struct CompilerEnvironment {
|
|||
MOZ_ASSERT(isComputed());
|
||||
return hugeMemory_;
|
||||
}
|
||||
bool bigInt() const {
|
||||
MOZ_ASSERT(isComputed());
|
||||
return bigInt_;
|
||||
}
|
||||
};
|
||||
|
||||
// ModuleEnvironment contains all the state necessary to process or render
|
||||
|
@ -215,6 +221,7 @@ struct ModuleEnvironment {
|
|||
bool gcTypesEnabled() const { return compilerEnv->gcTypes(); }
|
||||
bool refTypesEnabled() const { return compilerEnv->refTypes(); }
|
||||
bool multiValuesEnabled() const { return compilerEnv->multiValues(); }
|
||||
bool bigIntEnabled() const { return compilerEnv->bigInt(); }
|
||||
bool usesMemory() const { return memoryUsage != MemoryUsage::None; }
|
||||
bool usesSharedMemory() const { return memoryUsage == MemoryUsage::Shared; }
|
||||
bool isAsmJS() const { return kind == ModuleKind::AsmJS; }
|
||||
|
|
Загрузка…
Ссылка в новой задаче