зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1330891 - Baldr: simplify ModuleGenerator (r=bbouvier)
MozReview-Commit-ID: LrBIuXsUhtX
This commit is contained in:
Родитель
0a37fafed0
Коммит
7d79c6f41c
|
@ -1 +1 @@
|
|||
|jit-test| test-also-noasmjs; test-also-wasm-baseline
|
||||
|jit-test| test-also-noasmjs
|
||||
|
|
|
@ -238,14 +238,10 @@ DefaultJitOptions::DefaultJitOptions()
|
|||
SET_DEFAULT(wasmFoldOffsets, true);
|
||||
|
||||
// Until which wasm bytecode size should we accumulate functions, in order
|
||||
// to compile efficiently on helper threads (see also bug 1320374).
|
||||
SET_DEFAULT(wasmBatchThreshold, 10000);
|
||||
|
||||
// In order to have different batching thresholds for Ion and the wasm
|
||||
// baseline, and since a same batch can contain both Ion and baseline
|
||||
// compiled functions, we make Ion functions weight more by using a scaling
|
||||
// factor.
|
||||
SET_DEFAULT(wasmBatchIonScaleFactor, 9);
|
||||
// to compile efficiently on helper threads. Baseline code compiles much
|
||||
// faster than Ion code so use scaled thresholds (see also bug 1320374).
|
||||
SET_DEFAULT(wasmBatchBaselineThreshold, 10000);
|
||||
SET_DEFAULT(wasmBatchIonThreshold, 1100);
|
||||
|
||||
// Determines whether we suppress using signal handlers
|
||||
// for interrupting jit-ed code. This is used only for testing.
|
||||
|
|
|
@ -87,8 +87,8 @@ struct DefaultJitOptions
|
|||
uint32_t branchPruningBlockSpanFactor;
|
||||
uint32_t branchPruningEffectfulInstFactor;
|
||||
uint32_t branchPruningThreshold;
|
||||
uint32_t wasmBatchThreshold;
|
||||
uint32_t wasmBatchIonScaleFactor;
|
||||
uint32_t wasmBatchIonThreshold;
|
||||
uint32_t wasmBatchBaselineThreshold;
|
||||
mozilla::Maybe<uint32_t> forcedDefaultIonWarmUpThreshold;
|
||||
mozilla::Maybe<uint32_t> forcedDefaultIonSmallFunctionWarmUpThreshold;
|
||||
mozilla::Maybe<IonRegisterAllocator> forcedRegisterAllocator;
|
||||
|
|
|
@ -138,7 +138,7 @@ class JitTest:
|
|||
t.valgrind = self.valgrind
|
||||
t.tz_pacific = self.tz_pacific
|
||||
t.test_also_noasmjs = self.test_also_noasmjs
|
||||
t.test_also_wasm_baseline = self.test_also_noasmjs
|
||||
t.test_also_wasm_baseline = self.test_also_wasm_baseline
|
||||
t.test_also = self.test_also
|
||||
t.test_join = self.test_join
|
||||
t.expect_error = self.expect_error
|
||||
|
|
|
@ -7902,7 +7902,7 @@ LiveRegisterSet BaseCompiler::VolatileReturnGPR = volatileReturnGPR();
|
|||
} // js
|
||||
|
||||
bool
|
||||
js::wasm::BaselineCanCompile(const FunctionGenerator* fg)
|
||||
js::wasm::BaselineCanCompile()
|
||||
{
|
||||
// On all platforms we require signals for AsmJS/Wasm.
|
||||
// If we made it this far we must have signals.
|
||||
|
@ -7920,12 +7920,6 @@ js::wasm::BaselineCanCompile(const FunctionGenerator* fg)
|
|||
#endif
|
||||
|
||||
#if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM)
|
||||
// AsmJS code may use SIMD or atomics, which Baseline doesn't currently
|
||||
// handle. Since we haven't yet validated the function, we don't know
|
||||
// whether it actually uses those features. Assume the worst.
|
||||
if (fg->isAsmJS())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
|
@ -7935,7 +7929,7 @@ js::wasm::BaselineCanCompile(const FunctionGenerator* fg)
|
|||
bool
|
||||
js::wasm::BaselineCompileFunction(CompileTask* task, FuncCompileUnit* unit, UniqueChars *error)
|
||||
{
|
||||
MOZ_ASSERT(unit->mode() == CompileMode::Baseline);
|
||||
MOZ_ASSERT(task->mode() == CompileMode::Baseline);
|
||||
|
||||
const FuncBytes& func = unit->func();
|
||||
uint32_t bodySize = func.bytes().length();
|
||||
|
|
|
@ -24,21 +24,13 @@
|
|||
namespace js {
|
||||
namespace wasm {
|
||||
|
||||
class FunctionGenerator;
|
||||
class CompileTask;
|
||||
class FuncCompileUnit;
|
||||
|
||||
// Return true if BaselineCompileFunction can generate code for the
|
||||
// function held in the FunctionGenerator. If false is returned a
|
||||
// different compilation strategy must be chosen.
|
||||
//
|
||||
// This allows the baseline compiler to have different capabilities on
|
||||
// different platforms and defer to the full Ion compiler if
|
||||
// capabilities are missing. The FunctionGenerator and other data
|
||||
// structures contain information about the capabilities that are
|
||||
// required to compile the function.
|
||||
// Return whether BaselineCompileFunction can generate code on the current device.
|
||||
// Note: asm.js is also currently not supported due to Atomics and SIMD.
|
||||
bool
|
||||
BaselineCanCompile(const FunctionGenerator* fg);
|
||||
BaselineCanCompile();
|
||||
|
||||
// Generate adequate code quickly.
|
||||
bool
|
||||
|
|
|
@ -45,8 +45,7 @@ static const unsigned COMPILATION_LIFO_DEFAULT_CHUNK_SIZE = 64 * 1024;
|
|||
static const uint32_t BAD_CODE_RANGE = UINT32_MAX;
|
||||
|
||||
ModuleGenerator::ModuleGenerator(UniqueChars* error)
|
||||
: alwaysBaseline_(false),
|
||||
debugEnabled_(false),
|
||||
: compileMode_(CompileMode(-1)),
|
||||
error_(error),
|
||||
numSigs_(0),
|
||||
numTables_(0),
|
||||
|
@ -112,6 +111,12 @@ ModuleGenerator::initAsmJS(Metadata* asmJSMetadata)
|
|||
metadata_ = asmJSMetadata;
|
||||
MOZ_ASSERT(isAsmJS());
|
||||
|
||||
// Enabling debugging requires baseline and baseline is only enabled for
|
||||
// wasm (since the baseline does not currently support Atomics or SIMD).
|
||||
|
||||
metadata_->debugEnabled = false;
|
||||
compileMode_ = CompileMode::Ion;
|
||||
|
||||
// For asm.js, the Vectors in ModuleEnvironment are max-sized reservations
|
||||
// and will be initialized in a linear order via init* functions as the
|
||||
// module is generated.
|
||||
|
@ -124,7 +129,7 @@ ModuleGenerator::initAsmJS(Metadata* asmJSMetadata)
|
|||
}
|
||||
|
||||
bool
|
||||
ModuleGenerator::initWasm()
|
||||
ModuleGenerator::initWasm(const CompileArgs& args)
|
||||
{
|
||||
MOZ_ASSERT(!env_->isAsmJS());
|
||||
|
||||
|
@ -134,6 +139,11 @@ ModuleGenerator::initWasm()
|
|||
|
||||
MOZ_ASSERT(!isAsmJS());
|
||||
|
||||
metadata_->debugEnabled = args.debugEnabled && BaselineCanCompile();
|
||||
compileMode_ = args.alwaysBaseline || metadata_->debugEnabled
|
||||
? CompileMode::Baseline
|
||||
: CompileMode::Ion;
|
||||
|
||||
// For wasm, the Vectors are correctly-sized and already initialized.
|
||||
|
||||
numSigs_ = env_->sigs.length();
|
||||
|
@ -202,9 +212,6 @@ ModuleGenerator::init(UniqueModuleEnvironment env, const CompileArgs& args,
|
|||
|
||||
linkData_.globalDataLength = AlignBytes(InitialGlobalDataBytes, sizeof(void*));
|
||||
|
||||
alwaysBaseline_ = args.alwaysBaseline;
|
||||
debugEnabled_ = args.debugEnabled;
|
||||
|
||||
if (!funcToCodeRange_.appendN(BAD_CODE_RANGE, env_->funcSigs.length()))
|
||||
return false;
|
||||
|
||||
|
@ -214,7 +221,7 @@ ModuleGenerator::init(UniqueModuleEnvironment env, const CompileArgs& args,
|
|||
if (!exportedFuncs_.init())
|
||||
return false;
|
||||
|
||||
if (env_->isAsmJS() ? !initAsmJS(maybeAsmJSMetadata) : !initWasm())
|
||||
if (env_->isAsmJS() ? !initAsmJS(maybeAsmJSMetadata) : !initWasm(args))
|
||||
return false;
|
||||
|
||||
if (args.scriptedCaller.filename) {
|
||||
|
@ -903,7 +910,7 @@ ModuleGenerator::startFuncDefs()
|
|||
if (!tasks_.initCapacity(numTasks))
|
||||
return false;
|
||||
for (size_t i = 0; i < numTasks; i++)
|
||||
tasks_.infallibleEmplaceBack(*env_, COMPILATION_LIFO_DEFAULT_CHUNK_SIZE);
|
||||
tasks_.infallibleEmplaceBack(*env_, compileMode_, COMPILATION_LIFO_DEFAULT_CHUNK_SIZE);
|
||||
|
||||
if (!freeTasks_.reserve(numTasks))
|
||||
return false;
|
||||
|
@ -948,7 +955,7 @@ ModuleGenerator::launchBatchCompile()
|
|||
{
|
||||
MOZ_ASSERT(currentTask_);
|
||||
|
||||
currentTask_->setDebugEnabled(debugEnabled_);
|
||||
currentTask_->setDebugEnabled(metadata_->debugEnabled);
|
||||
|
||||
size_t numBatchedFuncs = currentTask_->units().length();
|
||||
MOZ_ASSERT(numBatchedFuncs);
|
||||
|
@ -977,30 +984,20 @@ ModuleGenerator::finishFuncDef(uint32_t funcIndex, FunctionGenerator* fg)
|
|||
MOZ_ASSERT(activeFuncDef_ == fg);
|
||||
|
||||
UniqueFuncBytes func = Move(fg->funcBytes_);
|
||||
|
||||
func->setFunc(funcIndex, &funcSig(funcIndex));
|
||||
|
||||
CompileMode mode;
|
||||
if ((alwaysBaseline_ || debugEnabled_) && BaselineCanCompile(fg)) {
|
||||
mode = CompileMode::Baseline;
|
||||
} else {
|
||||
mode = CompileMode::Ion;
|
||||
// Ion does not support debugging -- reset debugEnabled_ flags to avoid
|
||||
// turning debugging for wasm::Code.
|
||||
debugEnabled_ = false;
|
||||
}
|
||||
|
||||
CheckedInt<uint32_t> newBatched = func->bytes().length();
|
||||
if (mode == CompileMode::Ion)
|
||||
newBatched *= JitOptions.wasmBatchIonScaleFactor;
|
||||
newBatched += batchedBytecode_;
|
||||
|
||||
if (!currentTask_->units().emplaceBack(Move(func), mode))
|
||||
uint32_t funcBytecodeLength = func->bytes().length();
|
||||
if (!currentTask_->units().emplaceBack(Move(func)))
|
||||
return false;
|
||||
|
||||
if (newBatched.isValid() && newBatched.value() < JitOptions.wasmBatchThreshold)
|
||||
batchedBytecode_ = newBatched.value();
|
||||
else if (!launchBatchCompile())
|
||||
uint32_t threshold;
|
||||
switch (compileMode_) {
|
||||
case CompileMode::Baseline: threshold = JitOptions.wasmBatchBaselineThreshold; break;
|
||||
case CompileMode::Ion: threshold = JitOptions.wasmBatchIonThreshold; break;
|
||||
}
|
||||
|
||||
batchedBytecode_ += funcBytecodeLength;
|
||||
MOZ_ASSERT(batchedBytecode_ <= MaxModuleBytes);
|
||||
if (batchedBytecode_ > threshold && !launchBatchCompile())
|
||||
return false;
|
||||
|
||||
fg->m_ = nullptr;
|
||||
|
@ -1189,8 +1186,6 @@ ModuleGenerator::finish(const ShareableBytes& bytecode)
|
|||
if (isAsmJS() && !metadata_->tables.resize(numTables_))
|
||||
return nullptr;
|
||||
|
||||
metadata_->debugEnabled = debugEnabled_;
|
||||
|
||||
// Assert CodeRanges are sorted.
|
||||
#ifdef DEBUG
|
||||
uint32_t lastEnd = 0;
|
||||
|
@ -1229,17 +1224,19 @@ wasm::CompileFunction(CompileTask* task, UniqueChars* error)
|
|||
TraceLoggerThread* logger = TraceLoggerForCurrentThread();
|
||||
AutoTraceLog logCompile(logger, TraceLogger_WasmCompilation);
|
||||
|
||||
for (FuncCompileUnit& unit : task->units()) {
|
||||
switch (unit.mode()) {
|
||||
case CompileMode::Ion:
|
||||
switch (task->mode()) {
|
||||
case CompileMode::Ion:
|
||||
for (FuncCompileUnit& unit : task->units()) {
|
||||
if (!IonCompileFunction(task, &unit, error))
|
||||
return false;
|
||||
break;
|
||||
case CompileMode::Baseline:
|
||||
}
|
||||
break;
|
||||
case CompileMode::Baseline:
|
||||
for (FuncCompileUnit& unit : task->units()) {
|
||||
if (!BaselineCompileFunction(task, &unit, error))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -101,19 +101,16 @@ enum class CompileMode
|
|||
class FuncCompileUnit
|
||||
{
|
||||
UniqueFuncBytes func_;
|
||||
CompileMode mode_;
|
||||
FuncOffsets offsets_;
|
||||
DebugOnly<bool> finished_;
|
||||
|
||||
public:
|
||||
FuncCompileUnit(UniqueFuncBytes func, CompileMode mode)
|
||||
explicit FuncCompileUnit(UniqueFuncBytes func)
|
||||
: func_(Move(func)),
|
||||
mode_(mode),
|
||||
finished_(false)
|
||||
{}
|
||||
|
||||
const FuncBytes& func() const { return *func_; }
|
||||
CompileMode mode() const { return mode_; }
|
||||
FuncOffsets offsets() const { MOZ_ASSERT(finished_); return offsets_; }
|
||||
|
||||
void finish(FuncOffsets offsets) {
|
||||
|
@ -140,6 +137,7 @@ typedef Vector<FuncCompileUnit, 8, SystemAllocPolicy> FuncCompileUnitVector;
|
|||
class CompileTask
|
||||
{
|
||||
const ModuleEnvironment& env_;
|
||||
CompileMode mode_;
|
||||
LifoAlloc lifo_;
|
||||
Maybe<jit::TempAllocator> alloc_;
|
||||
Maybe<jit::MacroAssembler> masm_;
|
||||
|
@ -156,8 +154,9 @@ class CompileTask
|
|||
}
|
||||
|
||||
public:
|
||||
CompileTask(const ModuleEnvironment& env, size_t defaultChunkSize)
|
||||
CompileTask(const ModuleEnvironment& env, CompileMode mode, size_t defaultChunkSize)
|
||||
: env_(env),
|
||||
mode_(mode),
|
||||
lifo_(defaultChunkSize)
|
||||
{
|
||||
init();
|
||||
|
@ -177,6 +176,9 @@ class CompileTask
|
|||
FuncCompileUnitVector& units() {
|
||||
return units_;
|
||||
}
|
||||
CompileMode mode() const {
|
||||
return mode_;
|
||||
}
|
||||
bool debugEnabled() const {
|
||||
return debugEnabled_;
|
||||
}
|
||||
|
@ -213,8 +215,7 @@ class MOZ_STACK_CLASS ModuleGenerator
|
|||
typedef EnumeratedArray<Trap, Trap::Limit, ProfilingOffsets> TrapExitOffsetArray;
|
||||
|
||||
// Constant parameters
|
||||
bool alwaysBaseline_;
|
||||
bool debugEnabled_;
|
||||
CompileMode compileMode_;
|
||||
UniqueChars* error_;
|
||||
|
||||
// Data that is moved into the result of finish()
|
||||
|
@ -268,7 +269,7 @@ class MOZ_STACK_CLASS ModuleGenerator
|
|||
MOZ_MUST_USE bool launchBatchCompile();
|
||||
|
||||
MOZ_MUST_USE bool initAsmJS(Metadata* asmJSMetadata);
|
||||
MOZ_MUST_USE bool initWasm();
|
||||
MOZ_MUST_USE bool initWasm(const CompileArgs& args);
|
||||
|
||||
public:
|
||||
explicit ModuleGenerator(UniqueChars* error);
|
||||
|
|
|
@ -3657,7 +3657,7 @@ EmitExpr(FunctionCompiler& f)
|
|||
bool
|
||||
wasm::IonCompileFunction(CompileTask* task, FuncCompileUnit* unit, UniqueChars* error)
|
||||
{
|
||||
MOZ_ASSERT(unit->mode() == CompileMode::Ion);
|
||||
MOZ_ASSERT(task->mode() == CompileMode::Ion);
|
||||
|
||||
const FuncBytes& func = unit->func();
|
||||
const ModuleEnvironment& env = task->env();
|
||||
|
|
Загрузка…
Ссылка в новой задаче