diff --git a/js/src/ion/shared/CodeGenerator-x86-shared.cpp b/js/src/ion/shared/CodeGenerator-x86-shared.cpp index 538fb60bdcaa..ad22741b741a 100644 --- a/js/src/ion/shared/CodeGenerator-x86-shared.cpp +++ b/js/src/ion/shared/CodeGenerator-x86-shared.cpp @@ -651,6 +651,31 @@ CodeGeneratorX86Shared::visitMulI(LMulI *ins) return true; } +class ReturnZero : public OutOfLineCodeBase +{ + 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 +{ + 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; } diff --git a/js/src/ion/shared/CodeGenerator-x86-shared.h b/js/src/ion/shared/CodeGenerator-x86-shared.h index 01f8f88e9c12..c1cecc8ee39f 100644 --- a/js/src/ion/shared/CodeGenerator-x86-shared.h +++ b/js/src/ion/shared/CodeGenerator-x86-shared.h @@ -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(); };