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:
Lars T Hansen 2018-09-03 20:02:38 +02:00
Родитель ee0d09389e
Коммит 680fd3178c
8 изменённых файлов: 191 добавлений и 67 удалений

Просмотреть файл

@ -1470,6 +1470,7 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidator
ArrayViewVector arrayViews_; ArrayViewVector arrayViews_;
// State used to build the AsmJSModule in finish(): // State used to build the AsmJSModule in finish():
CompilerEnvironment compilerEnv_;
ModuleEnvironment env_; ModuleEnvironment env_;
MutableAsmJSMetadata asmJSMetadata_; MutableAsmJSMetadata asmJSMetadata_;
@ -1530,12 +1531,13 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidator
sigSet_(cx), sigSet_(cx),
funcImportMap_(cx), funcImportMap_(cx),
arrayViews_(cx), arrayViews_(cx),
env_(CompileMode::Once, Tier::Ion, DebugEnabled::False, HasGcTypes::False, compilerEnv_(CompileMode::Once, Tier::Ion, DebugEnabled::False, HasGcTypes::False),
Shareable::False, ModuleKind::AsmJS), env_(HasGcTypes::False, &compilerEnv_, Shareable::False, ModuleKind::AsmJS),
errorString_(nullptr), errorString_(nullptr),
errorOffset_(UINT32_MAX), errorOffset_(UINT32_MAX),
errorOverRecursed_(false) errorOverRecursed_(false)
{ {
compilerEnv_.computeParameters(HasGcTypes::False);
env_.minMemoryLength = RoundUpToNextValidAsmJSHeapLength(0); env_.minMemoryLength = RoundUpToNextValidAsmJSHeapLength(0);
} }

Просмотреть файл

