Commit 7fc8679c authored by haitao.feng@intel.com's avatar haitao.feng@intel.com

Tweak SmiAdd for X64

R=danno@chromium.org

Review URL: https://codereview.chromium.org/24754002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17074 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 908a7dc2
...@@ -1502,10 +1502,14 @@ void MacroAssembler::SmiAddConstant(Register dst, ...@@ -1502,10 +1502,14 @@ void MacroAssembler::SmiAddConstant(Register dst,
} else if (dst.is(src)) { } else if (dst.is(src)) {
ASSERT(!dst.is(kScratchRegister)); ASSERT(!dst.is(kScratchRegister));
Label done;
LoadSmiConstant(kScratchRegister, constant); LoadSmiConstant(kScratchRegister, constant);
addq(kScratchRegister, src); addq(dst, kScratchRegister);
j(overflow, on_not_smi_result, near_jump); j(no_overflow, &done, Label::kNear);
movq(dst, kScratchRegister); // Restore src.
subq(dst, kScratchRegister);
jmp(on_not_smi_result, near_jump);
bind(&done);
} else { } else {
LoadSmiConstant(dst, constant); LoadSmiConstant(dst, constant);
addq(dst, src); addq(dst, src);
...@@ -1605,6 +1609,29 @@ void MacroAssembler::SmiNeg(Register dst, ...@@ -1605,6 +1609,29 @@ void MacroAssembler::SmiNeg(Register dst,
} }
template<class T>
static void SmiAddHelper(MacroAssembler* masm,
Register dst,
Register src1,
T src2,
Label* on_not_smi_result,
Label::Distance near_jump) {
if (dst.is(src1)) {
Label done;
masm->addq(dst, src2);
masm->j(no_overflow, &done, Label::kNear);
// Restore src1.
masm->subq(dst, src2);
masm->jmp(on_not_smi_result, near_jump);
masm->bind(&done);
} else {
masm->movq(dst, src1);
masm->addq(dst, src2);
masm->j(overflow, on_not_smi_result, near_jump);
}
}
void MacroAssembler::SmiAdd(Register dst, void MacroAssembler::SmiAdd(Register dst,
Register src1, Register src1,
Register src2, Register src2,
...@@ -1612,16 +1639,7 @@ void MacroAssembler::SmiAdd(Register dst, ...@@ -1612,16 +1639,7 @@ void MacroAssembler::SmiAdd(Register dst,
Label::Distance near_jump) { Label::Distance near_jump) {
ASSERT_NOT_NULL(on_not_smi_result); ASSERT_NOT_NULL(on_not_smi_result);
ASSERT(!dst.is(src2)); ASSERT(!dst.is(src2));
if (dst.is(src1)) { SmiAddHelper<Register>(this, dst, src1, src2, on_not_smi_result, near_jump);
movq(kScratchRegister, src1);
addq(kScratchRegister, src2);
j(overflow, on_not_smi_result, near_jump);
movq(dst, kScratchRegister);
} else {
movq(dst, src1);
addq(dst, src2);
j(overflow, on_not_smi_result, near_jump);
}
} }
...@@ -1631,17 +1649,8 @@ void MacroAssembler::SmiAdd(Register dst, ...@@ -1631,17 +1649,8 @@ void MacroAssembler::SmiAdd(Register dst,
Label* on_not_smi_result, Label* on_not_smi_result,
Label::Distance near_jump) { Label::Distance near_jump) {
ASSERT_NOT_NULL(on_not_smi_result); ASSERT_NOT_NULL(on_not_smi_result);
if (dst.is(src1)) {
movq(kScratchRegister, src1);
addq(kScratchRegister, src2);
j(overflow, on_not_smi_result, near_jump);
movq(dst, kScratchRegister);
} else {
ASSERT(!src2.AddressUsesRegister(dst)); ASSERT(!src2.AddressUsesRegister(dst));
movq(dst, src1); SmiAddHelper<Operand>(this, dst, src1, src2, on_not_smi_result, near_jump);
addq(dst, src2);
j(overflow, on_not_smi_result, near_jump);
}
} }
......
...@@ -569,8 +569,8 @@ class MacroAssembler: public Assembler { ...@@ -569,8 +569,8 @@ class MacroAssembler: public Assembler {
Label::Distance near_jump = Label::kFar); Label::Distance near_jump = Label::kFar);
// Adds smi values and return the result as a smi. // Adds smi values and return the result as a smi.
// If dst is src1, then src1 will be destroyed, even if // If dst is src1, then src1 will be destroyed if the operation is
// the operation is unsuccessful. // successful, otherwise kept intact.
void SmiAdd(Register dst, void SmiAdd(Register dst,
Register src1, Register src1,
Register src2, Register src2,
......
...@@ -751,8 +751,6 @@ TEST(SmiNeg) { ...@@ -751,8 +751,6 @@ TEST(SmiNeg) {
} }
static void SmiAddTest(MacroAssembler* masm, static void SmiAddTest(MacroAssembler* masm,
Label* exit, Label* exit,
int id, int id,
...@@ -802,11 +800,118 @@ static void SmiAddTest(MacroAssembler* masm, ...@@ -802,11 +800,118 @@ static void SmiAddTest(MacroAssembler* masm,
} }
static void SmiAddOverflowTest(MacroAssembler* masm,
Label* exit,
int id,
int x) {
// Adds a Smi to x so that the addition overflows.
ASSERT(x != 0); // Can't overflow by adding a Smi.
int y_max = (x > 0) ? (Smi::kMaxValue + 0) : (Smi::kMinValue - x - 1);
int y_min = (x > 0) ? (Smi::kMaxValue - x + 1) : (Smi::kMinValue + 0);
__ movl(rax, Immediate(id));
__ Move(rcx, Smi::FromInt(x));
__ movq(r11, rcx); // Store original Smi value of x in r11.
__ Move(rdx, Smi::FromInt(y_min));
{
Label overflow_ok;
__ SmiAdd(r9, rcx, rdx, &overflow_ok);
__ jmp(exit);
__ bind(&overflow_ok);
__ incq(rax);
__ cmpq(rcx, r11);
__ j(not_equal, exit);
}
{
Label overflow_ok;
__ incq(rax);
__ SmiAdd(rcx, rcx, rdx, &overflow_ok);
__ jmp(exit);
__ bind(&overflow_ok);
__ incq(rax);
__ cmpq(rcx, r11);
__ j(not_equal, exit);
}
__ movq(rcx, r11);
{
Label overflow_ok;
__ incq(rax);
__ SmiAddConstant(r9, rcx, Smi::FromInt(y_min), &overflow_ok);
__ jmp(exit);
__ bind(&overflow_ok);
__ incq(rax);
__ cmpq(rcx, r11);
__ j(not_equal, exit);
}
{
Label overflow_ok;
__ incq(rax);
__ SmiAddConstant(rcx, rcx, Smi::FromInt(y_min), &overflow_ok);
__ jmp(exit);
__ bind(&overflow_ok);
__ incq(rax);
__ cmpq(rcx, r11);
__ j(not_equal, exit);
}
__ Move(rdx, Smi::FromInt(y_max));
{
Label overflow_ok;
__ incq(rax);
__ SmiAdd(r9, rcx, rdx, &overflow_ok);
__ jmp(exit);
__ bind(&overflow_ok);
__ incq(rax);
__ cmpq(rcx, r11);
__ j(not_equal, exit);
}
{
Label overflow_ok;
__ incq(rax);
__ SmiAdd(rcx, rcx, rdx, &overflow_ok);
__ jmp(exit);
__ bind(&overflow_ok);
__ incq(rax);
__ cmpq(rcx, r11);
__ j(not_equal, exit);
}
__ movq(rcx, r11);
{
Label overflow_ok;
__ incq(rax);
__ SmiAddConstant(r9, rcx, Smi::FromInt(y_max), &overflow_ok);
__ jmp(exit);
__ bind(&overflow_ok);
__ incq(rax);
__ cmpq(rcx, r11);
__ j(not_equal, exit);
}
{
Label overflow_ok;
__ incq(rax);
__ SmiAddConstant(rcx, rcx, Smi::FromInt(y_max), &overflow_ok);
__ jmp(exit);
__ bind(&overflow_ok);
__ incq(rax);
__ cmpq(rcx, r11);
__ j(not_equal, exit);
}
}
TEST(SmiAdd) { TEST(SmiAdd) {
v8::internal::V8::Initialize(NULL); v8::internal::V8::Initialize(NULL);
// Allocate an executable page of memory. // Allocate an executable page of memory.
size_t actual_size; size_t actual_size;
byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, byte* buffer =
static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
&actual_size, &actual_size,
true)); true));
CHECK(buffer); CHECK(buffer);
...@@ -829,6 +934,14 @@ TEST(SmiAdd) { ...@@ -829,6 +934,14 @@ TEST(SmiAdd) {
SmiAddTest(masm, &exit, 0x70, Smi::kMaxValue, -5); SmiAddTest(masm, &exit, 0x70, Smi::kMaxValue, -5);
SmiAddTest(masm, &exit, 0x80, Smi::kMaxValue, Smi::kMinValue); SmiAddTest(masm, &exit, 0x80, Smi::kMaxValue, Smi::kMinValue);
SmiAddOverflowTest(masm, &exit, 0x90, -1);
SmiAddOverflowTest(masm, &exit, 0xA0, 1);
SmiAddOverflowTest(masm, &exit, 0xB0, 1024);
SmiAddOverflowTest(masm, &exit, 0xC0, Smi::kMaxValue);
SmiAddOverflowTest(masm, &exit, 0xD0, -2);
SmiAddOverflowTest(masm, &exit, 0xE0, -42000);
SmiAddOverflowTest(masm, &exit, 0xF0, Smi::kMinValue);
__ xor_(rax, rax); // Success. __ xor_(rax, rax); // Success.
__ bind(&exit); __ bind(&exit);
ExitCode(masm); ExitCode(masm);
...@@ -886,6 +999,7 @@ static void SmiSubTest(MacroAssembler* masm, ...@@ -886,6 +999,7 @@ static void SmiSubTest(MacroAssembler* masm,
__ j(not_equal, exit); __ j(not_equal, exit);
} }
static void SmiSubOverflowTest(MacroAssembler* masm, static void SmiSubOverflowTest(MacroAssembler* masm,
Label* exit, Label* exit,
int id, int id,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment