зеркало из https://github.com/mozilla/gecko-dev.git
Bug 898461 - IonMonkey: Move div and mod overflow and divide-by-zero handling code out of line. r=jandem
This commit is contained in:
Родитель
407c5d4f16
Коммит
05e5a806ab
|
@ -651,6 +651,31 @@ CodeGeneratorX86Shared::visitMulI(LMulI *ins)
|
|||
return true;
|
||||
}
|
||||
|
||||
class ReturnZero : public OutOfLineCodeBase<CodeGeneratorX86Shared>
|
||||
{
|
||||
Register reg_;
|
||||
|
||||
public:
|
||||
explicit ReturnZero(Register reg)
|
||||
: reg_(reg)
|
||||
{ }
|
||||
|
||||
virtual bool accept(CodeGeneratorX86Shared *codegen) {
|
||||
return codegen->visitReturnZero(this);
|
||||
}
|
||||
Register reg() const {
|
||||
return reg_;
|
||||
}
|
||||
};
|
||||
|
||||
bool
|
||||
CodeGeneratorX86Shared::visitReturnZero(ReturnZero *ool)
|
||||
{
|
||||
masm.xorl(ool->reg(), ool->reg());
|
||||
masm.jmp(ool->rejoin());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGeneratorX86Shared::visitUDivOrMod(LUDivOrMod *ins)
|
||||
{
|
||||
|
@ -660,19 +685,17 @@ CodeGeneratorX86Shared::visitUDivOrMod(LUDivOrMod *ins)
|
|||
|
||||
JS_ASSERT_IF(output == eax, ToRegister(ins->remainder()) == edx);
|
||||
|
||||
Label afterDiv;
|
||||
|
||||
masm.testl(rhs, rhs);
|
||||
Label notzero;
|
||||
masm.j(Assembler::NonZero, ¬zero);
|
||||
masm.xorl(output, output);
|
||||
masm.jmp(&afterDiv);
|
||||
masm.bind(¬zero);
|
||||
|
||||
ReturnZero *ool = new ReturnZero(output);
|
||||
masm.j(Assembler::Zero, ool->entry());
|
||||
if (!addOutOfLineCode(ool))
|
||||
return false;
|
||||
|
||||
masm.xorl(edx, edx);
|
||||
masm.udiv(rhs);
|
||||
|
||||
masm.bind(&afterDiv);
|
||||
masm.bind(ool->rejoin());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -750,17 +773,16 @@ CodeGeneratorX86Shared::visitDivI(LDivI *ins)
|
|||
JS_ASSERT(output == eax);
|
||||
|
||||
Label done;
|
||||
ReturnZero *ool = NULL;
|
||||
|
||||
// Handle divide by zero.
|
||||
if (mir->canBeDivideByZero()) {
|
||||
masm.testl(rhs, rhs);
|
||||
if (mir->isTruncated()) {
|
||||
// Truncated division by zero is zero (Infinity|0 == 0)
|
||||
Label notzero;
|
||||
masm.j(Assembler::NonZero, ¬zero);
|
||||
masm.xorl(output, output);
|
||||
masm.jmp(&done);
|
||||
masm.bind(¬zero);
|
||||
if (!ool)
|
||||
ool = new ReturnZero(output);
|
||||
masm.j(Assembler::Zero, ool->entry());
|
||||
} else {
|
||||
JS_ASSERT(mir->fallible());
|
||||
if (!bailoutIf(Assembler::Zero, ins->snapshot()))
|
||||
|
@ -810,6 +832,12 @@ CodeGeneratorX86Shared::visitDivI(LDivI *ins)
|
|||
|
||||
masm.bind(&done);
|
||||
|
||||
if (ool) {
|
||||
if (!addOutOfLineCode(ool))
|
||||
return false;
|
||||
masm.bind(ool->rejoin());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -843,6 +871,47 @@ CodeGeneratorX86Shared::visitModPowTwoI(LModPowTwoI *ins)
|
|||
|
||||
}
|
||||
|
||||
class ModOverflowCheck : public OutOfLineCodeBase<CodeGeneratorX86Shared>
|
||||
{
|
||||
Label done_;
|
||||
LModI *ins_;
|
||||
Register rhs_;
|
||||
|
||||
public:
|
||||
explicit ModOverflowCheck(LModI *ins, Register rhs)
|
||||
: ins_(ins), rhs_(rhs)
|
||||
{ }
|
||||
|
||||
virtual bool accept(CodeGeneratorX86Shared *codegen) {
|
||||
return codegen->visitModOverflowCheck(this);
|
||||
}
|
||||
Label *done() {
|
||||
return &done_;
|
||||
}
|
||||
LModI *ins() const {
|
||||
return ins_;
|
||||
}
|
||||
Register rhs() const {
|
||||
return rhs_;
|
||||
}
|
||||
};
|
||||
|
||||
bool
|
||||
CodeGeneratorX86Shared::visitModOverflowCheck(ModOverflowCheck *ool)
|
||||
{
|
||||
masm.cmpl(ool->rhs(), Imm32(-1));
|
||||
if (ool->ins()->mir()->isTruncated()) {
|
||||
masm.j(Assembler::NotEqual, ool->rejoin());
|
||||
masm.xorl(edx, edx);
|
||||
masm.jmp(ool->done());
|
||||
} else {
|
||||
if (!bailoutIf(Assembler::Equal, ool->ins()->snapshot()))
|
||||
return false;
|
||||
masm.jmp(ool->rejoin());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGeneratorX86Shared::visitModI(LModI *ins)
|
||||
{
|
||||
|
@ -861,16 +930,16 @@ CodeGeneratorX86Shared::visitModI(LModI *ins)
|
|||
}
|
||||
|
||||
Label done;
|
||||
ReturnZero *ool = NULL;
|
||||
ModOverflowCheck *overflow = NULL;
|
||||
|
||||
// Prevent divide by zero.
|
||||
if (ins->mir()->canBeDivideByZero()) {
|
||||
masm.testl(rhs, rhs);
|
||||
if (ins->mir()->isTruncated()) {
|
||||
Label notzero;
|
||||
masm.j(Assembler::NonZero, ¬zero);
|
||||
masm.xorl(edx, edx);
|
||||
masm.jmp(&done);
|
||||
masm.bind(¬zero);
|
||||
if (!ool)
|
||||
ool = new ReturnZero(edx);
|
||||
masm.j(Assembler::Zero, ool->entry());
|
||||
} else {
|
||||
if (!bailoutIf(Assembler::Zero, ins->snapshot()))
|
||||
return false;
|
||||
|
@ -920,18 +989,9 @@ CodeGeneratorX86Shared::visitModI(LModI *ins)
|
|||
// Prevent an integer overflow exception from -2147483648 % -1
|
||||
Label notmin;
|
||||
masm.cmpl(lhs, Imm32(INT32_MIN));
|
||||
masm.j(Assembler::NotEqual, ¬min);
|
||||
masm.cmpl(rhs, Imm32(-1));
|
||||
if (ins->mir()->isTruncated()) {
|
||||
masm.j(Assembler::NotEqual, ¬min);
|
||||
masm.xorl(edx, edx);
|
||||
masm.jmp(&done);
|
||||
} else {
|
||||
if (!bailoutIf(Assembler::Equal, ins->snapshot()))
|
||||
return false;
|
||||
}
|
||||
masm.bind(¬min);
|
||||
|
||||
overflow = new ModOverflowCheck(ins, rhs);
|
||||
masm.j(Assembler::Equal, overflow->entry());
|
||||
masm.bind(overflow->rejoin());
|
||||
masm.cdq();
|
||||
masm.idiv(rhs);
|
||||
|
||||
|
@ -944,6 +1004,19 @@ CodeGeneratorX86Shared::visitModI(LModI *ins)
|
|||
}
|
||||
|
||||
masm.bind(&done);
|
||||
|
||||
if (overflow) {
|
||||
if (!addOutOfLineCode(overflow))
|
||||
return false;
|
||||
masm.bind(overflow->done());
|
||||
}
|
||||
|
||||
if (ool) {
|
||||
if (!addOutOfLineCode(ool))
|
||||
return false;
|
||||
masm.bind(ool->rejoin());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@ namespace ion {
|
|||
class OutOfLineBailout;
|
||||
class OutOfLineUndoALUOperation;
|
||||
class MulNegativeZeroCheck;
|
||||
class ModOverflowCheck;
|
||||
class ReturnZero;
|
||||
class OutOfLineTableSwitch;
|
||||
|
||||
class CodeGeneratorX86Shared : public CodeGeneratorShared
|
||||
|
@ -118,6 +120,8 @@ class CodeGeneratorX86Shared : public CodeGeneratorShared
|
|||
bool visitOutOfLineBailout(OutOfLineBailout *ool);
|
||||
bool visitOutOfLineUndoALUOperation(OutOfLineUndoALUOperation *ool);
|
||||
bool visitMulNegativeZeroCheck(MulNegativeZeroCheck *ool);
|
||||
bool visitModOverflowCheck(ModOverflowCheck *ool);
|
||||
bool visitReturnZero(ReturnZero *ool);
|
||||
bool visitOutOfLineTableSwitch(OutOfLineTableSwitch *ool);
|
||||
bool generateInvalidateEpilogue();
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче