Index: src/x64/macro-assembler-x64.cc |
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc |
index 586e4962ed037e419d286217bb15b154184c0016..9ffc4516dd6fcf0a357114213523e3a4e380ca07 100644 |
--- a/src/x64/macro-assembler-x64.cc |
+++ b/src/x64/macro-assembler-x64.cc |
@@ -1516,7 +1516,8 @@ void MacroAssembler::SmiAddConstant(const Operand& dst, Smi* constant) { |
void MacroAssembler::SmiAddConstant(Register dst, |
Register src, |
Smi* constant, |
- Label* on_not_smi_result, |
+ SmiOperationExecutionMode mode, |
+ Label* bailout_label, |
Label::Distance near_jump) { |
if (constant->value() == 0) { |
if (!dst.is(src)) { |
@@ -1524,19 +1525,32 @@ void MacroAssembler::SmiAddConstant(Register dst, |
} |
} else if (dst.is(src)) { |
ASSERT(!dst.is(kScratchRegister)); |
- |
- Label done; |
LoadSmiConstant(kScratchRegister, constant); |
addq(dst, kScratchRegister); |
- j(no_overflow, &done, Label::kNear); |
- // Restore src. |
- subq(dst, kScratchRegister); |
- jmp(on_not_smi_result, near_jump); |
- bind(&done); |
+ if (mode.Contains(BAILOUT_ON_NO_OVERFLOW)) { |
+ j(no_overflow, bailout_label, near_jump); |
+ ASSERT(mode.Contains(PRESERVE_SOURCE_REGISTER)); |
+ subq(dst, kScratchRegister); |
+ } else if (mode.Contains(BAILOUT_ON_OVERFLOW)) { |
+ if (mode.Contains(PRESERVE_SOURCE_REGISTER)) { |
+ Label done; |
+ j(no_overflow, &done, Label::kNear); |
+ subq(dst, kScratchRegister); |
+ jmp(bailout_label, near_jump); |
+ bind(&done); |
+ } else { |
+ // Bailout if overflow without reserving src. |
+ j(overflow, bailout_label, near_jump); |
+ } |
+ } else { |
+ CHECK(mode.IsEmpty()); |
+ } |
} else { |
+ ASSERT(mode.Contains(PRESERVE_SOURCE_REGISTER)); |
+ ASSERT(mode.Contains(BAILOUT_ON_OVERFLOW)); |
LoadSmiConstant(dst, constant); |
addq(dst, src); |
- j(overflow, on_not_smi_result, near_jump); |
+ j(overflow, bailout_label, near_jump); |
} |
} |
@@ -1568,7 +1582,8 @@ void MacroAssembler::SmiSubConstant(Register dst, Register src, Smi* constant) { |
void MacroAssembler::SmiSubConstant(Register dst, |
Register src, |
Smi* constant, |
- Label* on_not_smi_result, |
+ SmiOperationExecutionMode mode, |
+ Label* bailout_label, |
Label::Distance near_jump) { |
if (constant->value() == 0) { |
if (!dst.is(src)) { |
@@ -1576,35 +1591,40 @@ void MacroAssembler::SmiSubConstant(Register dst, |
} |
} else if (dst.is(src)) { |
ASSERT(!dst.is(kScratchRegister)); |
- 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, near_jump); |
- LoadSmiConstant(kScratchRegister, constant); |
- subq(dst, kScratchRegister); |
+ LoadSmiConstant(kScratchRegister, constant); |
+ subq(dst, kScratchRegister); |
+ if (mode.Contains(BAILOUT_ON_NO_OVERFLOW)) { |
+ j(no_overflow, bailout_label, near_jump); |
+ ASSERT(mode.Contains(PRESERVE_SOURCE_REGISTER)); |
+ addq(dst, kScratchRegister); |
+ } else if (mode.Contains(BAILOUT_ON_OVERFLOW)) { |
+ if (mode.Contains(PRESERVE_SOURCE_REGISTER)) { |
+ Label done; |
+ j(no_overflow, &done, Label::kNear); |
+ addq(dst, kScratchRegister); |
+ jmp(bailout_label, near_jump); |
+ bind(&done); |
+ } else { |
+ // Bailout if overflow without reserving src. |
+ j(overflow, bailout_label, near_jump); |
+ } |
} else { |
- // Subtract by adding the negation. |
- LoadSmiConstant(kScratchRegister, Smi::FromInt(-constant->value())); |
- addq(kScratchRegister, dst); |
- j(overflow, on_not_smi_result, near_jump); |
- movq(dst, kScratchRegister); |
+ CHECK(mode.IsEmpty()); |
} |
} else { |
+ ASSERT(mode.Contains(PRESERVE_SOURCE_REGISTER)); |
+ ASSERT(mode.Contains(BAILOUT_ON_OVERFLOW)); |
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, near_jump); |
- LoadSmiConstant(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); |
+ ASSERT(!dst.is(kScratchRegister)); |
+ movq(dst, src); |
+ LoadSmiConstant(kScratchRegister, constant); |
+ subq(dst, kScratchRegister); |
+ j(overflow, bailout_label, near_jump); |
} else { |
// Subtract by adding the negation. |
LoadSmiConstant(dst, Smi::FromInt(-(constant->value()))); |
addq(dst, src); |
- j(overflow, on_not_smi_result, near_jump); |
+ j(overflow, bailout_label, near_jump); |
} |
} |
} |