Commit 082c6aa0 authored by Lars T Hansen's avatar Lars T Hansen
Browse files

Bug 1675844 - tidy up. r=jseward, a=jcristau

Differential Revision: https://phabricator.services.mozilla.com/D98361
parent 733edfa0
......@@ -1853,8 +1853,9 @@ class BaseStackFrame final : public BaseStackFrameAllocator {
using LocalVector = Vector<Local, 16, SystemAllocPolicy>;
// Initialize `localInfo` based on the types of `locals` and `args`.
bool setupLocals(const ValTypeVector& locals, const ArgTypeVector& args,
bool debugEnabled, LocalVector* localInfo) {
MOZ_MUST_USE bool setupLocals(const ValTypeVector& locals,
const ArgTypeVector& args, bool debugEnabled,
LocalVector* localInfo) {
if (!localInfo->reserve(locals.length())) {
return false;
}
......@@ -3228,7 +3229,7 @@ class BaseCompiler final : public BaseCompilerInterface {
BaseOpIter iter_;
const FuncCompileInput& func_;
size_t lastReadCallSite_;
TempAllocator& alloc_;
TempAllocator::Fallible alloc_;
const ValTypeVector& locals_; // Types of parameters and locals
bool deadCode_; // Flag indicating we should decode & discard the opcode
BCESet
......@@ -3708,6 +3709,8 @@ class BaseCompiler final : public BaseCompilerInterface {
// count.
StkVector stk_;
static constexpr size_t MaxPushesPerOpcode = 10;
// BaselineCompileFunctions() "lends" us the StkVector to use in this
// BaseCompiler object, and that is installed in |stk_| in our constructor.
// This is so as to avoid having to malloc/free the vector's contents at
......@@ -4916,9 +4919,15 @@ class BaseCompiler final : public BaseCompilerInterface {
return Stk::StackResult(result.type(), offs);
}
void pushResults(ResultType type, StackHeight resultsBase) {
MOZ_MUST_USE bool pushResults(ResultType type, StackHeight resultsBase) {
if (type.empty()) {
return;
return true;
}
if (type.length() > 1) {
if (!stk_.reserve(stk_.length() + type.length() + MaxPushesPerOpcode)) {
return false;
}
}
// We need to push the results in reverse order, so first iterate through
......@@ -4968,24 +4977,26 @@ class BaseCompiler final : public BaseCompilerInterface {
break;
}
}
return true;
}
void pushBlockResults(ResultType type) {
pushResults(type, controlItem().stackHeight);
MOZ_MUST_USE bool pushBlockResults(ResultType type) {
return pushResults(type, controlItem().stackHeight);
}
// A combination of popBlockResults + pushBlockResults, used when entering a
// block with a control-flow join (loops) or split (if) to shuffle the
// fallthrough block parameters into the locations expected by the
// continuation.
void topBlockParams(ResultType type) {
MOZ_MUST_USE bool topBlockParams(ResultType type) {
// This function should only be called when entering a block with a
// control-flow join at the entry, where there are no live temporaries in
// the current block.
StackHeight base = controlItem().stackHeight;
MOZ_ASSERT(fr.stackResultsBase(stackConsumed(type.length())) == base);
popBlockResults(type, base, ContinuationKind::Fallthrough);
pushBlockResults(type);
return pushBlockResults(type);
}
// A combination of popBlockResults + pushBlockResults, used before branches
......@@ -4993,9 +5004,10 @@ class BaseCompiler final : public BaseCompilerInterface {
// is taken, the stack results will be shuffled down into place. For br_if
// that has fallthrough, the parameters for the untaken branch flow through to
// the continuation.
StackHeight topBranchParams(ResultType type) {
MOZ_MUST_USE bool topBranchParams(ResultType type, StackHeight* height) {
if (type.empty()) {
return fr.stackHeight();
*height = fr.stackHeight();
return true;
}
// There may be temporary values that need spilling; delay computation of
// the stack results base until after the popRegisterResults(), which spills
......@@ -5006,8 +5018,11 @@ class BaseCompiler final : public BaseCompilerInterface {
if (!iter.done()) {
popStackResults(iter, base);
}
pushResults(type, base);
return base;
if (!pushResults(type, base)) {
return false;
}
*height = base;
return true;
}
// Conditional branches with fallthrough are preceded by a topBranchParams, so
......@@ -5938,8 +5953,8 @@ class BaseCompiler final : public BaseCompilerInterface {
desc, instanceArg, builtin.identity, builtin.failureMode);
}
void pushCallResults(const FunctionCall& call, ResultType type,
const StackResultsLoc& loc) {
MOZ_MUST_USE bool pushCallResults(const FunctionCall& call, ResultType type,
const StackResultsLoc& loc) {
#if defined(JS_CODEGEN_ARM)
// pushResults currently bypasses special case code in captureReturnedFxx()
// that converts GPR results to FPR results for systemABI+softFP. If we
......@@ -5948,7 +5963,7 @@ class BaseCompiler final : public BaseCompilerInterface {
// registers - but that's OK.
MOZ_ASSERT(!call.usesSystemAbi || call.hardFP);
#endif
pushResults(type, fr.stackResultsBase(loc.bytes()));
return pushResults(type, fr.stackResultsBase(loc.bytes()));
}
//////////////////////////////////////////////////////////////////////
......@@ -7994,9 +8009,13 @@ class BaseCompiler final : public BaseCompilerInterface {
// Lhs "when applicable".
template <typename Cond, typename Lhs, typename Rhs>
void jumpConditionalWithResults(BranchState* b, Cond cond, Lhs lhs, Rhs rhs) {
MOZ_MUST_USE bool jumpConditionalWithResults(BranchState* b, Cond cond,
Lhs lhs, Rhs rhs) {
if (b->hasBlockResults()) {
StackHeight resultsBase = topBranchParams(b->resultType);
StackHeight resultsBase(0);
if (!topBranchParams(b->resultType, &resultsBase)) {
return false;
}
if (b->stackHeight != resultsBase) {
Label notTaken;
branchTo(b->invertBranch ? cond : Assembler::InvertCondition(cond), lhs,
......@@ -8007,12 +8026,13 @@ class BaseCompiler final : public BaseCompilerInterface {
b->resultType);
masm.jump(b->label);
masm.bind(&notTaken);
return;
return true;
}
}
branchTo(b->invertBranch ? Assembler::InvertCondition(cond) : cond, lhs,
rhs, b->label);
return true;
}
// sniffConditionalControl{Cmp,Eqz} may modify the latentWhatever_ state in
......@@ -8022,10 +8042,11 @@ class BaseCompiler final : public BaseCompilerInterface {
// then the compiler MUST instead call resetLatentOp() to reset the state.
template <typename Cond>
bool sniffConditionalControlCmp(Cond compareOp, ValType operandType);
bool sniffConditionalControlEqz(ValType operandType);
MOZ_MUST_USE bool sniffConditionalControlCmp(Cond compareOp,
ValType operandType);
MOZ_MUST_USE bool sniffConditionalControlEqz(ValType operandType);
void emitBranchSetup(BranchState* b);
void emitBranchPerform(BranchState* b);
MOZ_MUST_USE bool emitBranchPerform(BranchState* b);
//////////////////////////////////////////////////////////////////////
......@@ -8085,15 +8106,15 @@ class BaseCompiler final : public BaseCompilerInterface {
template <bool isSetLocal>
MOZ_MUST_USE bool emitSetOrTeeLocal(uint32_t slot);
void endBlock(ResultType type);
void endIfThen(ResultType type);
void endIfThenElse(ResultType type);
MOZ_MUST_USE bool endBlock(ResultType type);
MOZ_MUST_USE bool endIfThen(ResultType type);
MOZ_MUST_USE bool endIfThenElse(ResultType type);
void doReturn(ContinuationKind kind);
void pushReturnValueOfCall(const FunctionCall& call, MIRType type);
bool pushStackResultsForCall(const ResultType& type, RegPtr temp,
StackResultsLoc* loc);
MOZ_MUST_USE bool pushStackResultsForCall(const ResultType& type, RegPtr temp,
StackResultsLoc* loc);
void popStackResultsAfterCall(const StackResultsLoc& results,
uint32_t stackArgBytes);
......@@ -9567,14 +9588,19 @@ void BaseCompiler::emitBranchSetup(BranchState* b) {
}
}
void BaseCompiler::emitBranchPerform(BranchState* b) {
bool BaseCompiler::emitBranchPerform(BranchState* b) {
switch (latentType_.kind()) {
case ValType::I32: {
if (b->i32.rhsImm) {
jumpConditionalWithResults(b, latentIntCmp_, b->i32.lhs,
Imm32(b->i32.imm));
if (!jumpConditionalWithResults(b, latentIntCmp_, b->i32.lhs,
Imm32(b->i32.imm))) {
return false;
}
} else {
jumpConditionalWithResults(b, latentIntCmp_, b->i32.lhs, b->i32.rhs);
if (!jumpConditionalWithResults(b, latentIntCmp_, b->i32.lhs,
b->i32.rhs)) {
return false;
}
freeI32(b->i32.rhs);
}
freeI32(b->i32.lhs);
......@@ -9582,23 +9608,34 @@ void BaseCompiler::emitBranchPerform(BranchState* b) {
}
case ValType::I64: {
if (b->i64.rhsImm) {
jumpConditionalWithResults(b, latentIntCmp_, b->i64.lhs,
Imm64(b->i64.imm));
if (!jumpConditionalWithResults(b, latentIntCmp_, b->i64.lhs,
Imm64(b->i64.imm))) {
return false;
}
} else {
jumpConditionalWithResults(b, latentIntCmp_, b->i64.lhs, b->i64.rhs);
if (!jumpConditionalWithResults(b, latentIntCmp_, b->i64.lhs,
b->i64.rhs)) {
return false;
}
freeI64(b->i64.rhs);
}
freeI64(b->i64.lhs);
break;
}
case ValType::F32: {
jumpConditionalWithResults(b, latentDoubleCmp_, b->f32.lhs, b->f32.rhs);
if (!jumpConditionalWithResults(b, latentDoubleCmp_, b->f32.lhs,
b->f32.rhs)) {
return false;
}
freeF32(b->f32.lhs);
freeF32(b->f32.rhs);
break;
}
case ValType::F64: {
jumpConditionalWithResults(b, latentDoubleCmp_, b->f64.lhs, b->f64.rhs);
if (!jumpConditionalWithResults(b, latentDoubleCmp_, b->f64.lhs,
b->f64.rhs)) {
return false;
}
freeF64(b->f64.lhs);
freeF64(b->f64.rhs);
break;
......@@ -9608,6 +9645,7 @@ void BaseCompiler::emitBranchPerform(BranchState* b) {
}
}
resetLatentOp();
return true;
}
// For blocks and loops and ifs:
......@@ -9638,7 +9676,7 @@ bool BaseCompiler::emitBlock() {
return true;
}
void BaseCompiler::endBlock(ResultType type) {
bool BaseCompiler::endBlock(ResultType type) {
Control& block = controlItem();
if (deadCode_) {
......@@ -9663,10 +9701,14 @@ void BaseCompiler::endBlock(ResultType type) {
captureResultRegisters(type);
deadCode_ = false;
}
pushBlockResults(type);
if (!pushBlockResults(type)) {
return false;
}
}
bceSafe_ = block.bceSafeOnExit;
return true;
}
bool BaseCompiler::emitLoop() {
......@@ -9685,7 +9727,9 @@ bool BaseCompiler::emitLoop() {
if (!deadCode_) {
// Loop entry is a control join, so shuffle the entry parameters into the
// well-known locations.
topBlockParams(params);
if (!topBlockParams(params)) {
return false;
}
masm.nopAlign(CodeAlignment);
masm.bind(&controlItem(0).label);
// The interrupt check barfs if there are live registers.
......@@ -9735,14 +9779,18 @@ bool BaseCompiler::emitIf() {
// Because params can flow immediately to results in the case of an empty
// "then" or "else" block, and the result of an if/then is a join in
// general, we shuffle params eagerly to the result allocations.
topBlockParams(params);
emitBranchPerform(&b);
if (!topBlockParams(params)) {
return false;
}
if (!emitBranchPerform(&b)) {
return false;
}
}
return true;
}
void BaseCompiler::endIfThen(ResultType type) {
bool BaseCompiler::endIfThen(ResultType type) {
Control& ifThen = controlItem();
// The parameters to the "if" logically flow to both the "then" and "else"
......@@ -9779,10 +9827,14 @@ void BaseCompiler::endIfThen(ResultType type) {
deadCode_ = ifThen.deadOnArrival;
if (!deadCode_) {
pushBlockResults(type);
if (!pushBlockResults(type)) {
return false;
}
}
bceSafe_ = ifThen.bceSafeOnExit & ifThen.bceSafeOnEntry;
return true;
}
bool BaseCompiler::emitElse() {
......@@ -9832,13 +9884,15 @@ bool BaseCompiler::emitElse() {
if (!deadCode_) {
captureResultRegisters(params);
pushBlockResults(params);
if (!pushBlockResults(params)) {
return false;
}
}
return true;
}
void BaseCompiler::endIfThenElse(ResultType type) {
bool BaseCompiler::endIfThenElse(ResultType type) {
Control& ifThenElse = controlItem();
// The expression type is not a reliable guide to what we'll find
......@@ -9881,8 +9935,12 @@ void BaseCompiler::endIfThenElse(ResultType type) {
bceSafe_ = ifThenElse.bceSafeOnExit;
if (!deadCode_) {
pushBlockResults(type);
if (!pushBlockResults(type)) {
return false;
}
}
return true;
}
bool BaseCompiler::emitEnd() {
......@@ -9895,23 +9953,31 @@ bool BaseCompiler::emitEnd() {
switch (kind) {
case LabelKind::Body:
endBlock(type);
if (!endBlock(type)) {
return false;
}
doReturn(ContinuationKind::Fallthrough);
iter_.popEnd();
MOZ_ASSERT(iter_.controlStackEmpty());
return iter_.readFunctionEnd(iter_.end());
case LabelKind::Block:
endBlock(type);
if (!endBlock(type)) {
return false;
}
break;
case LabelKind::Loop:
// The end of a loop isn't a branch target, so we can just leave its
// results on the expression stack to be consumed by the outer block.
break;
case LabelKind::Then:
endIfThen(type);
if (!endIfThen(type)) {
return false;
}
break;
case LabelKind::Else:
endIfThenElse(type);
if (!endIfThenElse(type)) {
return false;
}
break;
#ifdef ENABLE_WASM_EXCEPTIONS
case LabelKind::Try:
......@@ -9979,9 +10045,7 @@ bool BaseCompiler::emitBrIf() {
BranchState b(&target.label, target.stackHeight, InvertBranch(false), type);
emitBranchSetup(&b);
emitBranchPerform(&b);
return true;
return emitBranchPerform(&b);
}
#ifdef ENABLE_WASM_FUNCTION_REFERENCES
......@@ -10012,7 +10076,10 @@ bool BaseCompiler::emitBrOnNull() {
if (b.hasBlockResults()) {
freeResultRegisters(b.resultType);
}
jumpConditionalWithResults(&b, Assembler::Equal, rp, ImmWord(NULLREF_VALUE));
if (!jumpConditionalWithResults(&b, Assembler::Equal, rp,
ImmWord(NULLREF_VALUE))) {
return false;
}
pushRef(rp);
return true;
......@@ -10048,7 +10115,10 @@ bool BaseCompiler::emitBrTable() {
freeIntegerResultRegisters(branchParams);
StackHeight resultsBase = topBranchParams(branchParams);
StackHeight resultsBase(0);
if (!topBranchParams(branchParams, &resultsBase)) {
return false;
}
Label dispatchCode;
masm.branch32(Assembler::Below, rc, Imm32(depths.length()), &dispatchCode);
......@@ -10405,9 +10475,7 @@ bool BaseCompiler::emitCall() {
popValueStackBy(numArgs);
captureCallResultRegisters(resultType);
pushCallResults(baselineCall, resultType, results);
return true;
return pushCallResults(baselineCall, resultType, results);
}
bool BaseCompiler::emitCallIndirect() {
......@@ -10462,9 +10530,7 @@ bool BaseCompiler::emitCallIndirect() {
popValueStackBy(numArgs);
captureCallResultRegisters(resultType);
pushCallResults(baselineCall, resultType, results);
return true;
return pushCallResults(baselineCall, resultType, results);
}
void BaseCompiler::emitRound(RoundingMode roundingMode, ValType operandType) {
......@@ -11352,7 +11418,9 @@ bool BaseCompiler::emitSelect(bool typed) {
case ValType::I32: {
RegI32 r, rs;
pop2xI32(&r, &rs);
emitBranchPerform(&b);
if (!emitBranchPerform(&b)) {
return false;
}
moveI32(rs, r);
masm.bind(&done);
freeI32(rs);
......@@ -11372,7 +11440,9 @@ bool BaseCompiler::emitSelect(bool typed) {
// use a double branch and a temporary boolean value for now.
RegI32 temp = needI32();
moveImm32(0, temp);
emitBranchPerform(&b);
if (!emitBranchPerform(&b)) {
return false;
}
moveImm32(1, temp);
masm.bind(&done);
......@@ -11388,7 +11458,9 @@ bool BaseCompiler::emitSelect(bool typed) {
#else
RegI64 r, rs;
pop2xI64(&r, &rs);
emitBranchPerform(&b);
if (!emitBranchPerform(&b)) {
return false;
}
moveI64(rs, r);
masm.bind(&done);
freeI64(rs);
......@@ -11399,7 +11471,9 @@ bool BaseCompiler::emitSelect(bool typed) {
case ValType::F32: {
RegF32 r, rs;
pop2xF32(&r, &rs);
emitBranchPerform(&b);
if (!emitBranchPerform(&b)) {
return false;
}
moveF32(rs, r);
masm.bind(&done);
freeF32(rs);
......@@ -11409,7 +11483,9 @@ bool BaseCompiler::emitSelect(bool typed) {
case ValType::F64: {
RegF64 r, rs;
pop2xF64(&r, &rs);
emitBranchPerform(&b);
if (!emitBranchPerform(&b)) {
return false;
}
moveF64(rs, r);
masm.bind(&done);
freeF64(rs);
......@@ -11420,7 +11496,9 @@ bool BaseCompiler::emitSelect(bool typed) {
case ValType::V128: {
RegV128 r, rs;
pop2xV128(&r, &rs);
emitBranchPerform(&b);
if (!emitBranchPerform(&b)) {
return false;
}
moveV128(rs, r);
masm.bind(&done);
freeV128(rs);
......@@ -11431,7 +11509,9 @@ bool BaseCompiler::emitSelect(bool typed) {
case ValType::Ref: {
RegPtr r, rs;
pop2xRef(&r, &rs);
emitBranchPerform(&b);
if (!emitBranchPerform(&b)) {
return false;
}
moveRef(rs, r);
masm.bind(&done);
freeRef(rs);
......@@ -14048,8 +14128,6 @@ bool BaseCompiler::emitBody() {
initControl(controlItem(), ResultType::Empty());
uint32_t overhead = 0;
for (;;) {
Nothing unused_a, unused_b;
......@@ -14150,25 +14228,7 @@ bool BaseCompiler::emitBody() {
continue; \
}
// TODO / EVALUATE (bug 1316845): Not obvious that this attempt at
// reducing overhead is really paying off relative to making the check
// every iteration.
if (overhead == 0) {
// Check every 50 expressions -- a happy medium between
// memory usage and checking overhead.
overhead = 50;
// Checking every 50 expressions should be safe, as the
// baseline JIT does very little allocation per expression.
CHECK(alloc_.ensureBallast());
// The pushiest opcode is LOOP, which pushes two values
// per instance.
CHECK(stk_.reserve(stk_.length() + overhead * 2));
}
overhead--;
CHECK(stk_.reserve(stk_.length() + MaxPushesPerOpcode));
OpBytes op;
CHECK(iter_.readOp(&op));
......@@ -15609,7 +15669,7 @@ BaseCompiler::BaseCompiler(const ModuleEnvironment& moduleEnv,
iter_(moduleEnv, decoder),
func_(func),
lastReadCallSite_(0),
alloc_(*alloc),
alloc_(alloc->fallible()),
locals_(locals),
deadCode_(false),
bceSafe_(0),
......
......@@ -1447,6 +1447,9 @@ class FunctionCompiler {
}
for (iter.switchToPrev(); !iter.done(); iter.prev()) {
if (!mirGen().ensureBallast()) {
return false;
}
const ABIResult& result = iter.cur();
MInstruction* def;
if (result.inRegister()) {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment