Bug 898461 - IonMonkey: Move div and mod overflow and divide-by-zero handling code out of line. r=jandem

This commit is contained in:
Dan Gohman 2013-07-29 16:22:46 -07:00
Родитель 407c5d4f16
Коммит 05e5a806ab
2 изменённых файлов: 107 добавлений и 30 удалений

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

@ -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, &notzero);
masm.xorl(output, output);
masm.jmp(&afterDiv);
masm.bind(&notzero);
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, &notzero);
masm.xorl(output, output);
masm.jmp(&done);
masm.bind(&notzero);
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, &notzero);
masm.xorl(edx, edx);
masm.jmp(&done);
masm.bind(&notzero);
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, &notmin);
masm.cmpl(rhs, Imm32(-1));
if (ins->mir()->isTruncated()) {
masm.j(Assembler::NotEqual, &notmin);
masm.xorl(edx, edx);
masm.jmp(&done);
} else {
if (!bailoutIf(Assembler::Equal, ins->snapshot()))
return false;
}
masm.bind(&notmin);
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();
};