| Index: src/x64/macro-assembler-x64.cc
|
| diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
|
| index 96fa4fc49630424093eaa29874c118e95c34a115..6a7ca602a3e8d24f5e9eacbf9a74b705dd2c8f95 100644
|
| --- a/src/x64/macro-assembler-x64.cc
|
| +++ b/src/x64/macro-assembler-x64.cc
|
| @@ -1699,34 +1699,37 @@ void MacroAssembler::SmiAdd(Register dst,
|
| }
|
|
|
|
|
| -void MacroAssembler::SmiSub(Register dst,
|
| - Register src1,
|
| - Register src2,
|
| - Label* on_not_smi_result,
|
| - Label::Distance near_jump) {
|
| - ASSERT_NOT_NULL(on_not_smi_result);
|
| - ASSERT(!dst.is(src2));
|
| +template<class T>
|
| +static void SmiSubHelper(MacroAssembler* masm,
|
| + Register dst,
|
| + Register src1,
|
| + T src2,
|
| + Label* on_not_smi_result,
|
| + Label::Distance near_jump) {
|
| if (dst.is(src1)) {
|
| - cmpq(dst, src2);
|
| - j(overflow, on_not_smi_result, near_jump);
|
| - subq(dst, src2);
|
| + Label done;
|
| + masm->subq(dst, src2);
|
| + masm->j(no_overflow, &done, Label::kNear);
|
| + // Restore src1.
|
| + masm->addq(dst, src2);
|
| + masm->jmp(on_not_smi_result, near_jump);
|
| + masm->bind(&done);
|
| } else {
|
| - movq(dst, src1);
|
| - subq(dst, src2);
|
| - j(overflow, on_not_smi_result, near_jump);
|
| + masm->movq(dst, src1);
|
| + masm->subq(dst, src2);
|
| + masm->j(overflow, on_not_smi_result, near_jump);
|
| }
|
| }
|
|
|
|
|
| -void MacroAssembler::SmiSub(Register dst, Register src1, Register src2) {
|
| - // No overflow checking. Use only when it's known that
|
| - // overflowing is impossible (e.g., subtracting two positive smis).
|
| +void MacroAssembler::SmiSub(Register dst,
|
| + Register src1,
|
| + Register src2,
|
| + Label* on_not_smi_result,
|
| + Label::Distance near_jump) {
|
| + ASSERT_NOT_NULL(on_not_smi_result);
|
| ASSERT(!dst.is(src2));
|
| - if (!dst.is(src1)) {
|
| - movq(dst, src1);
|
| - }
|
| - subq(dst, src2);
|
| - Assert(no_overflow, kSmiSubtractionOverflow);
|
| + SmiSubHelper<Register>(this, dst, src1, src2, on_not_smi_result, near_jump);
|
| }
|
|
|
|
|
| @@ -1736,29 +1739,36 @@ void MacroAssembler::SmiSub(Register dst,
|
| Label* on_not_smi_result,
|
| Label::Distance near_jump) {
|
| ASSERT_NOT_NULL(on_not_smi_result);
|
| - if (dst.is(src1)) {
|
| - movq(kScratchRegister, src2);
|
| - cmpq(src1, kScratchRegister);
|
| - j(overflow, on_not_smi_result, near_jump);
|
| - subq(src1, kScratchRegister);
|
| - } else {
|
| - movq(dst, src1);
|
| - subq(dst, src2);
|
| - j(overflow, on_not_smi_result, near_jump);
|
| - }
|
| + ASSERT(!src2.AddressUsesRegister(dst));
|
| + SmiSubHelper<Operand>(this, dst, src1, src2, on_not_smi_result, near_jump);
|
| }
|
|
|
|
|
| -void MacroAssembler::SmiSub(Register dst,
|
| - Register src1,
|
| - const Operand& src2) {
|
| +template<class T>
|
| +static void SmiSubNoOverflowHelper(MacroAssembler* masm,
|
| + Register dst,
|
| + Register src1,
|
| + T src2) {
|
| // No overflow checking. Use only when it's known that
|
| // overflowing is impossible (e.g., subtracting two positive smis).
|
| if (!dst.is(src1)) {
|
| - movq(dst, src1);
|
| + masm->movq(dst, src1);
|
| }
|
| - subq(dst, src2);
|
| - Assert(no_overflow, kSmiSubtractionOverflow);
|
| + masm->subq(dst, src2);
|
| + masm->Assert(no_overflow, kSmiSubtractionOverflow);
|
| +}
|
| +
|
| +
|
| +void MacroAssembler::SmiSub(Register dst, Register src1, Register src2) {
|
| + ASSERT(!dst.is(src2));
|
| + SmiSubNoOverflowHelper<Register>(this, dst, src1, src2);
|
| +}
|
| +
|
| +
|
| +void MacroAssembler::SmiSub(Register dst,
|
| + Register src1,
|
| + const Operand& src2) {
|
| + SmiSubNoOverflowHelper<Operand>(this, dst, src1, src2);
|
| }
|
|
|
|
|
|
|