Bug 1395587 - Baldr: remove FunctionGenerator (r=lth)

MozReview-Commit-ID: 4MIQEVy94OU

--HG--
extra : rebase_source : 97559c214a4e325f6ea16719aa2586f509438fdf
This commit is contained in:
Luke Wagner 2017-09-06 08:31:02 -05:00
parent 4cc7b26afd
commit 36b63a570d
6 changed files with 111 additions and 213 deletions

View File

@ -2892,10 +2892,9 @@ class MOZ_STACK_CLASS FunctionValidator
ModuleValidator& m_; ModuleValidator& m_;
ParseNode* fn_; ParseNode* fn_;
Bytes bytes_;
FunctionGenerator fg_; Encoder encoder_;
Maybe<Encoder> encoder_; Uint32Vector callSiteLineNums_;
LocalMap locals_; LocalMap locals_;
// Labels // Labels
@ -2912,6 +2911,7 @@ class MOZ_STACK_CLASS FunctionValidator
FunctionValidator(ModuleValidator& m, ParseNode* fn) FunctionValidator(ModuleValidator& m, ParseNode* fn)
: m_(m), : m_(m),
fn_(fn), fn_(fn),
encoder_(bytes_),
locals_(m.cx()), locals_(m.cx()),
breakLabels_(m.cx()), breakLabels_(m.cx()),
continueLabels_(m.cx()), continueLabels_(m.cx()),
@ -2924,24 +2924,19 @@ class MOZ_STACK_CLASS FunctionValidator
JSContext* cx() const { return m_.cx(); } JSContext* cx() const { return m_.cx(); }
ParseNode* fn() const { return fn_; } ParseNode* fn() const { return fn_; }
bool init(PropertyName* name, unsigned line) { bool init() {
if (!locals_.init() || !breakLabels_.init() || !continueLabels_.init()) return locals_.init() &&
return false; breakLabels_.init() &&
continueLabels_.init();
if (!m_.mg().startFuncDef(line, &fg_))
return false;
encoder_.emplace(fg_.bytes());
return true;
} }
bool finish(uint32_t funcIndex) { bool finish(uint32_t funcIndex, unsigned line) {
MOZ_ASSERT(!blockDepth_); MOZ_ASSERT(!blockDepth_);
MOZ_ASSERT(breakableStack_.empty()); MOZ_ASSERT(breakableStack_.empty());
MOZ_ASSERT(continuableStack_.empty()); MOZ_ASSERT(continuableStack_.empty());
MOZ_ASSERT(breakLabels_.empty()); MOZ_ASSERT(breakLabels_.empty());
MOZ_ASSERT(continueLabels_.empty()); MOZ_ASSERT(continueLabels_.empty());
return m_.mg().finishFuncDef(funcIndex, &fg_); return m_.mg().compileFuncDef(funcIndex, line, Move(bytes_), Move(callSiteLineNums_));
} }
bool fail(ParseNode* pn, const char* str) { bool fail(ParseNode* pn, const char* str) {
@ -3136,7 +3131,7 @@ class MOZ_STACK_CLASS FunctionValidator
/**************************************************** Encoding interface */ /**************************************************** Encoding interface */
Encoder& encoder() { return *encoder_; } Encoder& encoder() { return encoder_; }
MOZ_MUST_USE bool writeInt32Lit(int32_t i32) { MOZ_MUST_USE bool writeInt32Lit(int32_t i32) {
return encoder().writeOp(Op::I32Const) && return encoder().writeOp(Op::I32Const) &&
@ -3188,14 +3183,14 @@ class MOZ_STACK_CLASS FunctionValidator
} }
MOZ_MUST_USE bool writeCall(ParseNode* pn, Op op) { MOZ_MUST_USE bool writeCall(ParseNode* pn, Op op) {
return encoder().writeOp(op) && return encoder().writeOp(op) &&
fg_.addCallSiteLineNum(m().tokenStream().srcCoords.lineNum(pn->pn_pos.begin)); callSiteLineNums_.append(m().tokenStream().srcCoords.lineNum(pn->pn_pos.begin));
} }
MOZ_MUST_USE bool writeCall(ParseNode* pn, MozOp op) { MOZ_MUST_USE bool writeCall(ParseNode* pn, MozOp op) {
return encoder().writeOp(op) && return encoder().writeOp(op) &&
fg_.addCallSiteLineNum(m().tokenStream().srcCoords.lineNum(pn->pn_pos.begin)); callSiteLineNums_.append(m().tokenStream().srcCoords.lineNum(pn->pn_pos.begin));
} }
MOZ_MUST_USE bool prepareCall(ParseNode* pn) { MOZ_MUST_USE bool prepareCall(ParseNode* pn) {
return fg_.addCallSiteLineNum(m().tokenStream().srcCoords.lineNum(pn->pn_pos.begin)); return callSiteLineNums_.append(m().tokenStream().srcCoords.lineNum(pn->pn_pos.begin));
} }
MOZ_MUST_USE bool writeSimdOp(SimdType simdType, SimdOperation simdOp) { MOZ_MUST_USE bool writeSimdOp(SimdType simdType, SimdOperation simdOp) {
MozOp op = SimdToOp(simdType, simdOp); MozOp op = SimdToOp(simdType, simdOp);
@ -7104,7 +7099,7 @@ CheckFunction(ModuleValidator& m)
return false; return false;
FunctionValidator f(m, fn); FunctionValidator f(m, fn);
if (!f.init(FunctionName(fn), line)) if (!f.init())
return m.fail(fn, "internal compiler failure (probably out of memory)"); return m.fail(fn, "internal compiler failure (probably out of memory)");
ParseNode* stmtIter = ListHead(FunctionStatementList(fn)); ParseNode* stmtIter = ListHead(FunctionStatementList(fn));
@ -7138,7 +7133,7 @@ CheckFunction(ModuleValidator& m)
func->define(fn); func->define(fn);
if (!f.finish(func->index())) if (!f.finish(func->index(), line))
return m.fail(fn, "internal compiler failure (probably out of memory)"); return m.fail(fn, "internal compiler failure (probably out of memory)");
// Release the parser's lifo memory only after the last use of a parse node. // Release the parser's lifo memory only after the last use of a parse node.

View File

@ -570,7 +570,7 @@ class BaseCompiler
const ModuleEnvironment& env_; const ModuleEnvironment& env_;
BaseOpIter iter_; BaseOpIter iter_;
const FuncBytes& func_; const FuncCompileUnit& func_;
size_t lastReadCallSite_; size_t lastReadCallSite_;
TempAllocator& alloc_; TempAllocator& alloc_;
const ValTypeVector& locals_; // Types of parameters and locals const ValTypeVector& locals_; // Types of parameters and locals
@ -645,7 +645,7 @@ class BaseCompiler
public: public:
BaseCompiler(const ModuleEnvironment& env, BaseCompiler(const ModuleEnvironment& env,
Decoder& decoder, Decoder& decoder,
const FuncBytes& func, const FuncCompileUnit& func,
const ValTypeVector& locals, const ValTypeVector& locals,
bool debugEnabled, bool debugEnabled,
TempAllocator* alloc, TempAllocator* alloc,
@ -659,6 +659,8 @@ class BaseCompiler
MOZ_MUST_USE bool emitFunction(); MOZ_MUST_USE bool emitFunction();
void emitInitStackLocals(); void emitInitStackLocals();
const SigWithId& sig() const { return *env_.funcSigs[func_.index()]; }
// Used by some of the ScratchRegister implementations. // Used by some of the ScratchRegister implementations.
operator MacroAssembler&() const { return masm; } operator MacroAssembler&() const { return masm; }
@ -2236,7 +2238,7 @@ class BaseCompiler
// Copy arguments from registers to stack. // Copy arguments from registers to stack.
const ValTypeVector& args = func_.sig().args(); const ValTypeVector& args = sig().args();
for (ABIArgIter<const ValTypeVector> i(args); !i.done(); i++) { for (ABIArgIter<const ValTypeVector> i(args); !i.done(); i++) {
Local& l = localInfo_[i.index()]; Local& l = localInfo_[i.index()];
@ -2273,7 +2275,7 @@ class BaseCompiler
MOZ_ASSERT(debugEnabled_); MOZ_ASSERT(debugEnabled_);
size_t debugFrameOffset = masm.framePushed() - DebugFrame::offsetOfFrame(); size_t debugFrameOffset = masm.framePushed() - DebugFrame::offsetOfFrame();
Address resultsAddress(StackPointer, debugFrameOffset + DebugFrame::offsetOfResults()); Address resultsAddress(StackPointer, debugFrameOffset + DebugFrame::offsetOfResults());
switch (func_.sig().ret()) { switch (sig().ret()) {
case ExprType::Void: case ExprType::Void:
break; break;
case ExprType::I32: case ExprType::I32:
@ -2298,7 +2300,7 @@ class BaseCompiler
MOZ_ASSERT(debugEnabled_); MOZ_ASSERT(debugEnabled_);
size_t debugFrameOffset = masm.framePushed() - DebugFrame::offsetOfFrame(); size_t debugFrameOffset = masm.framePushed() - DebugFrame::offsetOfFrame();
Address resultsAddress(StackPointer, debugFrameOffset + DebugFrame::offsetOfResults()); Address resultsAddress(StackPointer, debugFrameOffset + DebugFrame::offsetOfResults());
switch (func_.sig().ret()) { switch (sig().ret()) {
case ExprType::Void: case ExprType::Void:
break; break;
case ExprType::I32: case ExprType::I32:
@ -5822,7 +5824,7 @@ BaseCompiler::emitReturn()
if (deadCode_) if (deadCode_)
return true; return true;
doReturn(func_.sig().ret(), PopStack(true)); doReturn(sig().ret(), PopStack(true));
deadCode_ = true; deadCode_ = true;
return true; return true;
@ -6891,7 +6893,7 @@ BaseCompiler::emitCurrentMemory()
bool bool
BaseCompiler::emitBody() BaseCompiler::emitBody()
{ {
if (!iter_.readFunctionStart(func_.sig().ret())) if (!iter_.readFunctionStart(sig().ret()))
return false; return false;
initControl(controlItem()); initControl(controlItem());
@ -6973,7 +6975,7 @@ BaseCompiler::emitBody()
if (iter_.controlStackEmpty()) { if (iter_.controlStackEmpty()) {
if (!deadCode_) if (!deadCode_)
doReturn(func_.sig().ret(), PopStack(false)); doReturn(sig().ret(), PopStack(false));
return iter_.readFunctionEnd(iter_.end()); return iter_.readFunctionEnd(iter_.end());
} }
NEXT(); NEXT();
@ -7584,7 +7586,7 @@ BaseCompiler::emitInitStackLocals()
BaseCompiler::BaseCompiler(const ModuleEnvironment& env, BaseCompiler::BaseCompiler(const ModuleEnvironment& env,
Decoder& decoder, Decoder& decoder,
const FuncBytes& func, const FuncCompileUnit& func,
const ValTypeVector& locals, const ValTypeVector& locals,
bool debugEnabled, bool debugEnabled,
TempAllocator* alloc, TempAllocator* alloc,
@ -7673,11 +7675,10 @@ BaseCompiler::init()
if (!SigI64I64_.append(ValType::I64) || !SigI64I64_.append(ValType::I64)) if (!SigI64I64_.append(ValType::I64) || !SigI64I64_.append(ValType::I64))
return false; return false;
const ValTypeVector& args = func_.sig().args();
if (!localInfo_.resize(locals_.length())) if (!localInfo_.resize(locals_.length()))
return false; return false;
const ValTypeVector& args = sig().args();
BaseLocalIter i(locals_, args.length(), debugEnabled_); BaseLocalIter i(locals_, args.length(), debugEnabled_);
varLow_ = i.reservedSize(); varLow_ = i.reservedSize();
for (; !i.done() && i.index() < args.length(); i++) { for (; !i.done() && i.index() < args.length(); i++) {
@ -7742,19 +7743,17 @@ js::wasm::BaselineCanCompile()
} }
bool bool
js::wasm::BaselineCompileFunction(CompileTask* task, FuncCompileUnit* unit, UniqueChars *error) js::wasm::BaselineCompileFunction(CompileTask* task, FuncCompileUnit* func, UniqueChars* error)
{ {
MOZ_ASSERT(task->tier() == Tier::Baseline); MOZ_ASSERT(task->tier() == Tier::Baseline);
MOZ_ASSERT(task->env().kind == ModuleKind::Wasm); MOZ_ASSERT(task->env().kind == ModuleKind::Wasm);
const FuncBytes& func = unit->func(); Decoder d(func->begin(), func->end(), func->lineOrBytecode(), error);
Decoder d(func.bytes().begin(), func.bytes().end(), func.lineOrBytecode(), error);
// Build the local types vector. // Build the local types vector.
ValTypeVector locals; ValTypeVector locals;
if (!locals.appendAll(func.sig().args())) if (!locals.appendAll(task->env().funcSigs[func->index()]->args()))
return false; return false;
if (!DecodeLocalEntries(d, task->env().kind, &locals)) if (!DecodeLocalEntries(d, task->env().kind, &locals))
return false; return false;
@ -7765,7 +7764,7 @@ js::wasm::BaselineCompileFunction(CompileTask* task, FuncCompileUnit* unit, Uniq
// One-pass baseline compilation. // One-pass baseline compilation.
BaseCompiler f(task->env(), d, func, locals, task->debugEnabled(), &task->alloc(), BaseCompiler f(task->env(), d, *func, locals, task->debugEnabled(), &task->alloc(),
&task->masm(), task->mode()); &task->masm(), task->mode());
if (!f.init()) if (!f.init())
return false; return false;
@ -7773,7 +7772,7 @@ js::wasm::BaselineCompileFunction(CompileTask* task, FuncCompileUnit* unit, Uniq
if (!f.emitFunction()) if (!f.emitFunction())
return false; return false;
unit->finish(f.finish()); func->finish(f.finish());
return true; return true;
} }

View File

@ -42,21 +42,12 @@ DecodeFunctionBody(Decoder& d, ModuleGenerator& mg, uint32_t funcIndex)
const size_t offsetInModule = d.currentOffset(); const size_t offsetInModule = d.currentOffset();
// Skip over the function body; we'll validate it later. // Skip over the function body; it will be validated by the compilation thread.
const uint8_t* bodyBegin; const uint8_t* bodyBegin;
if (!d.readBytes(bodySize, &bodyBegin)) if (!d.readBytes(bodySize, &bodyBegin))
return d.fail("function body length too big"); return d.fail("function body length too big");
FunctionGenerator fg; return mg.compileFuncDef(funcIndex, offsetInModule, bodyBegin, bodyBegin + bodySize);
if (!mg.startFuncDef(offsetInModule, &fg))
return false;
if (!fg.bytes().resize(bodySize))
return false;
memcpy(fg.bytes().begin(), bodyBegin, bodySize);
return mg.finishFuncDef(funcIndex, &fg);
} }
static bool static bool

View File

@ -64,7 +64,6 @@ ModuleGenerator::ModuleGenerator(const CompileArgs& args, ModuleEnvironment* env
outstanding_(0), outstanding_(0),
currentTask_(nullptr), currentTask_(nullptr),
batchedBytecode_(0), batchedBytecode_(0),
activeFuncDef_(nullptr),
startedFuncDefs_(false), startedFuncDefs_(false),
finishedFuncDefs_(false), finishedFuncDefs_(false),
numFinishedFuncDefs_(0) numFinishedFuncDefs_(0)
@ -432,12 +431,10 @@ ModuleGenerator::finishTask(CompileTask* task)
} }
uint32_t offsetInWhole = masm_.size(); uint32_t offsetInWhole = masm_.size();
for (const FuncCompileUnit& unit : task->units()) { for (const FuncCompileUnit& func : task->units()) {
const FuncBytes& func = unit.func();
// Offset the recorded FuncOffsets by the offset of the function in the // Offset the recorded FuncOffsets by the offset of the function in the
// whole module's code segment. // whole module's code segment.
FuncOffsets offsets = unit.offsets(); FuncOffsets offsets = func.offsets();
offsets.offsetBy(offsetInWhole); offsets.offsetBy(offsetInWhole);
// Add the CodeRange for this function. // Add the CodeRange for this function.
@ -455,7 +452,7 @@ ModuleGenerator::finishTask(CompileTask* task)
return false; return false;
MOZ_ASSERT(masm_.size() == offsetInWhole + task->masm().size()); MOZ_ASSERT(masm_.size() == offsetInWhole + task->masm().size());
if (!task->reset(&freeFuncBytes_)) if (!task->reset())
return false; return false;
freeTasks_.infallibleAppend(task); freeTasks_.infallibleAppend(task);
@ -885,34 +882,6 @@ ModuleGenerator::startFuncDefs()
return true; return true;
} }
bool
ModuleGenerator::startFuncDef(uint32_t lineOrBytecode, FunctionGenerator* fg)
{
MOZ_ASSERT(startedFuncDefs_);
MOZ_ASSERT(!activeFuncDef_);
MOZ_ASSERT(!finishedFuncDefs_);
if (!freeFuncBytes_.empty()) {
fg->funcBytes_ = Move(freeFuncBytes_.back());
freeFuncBytes_.popBack();
} else {
fg->funcBytes_ = js::MakeUnique<FuncBytes>();
if (!fg->funcBytes_)
return false;
}
if (!currentTask_) {
if (freeTasks_.empty() && !finishOutstandingTask())
return false;
currentTask_ = freeTasks_.popCopy();
}
fg->funcBytes_->setLineOrBytecode(lineOrBytecode);
fg->m_ = this;
activeFuncDef_ = fg;
return true;
}
bool bool
ModuleGenerator::launchBatchCompile() ModuleGenerator::launchBatchCompile()
{ {
@ -943,15 +912,24 @@ ModuleGenerator::launchBatchCompile()
} }
bool bool
ModuleGenerator::finishFuncDef(uint32_t funcIndex, FunctionGenerator* fg) ModuleGenerator::compileFuncDef(uint32_t funcIndex, uint32_t lineOrBytecode,
Bytes&& bytes, const uint8_t* begin, const uint8_t* end,
Uint32Vector&& lineNums)
{ {
MOZ_ASSERT(activeFuncDef_ == fg); MOZ_ASSERT(startedFuncDefs_);
MOZ_ASSERT(!finishedFuncDefs_);
MOZ_ASSERT_IF(mode() == CompileMode::Tier1, funcIndex < env_->numFuncs()); MOZ_ASSERT_IF(mode() == CompileMode::Tier1, funcIndex < env_->numFuncs());
UniqueFuncBytes func = Move(fg->funcBytes_); if (!currentTask_) {
func->setFunc(funcIndex, &funcSig(funcIndex)); if (freeTasks_.empty() && !finishOutstandingTask())
uint32_t funcBytecodeLength = func->bytes().length(); return false;
if (!currentTask_->units().emplaceBack(Move(func))) currentTask_ = freeTasks_.popCopy();
}
uint32_t funcBytecodeLength = end - begin;
FuncCompileUnitVector& units = currentTask_->units();
if (!units.emplaceBack(funcIndex, lineOrBytecode, Move(bytes), begin, end, Move(lineNums)))
return false; return false;
uint32_t threshold; uint32_t threshold;
@ -963,19 +941,27 @@ ModuleGenerator::finishFuncDef(uint32_t funcIndex, FunctionGenerator* fg)
batchedBytecode_ += funcBytecodeLength; batchedBytecode_ += funcBytecodeLength;
MOZ_ASSERT(batchedBytecode_ <= MaxModuleBytes); MOZ_ASSERT(batchedBytecode_ <= MaxModuleBytes);
if (batchedBytecode_ > threshold && !launchBatchCompile()) return batchedBytecode_ <= threshold || launchBatchCompile();
return false; }
fg->m_ = nullptr; bool
activeFuncDef_ = nullptr; ModuleGenerator::compileFuncDef(uint32_t funcIndex, uint32_t lineOrBytecode,
return true; const uint8_t* begin, const uint8_t* end)
{
return compileFuncDef(funcIndex, lineOrBytecode, Bytes(), begin, end, Uint32Vector());
}
bool
ModuleGenerator::compileFuncDef(uint32_t funcIndex, uint32_t lineOrBytecode,
Bytes&& bytes, Uint32Vector&& lineNums)
{
return compileFuncDef(funcIndex, lineOrBytecode, Move(bytes), bytes.begin(), bytes.end(), Move(lineNums));
} }
bool bool
ModuleGenerator::finishFuncDefs() ModuleGenerator::finishFuncDefs()
{ {
MOZ_ASSERT(startedFuncDefs_); MOZ_ASSERT(startedFuncDefs_);
MOZ_ASSERT(!activeFuncDef_);
MOZ_ASSERT(!finishedFuncDefs_); MOZ_ASSERT(!finishedFuncDefs_);
if (currentTask_ && !launchBatchCompile()) if (currentTask_ && !launchBatchCompile())
@ -1155,7 +1141,6 @@ ModuleGenerator::finishMetadata(const ShareableBytes& bytecode)
UniqueConstCodeSegment UniqueConstCodeSegment
ModuleGenerator::finishCodeSegment(const ShareableBytes& bytecode) ModuleGenerator::finishCodeSegment(const ShareableBytes& bytecode)
{ {
MOZ_ASSERT(!activeFuncDef_);
MOZ_ASSERT(finishedFuncDefs_); MOZ_ASSERT(finishedFuncDefs_);
if (!finishFuncExports()) if (!finishFuncExports())

View File

@ -29,77 +29,43 @@ namespace wasm {
struct CompileArgs; struct CompileArgs;
struct ModuleEnvironment; struct ModuleEnvironment;
class FunctionGenerator;
// The FuncBytes class represents a single, concurrently-compilable function.
// A FuncBytes object is composed of the wasm function body bytes along with the
// ambient metadata describing the function necessary to compile it.
class FuncBytes
{
Bytes bytes_;
uint32_t index_;
const SigWithId* sig_;
uint32_t lineOrBytecode_;
Uint32Vector callSiteLineNums_;
public:
FuncBytes()
: index_(UINT32_MAX),
sig_(nullptr),
lineOrBytecode_(UINT32_MAX)
{}
Bytes& bytes() {
return bytes_;
}
MOZ_MUST_USE bool addCallSiteLineNum(uint32_t lineno) {
return callSiteLineNums_.append(lineno);
}
void setLineOrBytecode(uint32_t lineOrBytecode) {
MOZ_ASSERT(lineOrBytecode_ == UINT32_MAX);
lineOrBytecode_ = lineOrBytecode;
}
void setFunc(uint32_t index, const SigWithId* sig) {
MOZ_ASSERT(index_ == UINT32_MAX);
MOZ_ASSERT(sig_ == nullptr);
index_ = index;
sig_ = sig;
}
void reset() {
bytes_.clear();
index_ = UINT32_MAX;
sig_ = nullptr;
lineOrBytecode_ = UINT32_MAX;
callSiteLineNums_.clear();
}
const Bytes& bytes() const { return bytes_; }
uint32_t index() const { return index_; }
const SigWithId& sig() const { return *sig_; }
uint32_t lineOrBytecode() const { return lineOrBytecode_; }
const Uint32Vector& callSiteLineNums() const { return callSiteLineNums_; }
};
typedef UniquePtr<FuncBytes> UniqueFuncBytes;
typedef Vector<UniqueFuncBytes, 8, SystemAllocPolicy> UniqueFuncBytesVector;
// FuncCompileUnit contains all the data necessary to produce and store the // FuncCompileUnit contains all the data necessary to produce and store the
// results of a single function's compilation. // results of a single function's compilation.
class FuncCompileUnit class FuncCompileUnit
{ {
UniqueFuncBytes func_; // Input:
Bytes bytesToDelete_;
const uint8_t* begin_;
const uint8_t* end_;
uint32_t index_;
uint32_t lineOrBytecode_;
Uint32Vector callSiteLineNums_;
// Output:
FuncOffsets offsets_; FuncOffsets offsets_;
DebugOnly<bool> finished_; DebugOnly<bool> finished_;
public: public:
explicit FuncCompileUnit(UniqueFuncBytes func) explicit FuncCompileUnit(uint32_t index, uint32_t lineOrBytecode,
: func_(Move(func)), Bytes&& bytesToDelete, const uint8_t* begin, const uint8_t* end,
Uint32Vector&& callSiteLineNums)
: bytesToDelete_(Move(bytesToDelete)),
begin_(begin),
end_(end),
index_(index),
lineOrBytecode_(lineOrBytecode),
callSiteLineNums_(Move(callSiteLineNums)),
finished_(false) finished_(false)
{} {}
const FuncBytes& func() const { return *func_; } const uint8_t* begin() const { return begin_; }
const uint8_t* end() const { return end_; }
uint32_t index() const { return index_; }
uint32_t lineOrBytecode() const { return lineOrBytecode_; }
const Uint32Vector& callSiteLineNums() const { return callSiteLineNums_; }
FuncOffsets offsets() const { MOZ_ASSERT(finished_); return offsets_; } FuncOffsets offsets() const { MOZ_ASSERT(finished_); return offsets_; }
void finish(FuncOffsets offsets) { void finish(FuncOffsets offsets) {
@ -107,12 +73,6 @@ class FuncCompileUnit
offsets_ = offsets; offsets_ = offsets;
finished_ = true; finished_ = true;
} }
UniqueFuncBytes recycle() {
MOZ_ASSERT(finished_);
func_->reset();
return Move(func_);
}
}; };
typedef Vector<FuncCompileUnit, 8, SystemAllocPolicy> FuncCompileUnitVector; typedef Vector<FuncCompileUnit, 8, SystemAllocPolicy> FuncCompileUnitVector;
@ -120,8 +80,7 @@ typedef Vector<FuncCompileUnit, 8, SystemAllocPolicy> FuncCompileUnitVector;
// A CompileTask represents the task of compiling a batch of functions. It is // A CompileTask represents the task of compiling a batch of functions. It is
// filled with a certain number of function's bodies that are sent off to a // filled with a certain number of function's bodies that are sent off to a
// compilation helper thread, which fills in the resulting code offsets, and // compilation helper thread, which fills in the resulting code offsets, and
// finally sent back to the validation thread. To save time allocating and // finally sent back to the validation thread.
// freeing memory, CompileTasks are reset() and reused.
class CompileTask class CompileTask
{ {
@ -170,17 +129,11 @@ class CompileTask
bool debugEnabled() const { bool debugEnabled() const {
return env_.debug == DebugEnabled::True; return env_.debug == DebugEnabled::True;
} }
bool reset(UniqueFuncBytesVector* freeFuncBytes) { bool reset() {
for (FuncCompileUnit& unit : units_) {
if (!freeFuncBytes->emplaceBack(Move(unit.recycle())))
return false;
}
units_.clear(); units_.clear();
masm_.reset(); masm_.reset();
alloc_.reset(); alloc_.reset();
lifo_.releaseAll(); lifo_.releaseAll();
init(); init();
return true; return true;
} }
@ -233,12 +186,10 @@ class MOZ_STACK_CLASS ModuleGenerator
uint32_t outstanding_; uint32_t outstanding_;
CompileTaskVector tasks_; CompileTaskVector tasks_;
CompileTaskPtrVector freeTasks_; CompileTaskPtrVector freeTasks_;
UniqueFuncBytesVector freeFuncBytes_;
CompileTask* currentTask_; CompileTask* currentTask_;
uint32_t batchedBytecode_; uint32_t batchedBytecode_;
// Assertions // Assertions
DebugOnly<FunctionGenerator*> activeFuncDef_;
DebugOnly<bool> startedFuncDefs_; DebugOnly<bool> startedFuncDefs_;
DebugOnly<bool> finishedFuncDefs_; DebugOnly<bool> finishedFuncDefs_;
DebugOnly<uint32_t> numFinishedFuncDefs_; DebugOnly<uint32_t> numFinishedFuncDefs_;
@ -262,6 +213,9 @@ class MOZ_STACK_CLASS ModuleGenerator
MOZ_MUST_USE bool allocateGlobal(GlobalDesc* global); MOZ_MUST_USE bool allocateGlobal(GlobalDesc* global);
MOZ_MUST_USE bool launchBatchCompile(); MOZ_MUST_USE bool launchBatchCompile();
MOZ_MUST_USE bool compileFuncDef(uint32_t funcIndex, uint32_t lineOrBytecode,
Bytes&& bytes, const uint8_t* begin, const uint8_t* end,
Uint32Vector&& lineNums);
MOZ_MUST_USE bool initAsmJS(Metadata* asmJSMetadata); MOZ_MUST_USE bool initAsmJS(Metadata* asmJSMetadata);
MOZ_MUST_USE bool initWasm(); MOZ_MUST_USE bool initWasm();
@ -280,8 +234,10 @@ class MOZ_STACK_CLASS ModuleGenerator
// Function definitions: // Function definitions:
MOZ_MUST_USE bool startFuncDefs(); MOZ_MUST_USE bool startFuncDefs();
MOZ_MUST_USE bool startFuncDef(uint32_t lineOrBytecode, FunctionGenerator* fg); MOZ_MUST_USE bool compileFuncDef(uint32_t funcIndex, uint32_t lineOrBytecode,
MOZ_MUST_USE bool finishFuncDef(uint32_t funcIndex, FunctionGenerator* fg); const uint8_t* begin, const uint8_t* end);
MOZ_MUST_USE bool compileFuncDef(uint32_t funcIndex, uint32_t lineOrBytecode,
Bytes&& bytes, Uint32Vector&& callSiteLineNums);
MOZ_MUST_USE bool finishFuncDefs(); MOZ_MUST_USE bool finishFuncDefs();
// asm.js accessors: // asm.js accessors:
@ -309,33 +265,6 @@ class MOZ_STACK_CLASS ModuleGenerator
MOZ_MUST_USE bool finishTier2(Module& module); MOZ_MUST_USE bool finishTier2(Module& module);
}; };
// A FunctionGenerator encapsulates the generation of a single function body.
// ModuleGenerator::startFuncDef must be called after construction and before
// doing anything else.
//
// After the body is complete, ModuleGenerator::finishFuncDef must be called
// before the FunctionGenerator is destroyed and the next function is started.
class MOZ_STACK_CLASS FunctionGenerator
{
friend class ModuleGenerator;
ModuleGenerator* m_;
UniqueFuncBytes funcBytes_;
public:
FunctionGenerator()
: m_(nullptr), funcBytes_(nullptr)
{}
Bytes& bytes() {
return funcBytes_->bytes();
}
MOZ_MUST_USE bool addCallSiteLineNum(uint32_t lineno) {
return funcBytes_->addCallSiteLineNum(lineno);
}
};
} // namespace wasm } // namespace wasm
} // namespace js } // namespace js

View File

@ -126,7 +126,7 @@ class FunctionCompiler
const ModuleEnvironment& env_; const ModuleEnvironment& env_;
IonOpIter iter_; IonOpIter iter_;
const FuncBytes& func_; const FuncCompileUnit& func_;
const ValTypeVector& locals_; const ValTypeVector& locals_;
size_t lastReadCallSite_; size_t lastReadCallSite_;
@ -149,7 +149,7 @@ class FunctionCompiler
public: public:
FunctionCompiler(const ModuleEnvironment& env, FunctionCompiler(const ModuleEnvironment& env,
Decoder& decoder, Decoder& decoder,
const FuncBytes& func, const FuncCompileUnit& func,
const ValTypeVector& locals, const ValTypeVector& locals,
MIRGenerator& mirGen) MIRGenerator& mirGen)
: env_(env), : env_(env),
@ -171,7 +171,7 @@ class FunctionCompiler
const ModuleEnvironment& env() const { return env_; } const ModuleEnvironment& env() const { return env_; }
IonOpIter& iter() { return iter_; } IonOpIter& iter() { return iter_; }
TempAllocator& alloc() const { return alloc_; } TempAllocator& alloc() const { return alloc_; }
const Sig& sig() const { return func_.sig(); } const Sig& sig() const { return *env_.funcSigs[func_.index()]; }
BytecodeOffset bytecodeOffset() const { BytecodeOffset bytecodeOffset() const {
return iter_.bytecodeOffset(); return iter_.bytecodeOffset();
@ -184,7 +184,7 @@ class FunctionCompiler
{ {
// Prepare the entry block for MIR generation: // Prepare the entry block for MIR generation:
const ValTypeVector& args = func_.sig().args(); const ValTypeVector& args = sig().args();
if (!mirGen_.ensureBallast()) if (!mirGen_.ensureBallast())
return false; return false;
@ -3852,19 +3852,18 @@ EmitBodyExprs(FunctionCompiler& f)
} }
bool bool
wasm::IonCompileFunction(CompileTask* task, FuncCompileUnit* unit, UniqueChars* error) wasm::IonCompileFunction(CompileTask* task, FuncCompileUnit* func, UniqueChars* error)
{ {
MOZ_ASSERT(task->tier() == Tier::Ion); MOZ_ASSERT(task->tier() == Tier::Ion);
const FuncBytes& func = unit->func();
const ModuleEnvironment& env = task->env(); const ModuleEnvironment& env = task->env();
Decoder d(func.bytes().begin(), func.bytes().end(), func.lineOrBytecode(), error); Decoder d(func->begin(), func->end(), func->lineOrBytecode(), error);
// Build the local types vector. // Build the local types vector.
ValTypeVector locals; ValTypeVector locals;
if (!locals.appendAll(func.sig().args())) if (!locals.appendAll(task->env().funcSigs[func->index()]->args()))
return false; return false;
if (!DecodeLocalEntries(d, env.kind, &locals)) if (!DecodeLocalEntries(d, env.kind, &locals))
return false; return false;
@ -3881,7 +3880,7 @@ wasm::IonCompileFunction(CompileTask* task, FuncCompileUnit* unit, UniqueChars*
// Build MIR graph // Build MIR graph
{ {
FunctionCompiler f(env, d, func, locals, mir); FunctionCompiler f(env, d, *func, locals, mir);
if (!f.init()) if (!f.init())
return false; return false;
@ -3906,16 +3905,16 @@ wasm::IonCompileFunction(CompileTask* task, FuncCompileUnit* unit, UniqueChars*
if (!lir) if (!lir)
return false; return false;
SigIdDesc sigId = env.funcSigs[func.index()]->id; SigIdDesc sigId = env.funcSigs[func->index()]->id;
CodeGenerator codegen(&mir, lir, &task->masm()); CodeGenerator codegen(&mir, lir, &task->masm());
BytecodeOffset prologueTrapOffset(func.lineOrBytecode()); BytecodeOffset prologueTrapOffset(func->lineOrBytecode());
FuncOffsets offsets; FuncOffsets offsets;
if (!codegen.generateWasm(sigId, prologueTrapOffset, &offsets)) if (!codegen.generateWasm(sigId, prologueTrapOffset, &offsets))
return false; return false;
unit->finish(offsets); func->finish(offsets);
} }
return true; return true;