Index: src/x64/macro-assembler-x64.cc |
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc |
index 3823cadb54b519f93c9a973302df964d5809bc82..b859264c6e1e2a4d2be2182e699cc405ca94c42f 100644 |
--- a/src/x64/macro-assembler-x64.cc |
+++ b/src/x64/macro-assembler-x64.cc |
@@ -696,15 +696,13 @@ void MacroAssembler::SmiAdd(Register dst, |
movq(dst, src1); |
addq(dst, src2); |
} |
- Assert(no_overflow, "Smi addition onverflow"); |
+ Assert(no_overflow, "Smi addition overflow"); |
} else if (dst.is(src1)) { |
- addq(dst, src2); |
+ movq(kScratchRegister, src1); |
+ addq(kScratchRegister, src2); |
Label smi_result; |
- j(no_overflow, &smi_result); |
- // Restore src1. |
- subq(src1, src2); |
- jmp(on_not_smi_result); |
- bind(&smi_result); |
+ j(overflow, on_not_smi_result); |
+ movq(dst, kScratchRegister); |
} else { |
movq(dst, src1); |
addq(dst, src2); |
@@ -727,15 +725,11 @@ void MacroAssembler::SmiSub(Register dst, |
movq(dst, src1); |
subq(dst, src2); |
} |
- Assert(no_overflow, "Smi substraction onverflow"); |
+ Assert(no_overflow, "Smi subtraction overflow"); |
} else if (dst.is(src1)) { |
+ cmpq(dst, src2); |
+ j(overflow, on_not_smi_result); |
subq(dst, src2); |
- Label smi_result; |
- j(no_overflow, &smi_result); |
- // Restore src1. |
- addq(src1, src2); |
- jmp(on_not_smi_result); |
- bind(&smi_result); |
} else { |
movq(dst, src1); |
subq(dst, src2); |
@@ -757,15 +751,12 @@ void MacroAssembler::SmiSub(Register dst, |
movq(dst, src1); |
subq(dst, src2); |
} |
- Assert(no_overflow, "Smi substraction onverflow"); |
+ Assert(no_overflow, "Smi subtraction overflow"); |
} else if (dst.is(src1)) { |
- subq(dst, src2); |
- Label smi_result; |
- j(no_overflow, &smi_result); |
- // Restore src1. |
- addq(src1, src2); |
- jmp(on_not_smi_result); |
- bind(&smi_result); |
+ movq(kScratchRegister, src1); |
+ subq(kScratchRegister, src2); |
+ j(overflow, on_not_smi_result); |
+ movq(src1, kScratchRegister); |
} else { |
movq(dst, src1); |
subq(dst, src2); |
@@ -883,12 +874,9 @@ void MacroAssembler::SmiAddConstant(Register dst, |
ASSERT(!dst.is(kScratchRegister)); |
Move(kScratchRegister, constant); |
- addq(dst, kScratchRegister); |
- Label result_ok; |
- j(no_overflow, &result_ok); |
- subq(dst, kScratchRegister); |
- jmp(on_not_smi_result); |
- bind(&result_ok); |
+ addq(kScratchRegister, dst); |
+ j(overflow, on_not_smi_result); |
+ movq(dst, kScratchRegister); |
} else { |
Move(dst, constant); |
addq(dst, src); |
@@ -910,10 +898,12 @@ void MacroAssembler::SmiSubConstant(Register dst, Register src, Smi* constant) { |
} else { |
// Subtract by adding the negative, to do it in two operations. |
if (constant->value() == Smi::kMinValue) { |
- Move(kScratchRegister, constant); |
- movq(dst, src); |
- subq(dst, kScratchRegister); |
+ Move(dst, constant); |
+ // Adding and subtracting the min-value gives the same result, it only |
+ // differs on the overflow bit, which we don't check here. |
+ addq(dst, src); |
} else { |
+ // Subtract by adding the negation. |
Move(dst, Smi::FromInt(-constant->value())); |
addq(dst, src); |
} |
@@ -931,21 +921,32 @@ void MacroAssembler::SmiSubConstant(Register dst, |
} |
} else if (dst.is(src)) { |
ASSERT(!dst.is(kScratchRegister)); |
- |
- Move(kScratchRegister, constant); |
- subq(dst, kScratchRegister); |
- Label sub_success; |
- j(no_overflow, &sub_success); |
- addq(src, kScratchRegister); |
- jmp(on_not_smi_result); |
- bind(&sub_success); |
- } else { |
if (constant->value() == Smi::kMinValue) { |
+ // Subtracting min-value from any non-negative value will overflow. |
+ // We test the non-negativeness before doing the subtraction. |
+ testq(src, src); |
+ j(not_sign, on_not_smi_result); |
Move(kScratchRegister, constant); |
- movq(dst, src); |
subq(dst, kScratchRegister); |
+ } else { |
+ // Subtract by adding the negation. |
+ Move(kScratchRegister, Smi::FromInt(-constant->value())); |
+ addq(kScratchRegister, dst); |
j(overflow, on_not_smi_result); |
+ movq(dst, kScratchRegister); |
+ } |
+ } else { |
+ if (constant->value() == Smi::kMinValue) { |
+ // Subtracting min-value from any non-negative value will overflow. |
+ // We test the non-negativeness before doing the subtraction. |
+ testq(src, src); |
+ j(not_sign, on_not_smi_result); |
+ Move(dst, constant); |
+ // Adding and subtracting the min-value gives the same result, it only |
+ // differs on the overflow bit, which we don't check here. |
+ addq(dst, src); |
} else { |
+ // Subtract by adding the negation. |
Move(dst, Smi::FromInt(-(constant->value()))); |
addq(dst, src); |
j(overflow, on_not_smi_result); |