@ -3382,7 +3382,7 @@ class BaseCompiler final : public BaseCompilerInterface
GenerateFunctionPrologue(masm, GenerateFunctionPrologue(masm,
env_.funcTypes[func_.index]->id, env_.funcTypes[func_.index]->id,
env_.mode == CompileMode::Tier1 ? Some(func_.index) : Nothing(), env_.mode() == CompileMode::Tier1 ? Some(func_.index) : Nothing(),
&offsets_); &offsets_);
// Initialize DebugFrame fields before the stack overflow trap so that // 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, const FuncCompileInputVector& inputs, CompiledCode* code,
UniqueChars* error) UniqueChars* error)
{ {
MOZ_ASSERT(env.tier == Tier::Baseline); MOZ_ASSERT(env.tier() == Tier::Baseline);
MOZ_ASSERT(env.kind == ModuleKind::Wasm); MOZ_ASSERT(env.kind == ModuleKind::Wasm);
// The MacroAssembler will sometimes access the jitContext. // The MacroAssembler will sometimes access the jitContext.

Просмотреть файл

@ -81,11 +81,11 @@ CompileArgs::CompileArgs(JSContext* cx, ScriptedCaller&& scriptedCaller)
bool gcEnabled = false; bool gcEnabled = false;
#endif #endif
baselineEnabled = cx->options().wasmBaseline() || gcEnabled; baselineEnabled = cx->options().wasmBaseline();
ionEnabled = cx->options().wasmIon() && !gcEnabled; ionEnabled = cx->options().wasmIon();
sharedMemoryEnabled = cx->realm()->creationOptions().getSharedMemoryAndAtomicsEnabled(); sharedMemoryEnabled = cx->realm()->creationOptions().getSharedMemoryAndAtomicsEnabled();
gcTypesConfigured = gcEnabled ? HasGcTypes::True : HasGcTypes::False; 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 // Debug information such as source view or debug traps will require
// additional memory and permanently stay in baseline code, so we try to // additional memory and permanently stay in baseline code, so we try to
@ -373,10 +373,51 @@ TieringBeneficial(uint32_t codeSize)
return true; return true;
} }
static void CompilerEnvironment::CompilerEnvironment(const CompileArgs& args)
InitialCompileFlags(const CompileArgs& args, Decoder& d, CompileMode* mode, Tier* tier, : state_(InitialWithArgs),
DebugEnabled* debug) 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; uint32_t codeSectionSize = 0;
SectionRange range; SectionRange range;
@ -384,24 +425,25 @@ InitialCompileFlags(const CompileArgs& args, Decoder& d, CompileMode* mode, Tier
codeSectionSize = range.size; codeSectionSize = range.size;
// Attempt to default to ion if baseline is disabled. // Attempt to default to ion if baseline is disabled.
bool baselineEnabled = BaselineCanCompile() && (args.baselineEnabled || args.testTiering); bool baselineEnabled = BaselineCanCompile() && (argBaselineEnabled || argTestTiering);
bool debugEnabled = BaselineCanCompile() && args.debugEnabled; bool debugEnabled = BaselineCanCompile() && argDebugEnabled;
bool ionEnabled = IonCanCompile() && (args.ionEnabled || !baselineEnabled || args.testTiering); bool ionEnabled = IonCanCompile() && (argIonEnabled || !baselineEnabled || argTestTiering);
// HasCompilerSupport() should prevent failure here // HasCompilerSupport() should prevent failure here
MOZ_RELEASE_ASSERT(baselineEnabled || ionEnabled); MOZ_RELEASE_ASSERT(baselineEnabled || ionEnabled);
if (baselineEnabled && ionEnabled && !debugEnabled && CanUseExtraThreads() && if (baselineEnabled && ionEnabled && !debugEnabled && CanUseExtraThreads() &&
(TieringBeneficial(codeSectionSize) || args.testTiering)) (TieringBeneficial(codeSectionSize) || argTestTiering))
{ {
*mode = CompileMode::Tier1; mode_ = CompileMode::Tier1;
*tier = Tier::Baseline; tier_ = Tier::Baseline;
} else { } else {
*mode = CompileMode::Once; mode_ = CompileMode::Once;
*tier = debugEnabled || !ionEnabled ? Tier::Baseline : Tier::Ion; 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> template <class DecoderT>
@ -462,12 +504,9 @@ wasm::CompileBuffer(const CompileArgs& args, const ShareableBytes& bytecode, Uni
Decoder d(bytecode.bytes, 0, error, warnings); Decoder d(bytecode.bytes, 0, error, warnings);
CompileMode mode; CompilerEnvironment compilerEnv(args);
Tier tier; ModuleEnvironment env(args.gcTypesConfigured,
DebugEnabled debug; &compilerEnv,
InitialCompileFlags(args, d, &mode, &tier, &debug);
ModuleEnvironment env(mode, tier, debug, args.gcTypesConfigured,
args.sharedMemoryEnabled ? Shareable::True : Shareable::False); args.sharedMemoryEnabled ? Shareable::True : Shareable::False);
if (!DecodeModuleEnvironment(d, &env)) if (!DecodeModuleEnvironment(d, &env))
return nullptr; return nullptr;
@ -493,13 +532,17 @@ wasm::CompileTier2(const CompileArgs& args, Module& module, Atomic<bool>* cancel
UniqueChars error; UniqueChars error;
Decoder d(module.bytecode().bytes, 0, &error); Decoder d(module.bytecode().bytes, 0, &error);
MOZ_ASSERT(args.gcTypesConfigured == HasGcTypes::False, "can't ion-compile with gc types yet"); HasGcTypes gcTypesConfigured = HasGcTypes::False; // No Ion support yet
CompilerEnvironment compilerEnv(CompileMode::Tier2, Tier::Ion, DebugEnabled::False,
ModuleEnvironment env(CompileMode::Tier2, Tier::Ion, DebugEnabled::False, HasGcTypes::False, gcTypesConfigured);
ModuleEnvironment env(gcTypesConfigured,
&compilerEnv,
args.sharedMemoryEnabled ? Shareable::True : Shareable::False); args.sharedMemoryEnabled ? Shareable::True : Shareable::False);
if (!DecodeModuleEnvironment(d, &env)) if (!DecodeModuleEnvironment(d, &env))
return; return;
MOZ_ASSERT(env.gcTypesEnabled() == HasGcTypes::False, "can't ion-compile with gc types yet");
ModuleGenerator mg(args, &env, cancelled, &error); ModuleGenerator mg(args, &env, cancelled, &error);
if (!mg.init()) if (!mg.init())
return; return;
@ -617,12 +660,9 @@ wasm::CompileStreaming(const CompileArgs& args,
{ {
Decoder d(envBytes, 0, error, warnings); Decoder d(envBytes, 0, error, warnings);
CompileMode mode; CompilerEnvironment compilerEnv(args);
Tier tier; env.emplace(args.gcTypesConfigured,
DebugEnabled debug; &compilerEnv,
InitialCompileFlags(args, d, &mode, &tier, &debug);
env.emplace(mode, tier, debug, args.gcTypesConfigured,
args.sharedMemoryEnabled ? Shareable::True : Shareable::False); args.sharedMemoryEnabled ? Shareable::True : Shareable::False);
if (!DecodeModuleEnvironment(d, env.ptr())) if (!DecodeModuleEnvironment(d, env.ptr()))
return nullptr; return nullptr;

Просмотреть файл

@ -607,7 +607,7 @@ ExecuteCompileTask(CompileTask* task, UniqueChars* error)
MOZ_ASSERT(task->lifo.isEmpty()); MOZ_ASSERT(task->lifo.isEmpty());
MOZ_ASSERT(task->output.empty()); MOZ_ASSERT(task->output.empty());
switch (task->env.tier) { switch (task->env.tier()) {
case Tier::Ion: case Tier::Ion:
if (!IonCompileFunctions(task->env, task->lifo, task->inputs, &task->output, error)) if (!IonCompileFunctions(task->env, task->lifo, task->inputs, &task->output, error))
return false; return false;

Просмотреть файл

@ -198,8 +198,8 @@ class MOZ_STACK_CLASS ModuleGenerator
UniqueModuleSegment finish(const ShareableBytes& bytecode); UniqueModuleSegment finish(const ShareableBytes& bytecode);
bool isAsmJS() const { return env_->isAsmJS(); } bool isAsmJS() const { return env_->isAsmJS(); }
Tier tier() const { return env_->tier; } Tier tier() const { return env_->tier(); }
CompileMode mode() const { return env_->mode; } CompileMode mode() const { return env_->mode(); }
bool debugEnabled() const { return env_->debugEnabled(); } bool debugEnabled() const { return env_->debugEnabled(); }
public: public:

Просмотреть файл

@ -3483,7 +3483,7 @@ wasm::IonCompileFunctions(const ModuleEnvironment& env, LifoAlloc& lifo,
const FuncCompileInputVector& inputs, CompiledCode* code, const FuncCompileInputVector& inputs, CompiledCode* code,
UniqueChars* error) UniqueChars* error)
{ {
MOZ_ASSERT(env.tier == Tier::Ion); MOZ_ASSERT(env.tier() == Tier::Ion);
TempAllocator alloc(&lifo); TempAllocator alloc(&lifo);
JitContext jitContext(&alloc); JitContext jitContext(&alloc);

Просмотреть файл

@ -2072,8 +2072,13 @@ wasm::DecodeModuleEnvironment(Decoder& d, ModuleEnvironment* env)
#ifdef ENABLE_WASM_GC #ifdef ENABLE_WASM_GC
if (!DecodeGCFeatureOptInSection(d, env)) if (!DecodeGCFeatureOptInSection(d, env))
return false; return false;
HasGcTypes gcFeatureOptIn = env->gcFeatureOptIn;
#else
HasGcTypes gcFeatureOptIn = HasGcTypes::False;
#endif #endif
env->compilerEnv->computeParameters(d, gcFeatureOptIn);
if (!DecodeTypeSection(d, env)) if (!DecodeTypeSection(d, env))
return false; return false;
@ -2342,12 +2347,15 @@ wasm::Validate(JSContext* cx, const ShareableBytes& bytecode, UniqueChars* error
Decoder d(bytecode.bytes, 0, error); Decoder d(bytecode.bytes, 0, error);
#ifdef ENABLE_WASM_GC #ifdef ENABLE_WASM_GC
HasGcTypes gcSupport = cx->options().wasmGc() ? HasGcTypes::True : HasGcTypes::False; HasGcTypes gcTypesConfigured = cx->options().wasmGc() ? HasGcTypes::True : HasGcTypes::False;
#else #else
HasGcTypes gcSupport = HasGcTypes::False; HasGcTypes gcTypesConfigured = HasGcTypes::False;
#endif #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() cx->realm()->creationOptions().getSharedMemoryAndAtomicsEnabled()
? Shareable::True ? Shareable::True
: Shareable::False); : Shareable::False);

Просмотреть файл

@ -45,6 +45,83 @@ struct SectionRange
typedef Maybe<SectionRange> MaybeSectionRange; 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 // ModuleEnvironment contains all the state necessary to validate, process or
// render functions. It is created by decoding all the sections before the wasm // 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 // code section and then used immutably during. When compiling a module using a
@ -56,21 +133,17 @@ typedef Maybe<SectionRange> MaybeSectionRange;
struct ModuleEnvironment struct ModuleEnvironment
{ {
// Constant parameters for the entire compilation: // Constant parameters for the entire compilation:
const DebugEnabled debug; const ModuleKind kind;
const ModuleKind kind; const Shareable sharedMemoryEnabled;
const CompileMode mode;
const Shareable sharedMemoryEnabled;
// `gcTypesConfigured` reflects the value of the flags --wasm-gc and // `gcTypesConfigured` reflects the value of the flags --wasm-gc and
// javascript.options.wasm_gc. These flags will disappear eventually, thus // javascript.options.wasm_gc. These flags will disappear eventually, thus
// allowing the removal of this variable and its replacement everywhere by // allowing the removal of this variable and its replacement everywhere by
// the value HasGcTypes::True. // the value HasGcTypes::True.
// //
// For now, the value is used (a) in the value of gcTypesEnabled(), which // For now, the value is used to control whether we emit code to suppress GC
// controls whether ref types and struct types and associated instructions // while wasm activations are on the stack.
// are accepted during validation, and (b) to control whether we emit code const HasGcTypes gcTypesConfigured;
// to suppress GC while wasm activations are on the stack. CompilerEnvironment* const compilerEnv;
const HasGcTypes gcTypesConfigured;
const Tier tier;
// 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:
@ -105,18 +178,14 @@ struct ModuleEnvironment
NameInBytecodeVector funcNames; NameInBytecodeVector funcNames;
CustomSectionVector customSections; CustomSectionVector customSections;
explicit ModuleEnvironment(CompileMode mode, explicit ModuleEnvironment(HasGcTypes gcTypesConfigured,
Tier tier, CompilerEnvironment* compilerEnv,
DebugEnabled debug,
HasGcTypes hasGcTypes,
Shareable sharedMemoryEnabled, Shareable sharedMemoryEnabled,
ModuleKind kind = ModuleKind::Wasm) ModuleKind kind = ModuleKind::Wasm)
: debug(debug), : kind(kind),
kind(kind),
mode(mode),
sharedMemoryEnabled(sharedMemoryEnabled), sharedMemoryEnabled(sharedMemoryEnabled),
gcTypesConfigured(hasGcTypes), gcTypesConfigured(gcTypesConfigured),
tier(tier), compilerEnv(compilerEnv),
#ifdef ENABLE_WASM_GC #ifdef ENABLE_WASM_GC
gcFeatureOptIn(HasGcTypes::False), gcFeatureOptIn(HasGcTypes::False),
#endif #endif
@ -124,6 +193,15 @@ struct ModuleEnvironment
minMemoryLength(0) minMemoryLength(0)
{} {}
Tier tier() const {
return compilerEnv->tier();
}
CompileMode mode() const {
return compilerEnv->mode();
}
DebugEnabled debug() const {
return compilerEnv->debug();
}
size_t numTables() const { size_t numTables() const {
return tables.length(); return tables.length();
} }
@ -140,11 +218,7 @@ struct ModuleEnvironment
return funcTypes.length() - funcImportGlobalDataOffsets.length(); return funcTypes.length() - funcImportGlobalDataOffsets.length();
} }
HasGcTypes gcTypesEnabled() const { HasGcTypes gcTypesEnabled() const {
#ifdef ENABLE_WASM_GC return compilerEnv->gcTypes();
if (gcTypesConfigured == HasGcTypes::True)
return gcFeatureOptIn;
#endif
return HasGcTypes::False;
} }
bool usesMemory() const { bool usesMemory() const {
return memoryUsage != MemoryUsage::None; return memoryUsage != MemoryUsage::None;
@ -156,7 +230,7 @@ struct ModuleEnvironment
return kind == ModuleKind::AsmJS; return kind == ModuleKind::AsmJS;
} }
bool debugEnabled() const { bool debugEnabled() const {
return debug == DebugEnabled::True; return compilerEnv->debug() == DebugEnabled::True;
} }
bool funcIsImport(uint32_t funcIndex) const { bool funcIsImport(uint32_t funcIndex) const {
return funcIndex < funcImportGlobalDataOffsets.length(); return funcIndex < funcImportGlobalDataOffsets.length();