зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1487329 - Select wasm baseline compiler if content opts into gc types. r=bbouvier
Creates a level of indirection to encapsulate the compilation parameters (mode, tier, debug, gc-enabled) so as to allow their computation to be delayed. This centers on the new struct CompilerEnvironment, defined in WasmValidate.h. After this change, compiler selection is driven by the presence of the gc-feature-opt-in section. We finalize the values in CompilerEnvironment after having parsed that section. (That parsing is still under #ifdef.) --wasm-gc is still used as a higher-level control; if it is not present there will be no gc support at all. But once we remove that flag, very little will change here; all code that reads that flag can instead pass HasGcTypes::True, and compiler selection will be entirely driven by the presence of the opt-in section. There are a few too many uses of HasGcTypes::False here; most of these will disappear along with the --wasm-gc flag. --HG-- extra : rebase_source : d2c2bd01309124caaa66f13564be2bcf24f34946
This commit is contained in:
Родитель
ee0d09389e
Коммит
680fd3178c
|
@ -1470,6 +1470,7 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidator
|
|||
ArrayViewVector arrayViews_;
|
||||
|
||||
// State used to build the AsmJSModule in finish():
|
||||
CompilerEnvironment compilerEnv_;
|
||||
ModuleEnvironment env_;
|
||||
MutableAsmJSMetadata asmJSMetadata_;
|
||||
|
||||
|
@ -1530,12 +1531,13 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidator
|
|||
sigSet_(cx),
|
||||
funcImportMap_(cx),
|
||||
arrayViews_(cx),
|
||||
env_(CompileMode::Once, Tier::Ion, DebugEnabled::False, HasGcTypes::False,
|
||||
Shareable::False, ModuleKind::AsmJS),
|
||||
compilerEnv_(CompileMode::Once, Tier::Ion, DebugEnabled::False, HasGcTypes::False),
|
||||
env_(HasGcTypes::False, &compilerEnv_, Shareable::False, ModuleKind::AsmJS),
|
||||
errorString_(nullptr),
|
||||
errorOffset_(UINT32_MAX),
|
||||
errorOverRecursed_(false)
|
||||
{
|
||||
compilerEnv_.computeParameters(HasGcTypes::False);
|
||||
env_.minMemoryLength = RoundUpToNextValidAsmJSHeapLength(0);
|
||||
}
|
||||
|
||||
|
|
|
@ -3382,7 +3382,7 @@ class BaseCompiler final : public BaseCompilerInterface
|
|||
|
||||
GenerateFunctionPrologue(masm,
|
||||
env_.funcTypes[func_.index]->id,
|
||||
env_.mode == CompileMode::Tier1 ? Some(func_.index) : Nothing(),
|
||||
env_.mode() == CompileMode::Tier1 ? Some(func_.index) : Nothing(),
|
||||
&offsets_);
|
||||
|
||||
// Initialize DebugFrame fields before the stack overflow trap so that
|
||||
|
@ -10352,7 +10352,7 @@ js::wasm::BaselineCompileFunctions(const ModuleEnvironment& env, LifoAlloc& lifo
|
|||
const FuncCompileInputVector& inputs, CompiledCode* code,
|
||||
UniqueChars* error)
|
||||
{
|
||||
MOZ_ASSERT(env.tier == Tier::Baseline);
|
||||
MOZ_ASSERT(env.tier() == Tier::Baseline);
|
||||
MOZ_ASSERT(env.kind == ModuleKind::Wasm);
|
||||
|
||||
// The MacroAssembler will sometimes access the jitContext.
|
||||
|
|
|
@ -81,11 +81,11 @@ CompileArgs::CompileArgs(JSContext* cx, ScriptedCaller&& scriptedCaller)
|
|||
bool gcEnabled = false;
|
||||
#endif
|
||||
|
||||
baselineEnabled = cx->options().wasmBaseline() || gcEnabled;
|
||||
ionEnabled = cx->options().wasmIon() && !gcEnabled;
|
||||
baselineEnabled = cx->options().wasmBaseline();
|
||||
ionEnabled = cx->options().wasmIon();
|
||||
sharedMemoryEnabled = cx->realm()->creationOptions().getSharedMemoryAndAtomicsEnabled();
|
||||
gcTypesConfigured = gcEnabled ? HasGcTypes::True : HasGcTypes::False;
|
||||
testTiering = (cx->options().testWasmAwaitTier2() || JitOptions.wasmDelayTier2) && !gcEnabled;
|
||||
testTiering = cx->options().testWasmAwaitTier2() || JitOptions.wasmDelayTier2;
|
||||
|
||||
// Debug information such as source view or debug traps will require
|
||||
// additional memory and permanently stay in baseline code, so we try to
|
||||
|
@ -373,10 +373,51 @@ TieringBeneficial(uint32_t codeSize)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
InitialCompileFlags(const CompileArgs& args, Decoder& d, CompileMode* mode, Tier* tier,
|
||||
DebugEnabled* debug)
|
||||
CompilerEnvironment::CompilerEnvironment(const CompileArgs& args)
|
||||
: state_(InitialWithArgs),
|
||||
args_(&args)
|
||||
{
|
||||
}
|
||||
|
||||
CompilerEnvironment::CompilerEnvironment(CompileMode mode,
|
||||
Tier tier,
|
||||
DebugEnabled debugEnabled,
|
||||
HasGcTypes gcTypesConfigured)
|
||||
: state_(InitialWithModeTierDebug),
|
||||
mode_(mode),
|
||||
tier_(tier),
|
||||
debug_(debugEnabled),
|
||||
gcTypes_(gcTypesConfigured)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
CompilerEnvironment::computeParameters(HasGcTypes gcFeatureOptIn)
|
||||
{
|
||||
MOZ_ASSERT(state_ == InitialWithModeTierDebug);
|
||||
|
||||
if (gcTypes_ == HasGcTypes::True)
|
||||
gcTypes_ = gcFeatureOptIn;
|
||||
state_ = Computed;
|
||||
}
|
||||
|
||||
void
|
||||
CompilerEnvironment::computeParameters(Decoder& d, HasGcTypes gcFeatureOptIn)
|
||||
{
|
||||
MOZ_ASSERT(!isComputed());
|
||||
|
||||
if (state_ == InitialWithModeTierDebug) {
|
||||
computeParameters(gcFeatureOptIn);
|
||||
return;
|
||||
}
|
||||
|
||||
bool gcEnabled = args_->gcTypesConfigured == HasGcTypes::True &&
|
||||
gcFeatureOptIn == HasGcTypes::True;
|
||||
bool argBaselineEnabled = args_->baselineEnabled || gcEnabled;
|
||||
bool argIonEnabled = args_->ionEnabled && !gcEnabled;
|
||||
bool argTestTiering = args_->testTiering && !gcEnabled;
|
||||
bool argDebugEnabled = args_->debugEnabled;
|
||||
|
||||
uint32_t codeSectionSize = 0;
|
||||
|
||||
SectionRange range;
|
||||
|
@ -384,24 +425,25 @@ InitialCompileFlags(const CompileArgs& args, Decoder& d, CompileMode* mode, Tier
|
|||
codeSectionSize = range.size;
|
||||
|
||||
// Attempt to default to ion if baseline is disabled.
|
||||
bool baselineEnabled = BaselineCanCompile() && (args.baselineEnabled || args.testTiering);
|
||||
bool debugEnabled = BaselineCanCompile() && args.debugEnabled;
|
||||
bool ionEnabled = IonCanCompile() && (args.ionEnabled || !baselineEnabled || args.testTiering);
|
||||
bool baselineEnabled = BaselineCanCompile() && (argBaselineEnabled || argTestTiering);
|
||||
bool debugEnabled = BaselineCanCompile() && argDebugEnabled;
|
||||
bool ionEnabled = IonCanCompile() && (argIonEnabled || !baselineEnabled || argTestTiering);
|
||||
|
||||
// HasCompilerSupport() should prevent failure here
|
||||
MOZ_RELEASE_ASSERT(baselineEnabled || ionEnabled);
|
||||
|
||||
if (baselineEnabled && ionEnabled && !debugEnabled && CanUseExtraThreads() &&
|
||||
(TieringBeneficial(codeSectionSize) || args.testTiering))
|
||||
(TieringBeneficial(codeSectionSize) || argTestTiering))
|
||||
{
|
||||
*mode = CompileMode::Tier1;
|
||||
*tier = Tier::Baseline;
|
||||
mode_ = CompileMode::Tier1;
|
||||
tier_ = Tier::Baseline;
|
||||
} else {
|
||||
*mode = CompileMode::Once;
|
||||
*tier = debugEnabled || !ionEnabled ? Tier::Baseline : Tier::Ion;
|
||||
mode_ = CompileMode::Once;
|
||||
tier_ = debugEnabled || !ionEnabled ? Tier::Baseline : Tier::Ion;
|
||||
}
|
||||
|
||||
*debug = debugEnabled ? DebugEnabled::True : DebugEnabled::False;
|
||||
debug_ = debugEnabled ? DebugEnabled::True : DebugEnabled::False;
|
||||
gcTypes_ = gcEnabled ? HasGcTypes::True : HasGcTypes::False;
|
||||
state_ = Computed;
|
||||
}
|
||||
|
||||
template <class DecoderT>
|
||||
|
@ -462,12 +504,9 @@ wasm::CompileBuffer(const CompileArgs& args, const ShareableBytes& bytecode, Uni
|
|||
|
||||
Decoder d(bytecode.bytes, 0, error, warnings);
|
||||
|
||||
CompileMode mode;
|
||||
Tier tier;
|
||||
DebugEnabled debug;
|
||||
InitialCompileFlags(args, d, &mode, &tier, &debug);
|
||||
|
||||
ModuleEnvironment env(mode, tier, debug, args.gcTypesConfigured,
|
||||
CompilerEnvironment compilerEnv(args);
|
||||
ModuleEnvironment env(args.gcTypesConfigured,
|
||||
&compilerEnv,
|
||||
args.sharedMemoryEnabled ? Shareable::True : Shareable::False);
|
||||
if (!DecodeModuleEnvironment(d, &env))
|
||||
return nullptr;
|
||||
|
@ -493,13 +532,17 @@ wasm::CompileTier2(const CompileArgs& args, Module& module, Atomic<bool>* cancel
|
|||
UniqueChars error;
|
||||
Decoder d(module.bytecode().bytes, 0, &error);
|
||||
|
||||
MOZ_ASSERT(args.gcTypesConfigured == HasGcTypes::False, "can't ion-compile with gc types yet");
|
||||
|
||||
ModuleEnvironment env(CompileMode::Tier2, Tier::Ion, DebugEnabled::False, HasGcTypes::False,
|
||||
HasGcTypes gcTypesConfigured = HasGcTypes::False; // No Ion support yet
|
||||
CompilerEnvironment compilerEnv(CompileMode::Tier2, Tier::Ion, DebugEnabled::False,
|
||||
gcTypesConfigured);
|
||||
ModuleEnvironment env(gcTypesConfigured,
|
||||
&compilerEnv,
|
||||
args.sharedMemoryEnabled ? Shareable::True : Shareable::False);
|
||||
if (!DecodeModuleEnvironment(d, &env))
|
||||
return;
|
||||
|
||||
MOZ_ASSERT(env.gcTypesEnabled() == HasGcTypes::False, "can't ion-compile with gc types yet");
|
||||
|
||||
ModuleGenerator mg(args, &env, cancelled, &error);
|
||||
if (!mg.init())
|
||||
return;
|
||||
|
@ -617,12 +660,9 @@ wasm::CompileStreaming(const CompileArgs& args,
|
|||
{
|
||||
Decoder d(envBytes, 0, error, warnings);
|
||||
|
||||
CompileMode mode;
|
||||
Tier tier;
|
||||
DebugEnabled debug;
|
||||
InitialCompileFlags(args, d, &mode, &tier, &debug);
|
||||
|
||||
env.emplace(mode, tier, debug, args.gcTypesConfigured,
|
||||
CompilerEnvironment compilerEnv(args);
|
||||
env.emplace(args.gcTypesConfigured,
|
||||
&compilerEnv,
|
||||
args.sharedMemoryEnabled ? Shareable::True : Shareable::False);
|
||||
if (!DecodeModuleEnvironment(d, env.ptr()))
|
||||
return nullptr;
|
||||
|
|
|
@ -607,7 +607,7 @@ ExecuteCompileTask(CompileTask* task, UniqueChars* error)
|
|||
MOZ_ASSERT(task->lifo.isEmpty());
|
||||
MOZ_ASSERT(task->output.empty());
|
||||
|
||||
switch (task->env.tier) {
|
||||
switch (task->env.tier()) {
|
||||
case Tier::Ion:
|
||||
if (!IonCompileFunctions(task->env, task->lifo, task->inputs, &task->output, error))
|
||||
return false;
|
||||
|
|
|
@ -198,8 +198,8 @@ class MOZ_STACK_CLASS ModuleGenerator
|
|||
UniqueModuleSegment finish(const ShareableBytes& bytecode);
|
||||
|
||||
bool isAsmJS() const { return env_->isAsmJS(); }
|
||||
Tier tier() const { return env_->tier; }
|
||||
CompileMode mode() const { return env_->mode; }
|
||||
Tier tier() const { return env_->tier(); }
|
||||
CompileMode mode() const { return env_->mode(); }
|
||||
bool debugEnabled() const { return env_->debugEnabled(); }
|
||||
|
||||
public:
|
||||
|
|
|
@ -3483,7 +3483,7 @@ wasm::IonCompileFunctions(const ModuleEnvironment& env, LifoAlloc& lifo,
|
|||
const FuncCompileInputVector& inputs, CompiledCode* code,
|
||||
UniqueChars* error)
|
||||
{
|
||||
MOZ_ASSERT(env.tier == Tier::Ion);
|
||||
MOZ_ASSERT(env.tier() == Tier::Ion);
|
||||
|
||||
TempAllocator alloc(&lifo);
|
||||
JitContext jitContext(&alloc);
|
||||
|
|
|
@ -2072,8 +2072,13 @@ wasm::DecodeModuleEnvironment(Decoder& d, ModuleEnvironment* env)
|
|||
#ifdef ENABLE_WASM_GC
|
||||
if (!DecodeGCFeatureOptInSection(d, env))
|
||||
return false;
|
||||
HasGcTypes gcFeatureOptIn = env->gcFeatureOptIn;
|
||||
#else
|
||||
HasGcTypes gcFeatureOptIn = HasGcTypes::False;
|
||||
#endif
|
||||
|
||||
env->compilerEnv->computeParameters(d, gcFeatureOptIn);
|
||||
|
||||
if (!DecodeTypeSection(d, env))
|
||||
return false;
|
||||
|
||||
|
@ -2342,12 +2347,15 @@ wasm::Validate(JSContext* cx, const ShareableBytes& bytecode, UniqueChars* error
|
|||
Decoder d(bytecode.bytes, 0, error);
|
||||
|
||||
#ifdef ENABLE_WASM_GC
|
||||
HasGcTypes gcSupport = cx->options().wasmGc() ? HasGcTypes::True : HasGcTypes::False;
|
||||
HasGcTypes gcTypesConfigured = cx->options().wasmGc() ? HasGcTypes::True : HasGcTypes::False;
|
||||
#else
|
||||
HasGcTypes gcSupport = HasGcTypes::False;
|
||||
HasGcTypes gcTypesConfigured = HasGcTypes::False;
|
||||
#endif
|
||||
|
||||
ModuleEnvironment env(CompileMode::Once, Tier::Ion, DebugEnabled::False, gcSupport,
|
||||
CompilerEnvironment compilerEnv(CompileMode::Once, Tier::Ion, DebugEnabled::False,
|
||||
gcTypesConfigured);
|
||||
ModuleEnvironment env(gcTypesConfigured,
|
||||
&compilerEnv,
|
||||
cx->realm()->creationOptions().getSharedMemoryAndAtomicsEnabled()
|
||||
? Shareable::True
|
||||
: Shareable::False);
|
||||
|
|
|
@ -45,6 +45,83 @@ struct SectionRange
|
|||
|
||||
typedef Maybe<SectionRange> MaybeSectionRange;
|
||||
|
||||
// CompilerEnvironment holds any values that will be needed to compute
|
||||
// compilation parameters once the module's feature opt-in sections have been
|
||||
// parsed.
|
||||
//
|
||||
// Subsequent to construction a computeParameters() call will compute the final
|
||||
// compilation parameters, and the object can then be queried for their values.
|
||||
|
||||
struct CompileArgs;
|
||||
class Decoder;
|
||||
|
||||
struct CompilerEnvironment
|
||||
{
|
||||
// The object starts in one of two "initial" states; computeParameters moves
|
||||
// it into the "computed" state.
|
||||
enum State
|
||||
{
|
||||
InitialWithArgs,
|
||||
InitialWithModeTierDebug,
|
||||
Computed
|
||||
};
|
||||
|
||||
State state_;
|
||||
union {
|
||||
// Value if the state_ == InitialWithArgs.
|
||||
const CompileArgs* args_;
|
||||
|
||||
// Value in the other two states.
|
||||
struct {
|
||||
CompileMode mode_;
|
||||
Tier tier_;
|
||||
DebugEnabled debug_;
|
||||
HasGcTypes gcTypes_;
|
||||
};
|
||||
};
|
||||
|
||||
public:
|
||||
// Retain a reference to the CompileArgs. A subsequent computeParameters()
|
||||
// will compute all parameters from the CompileArgs and additional values.
|
||||
CompilerEnvironment(const CompileArgs& args);
|
||||
|
||||
// Save the provided values for mode, tier, and debug, and the initial value
|
||||
// for gcTypes. A subsequent computeParameters() will compute the final
|
||||
// value of gcTypes.
|
||||
CompilerEnvironment(CompileMode mode,
|
||||
Tier tier,
|
||||
DebugEnabled debugEnabled,
|
||||
HasGcTypes gcTypesConfigured);
|
||||
|
||||
// Compute any remaining compilation parameters.
|
||||
void computeParameters(Decoder& d, HasGcTypes gcFeatureOptIn);
|
||||
|
||||
// Compute any remaining compilation parameters. Only use this method if
|
||||
// the CompilerEnvironment was created with values for mode, tier, and
|
||||
// debug.
|
||||
void computeParameters(HasGcTypes gcFeatureOptIn);
|
||||
|
||||
bool isComputed() const {
|
||||
return state_ == Computed;
|
||||
}
|
||||
CompileMode mode() const {
|
||||
MOZ_ASSERT(isComputed());
|
||||
return mode_;
|
||||
}
|
||||
Tier tier() const {
|
||||
MOZ_ASSERT(isComputed());
|
||||
return tier_;
|
||||
}
|
||||
DebugEnabled debug() const {
|
||||
MOZ_ASSERT(isComputed());
|
||||
return debug_;
|
||||
}
|
||||
HasGcTypes gcTypes() const {
|
||||
MOZ_ASSERT(isComputed());
|
||||
return gcTypes_;
|
||||
}
|
||||
};
|
||||
|
||||
// ModuleEnvironment contains all the state necessary to validate, process or
|
||||
// render functions. It is created by decoding all the sections before the wasm
|
||||
// code section and then used immutably during. When compiling a module using a
|
||||
|
@ -56,21 +133,17 @@ typedef Maybe<SectionRange> MaybeSectionRange;
|
|||
struct ModuleEnvironment
|
||||
{
|
||||
// Constant parameters for the entire compilation:
|
||||
const DebugEnabled debug;
|
||||
const ModuleKind kind;
|
||||
const CompileMode mode;
|
||||
const Shareable sharedMemoryEnabled;
|
||||
// `gcTypesConfigured` reflects the value of the flags --wasm-gc and
|
||||
// javascript.options.wasm_gc. These flags will disappear eventually, thus
|
||||
// allowing the removal of this variable and its replacement everywhere by
|
||||
// the value HasGcTypes::True.
|
||||
//
|
||||
// For now, the value is used (a) in the value of gcTypesEnabled(), which
|
||||
// controls whether ref types and struct types and associated instructions
|
||||
// are accepted during validation, and (b) to control whether we emit code
|
||||
// to suppress GC while wasm activations are on the stack.
|
||||
// For now, the value is used to control whether we emit code to suppress GC
|
||||
// while wasm activations are on the stack.
|
||||
const HasGcTypes gcTypesConfigured;
|
||||
const Tier tier;
|
||||
CompilerEnvironment* const compilerEnv;
|
||||
|
||||
// Module fields decoded from the module environment (or initialized while
|
||||
// validating an asm.js module) and immutable during compilation:
|
||||
|
@ -105,18 +178,14 @@ struct ModuleEnvironment
|
|||
NameInBytecodeVector funcNames;
|
||||
CustomSectionVector customSections;
|
||||
|
||||
explicit ModuleEnvironment(CompileMode mode,
|
||||
Tier tier,
|
||||
DebugEnabled debug,
|
||||
HasGcTypes hasGcTypes,
|
||||
explicit ModuleEnvironment(HasGcTypes gcTypesConfigured,
|
||||
CompilerEnvironment* compilerEnv,
|
||||
Shareable sharedMemoryEnabled,
|
||||
ModuleKind kind = ModuleKind::Wasm)
|
||||
: debug(debug),
|
||||
kind(kind),
|
||||
mode(mode),
|
||||
: kind(kind),
|
||||
sharedMemoryEnabled(sharedMemoryEnabled),
|
||||
gcTypesConfigured(hasGcTypes),
|
||||
tier(tier),
|
||||
gcTypesConfigured(gcTypesConfigured),
|
||||
compilerEnv(compilerEnv),
|
||||
#ifdef ENABLE_WASM_GC
|
||||
gcFeatureOptIn(HasGcTypes::False),
|
||||
#endif
|
||||
|
@ -124,6 +193,15 @@ struct ModuleEnvironment
|
|||
minMemoryLength(0)
|
||||
{}
|
||||
|
||||
Tier tier() const {
|
||||
return compilerEnv->tier();
|
||||
}
|
||||
CompileMode mode() const {
|
||||
return compilerEnv->mode();
|
||||
}
|
||||
DebugEnabled debug() const {
|
||||
return compilerEnv->debug();
|
||||
}
|
||||
size_t numTables() const {
|
||||
return tables.length();
|
||||
}
|
||||
|
@ -140,11 +218,7 @@ struct ModuleEnvironment
|
|||
return funcTypes.length() - funcImportGlobalDataOffsets.length();
|
||||
}
|
||||
HasGcTypes gcTypesEnabled() const {
|
||||
#ifdef ENABLE_WASM_GC
|
||||
if (gcTypesConfigured == HasGcTypes::True)
|
||||
return gcFeatureOptIn;
|
||||
#endif
|
||||
return HasGcTypes::False;
|
||||
return compilerEnv->gcTypes();
|
||||
}
|
||||
bool usesMemory() const {
|
||||
return memoryUsage != MemoryUsage::None;
|
||||
|
@ -156,7 +230,7 @@ struct ModuleEnvironment
|
|||
return kind == ModuleKind::AsmJS;
|
||||
}
|
||||
bool debugEnabled() const {
|
||||
return debug == DebugEnabled::True;
|
||||
return compilerEnv->debug() == DebugEnabled::True;
|
||||
}
|
||||
bool funcIsImport(uint32_t funcIndex) const {
|
||||
return funcIndex < funcImportGlobalDataOffsets.length();
|
||||
|
|
Загрузка…
Ссылка в новой задаче