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,
} else if (dst.is(src)) {
ASSERT(!dst.is(kScratchRegister));
Label done;
LoadSmiConstant(kScratchRegister, constant);
addq(kScratchRegister, src);
j(overflow, on_not_smi_result, near_jump);
movq(dst, kScratchRegister);
addq(dst, kScratchRegister);
j(no_overflow, &done, Label::kNear);
// Restore src.
subq(dst, kScratchRegister);
jmp(on_not_smi_result, near_jump);
bind(&done);
} else {
LoadSmiConstant(dst, constant);
addq(dst, src);
......@@ -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,
Register src1,
Register src2,
......@@ -1612,16 +1639,7 @@ void MacroAssembler::SmiAdd(Register dst,
Label::Distance near_jump) {
ASSERT_NOT_NULL(on_not_smi_result);
ASSERT(!dst.is(src2));
if (dst.is(src1)) {
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);
}
SmiAddHelper<Register>(this, dst, src1, src2, on_not_smi_result, near_jump);
}
......@@ -1631,17 +1649,8 @@ void MacroAssembler::SmiAdd(Register dst,
Label* on_not_smi_result,
Label::Distance near_jump) {
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));
movq(dst, src1);
addq(dst, src2);
j(overflow, on_not_smi_result, near_jump);
}
ASSERT(!src2.AddressUsesRegister(dst));
SmiAddHelper<Operand>(this, dst, src1, src2, on_not_smi_result, near_jump);
}
......
......@@ -569,8 +569,8 @@ class MacroAssembler: public Assembler {
Label::Distance near_jump = Label::kFar);
// Adds smi values and return the result as a smi.
// If dst is src1, then src1 will be destroyed, even if
// the operation is unsuccessful.
// If dst is src1, then src1 will be destroyed if the operation is
// successful, otherwise kept intact.
void SmiAdd(Register dst,
Register src1,
Register src2,
......
......@@ -751,8 +751,6 @@ TEST(SmiNeg) {
}
static void SmiAddTest(MacroAssembler* masm,
Label* exit,
int id,
......@@ -802,13 +800,120 @@ 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) {
v8::internal::V8::Initialize(NULL);
// Allocate an executable page of memory.
size_t actual_size;
byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
&actual_size,
true));
byte* buffer =
static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
&actual_size,
true));
CHECK(buffer);
Isolate* isolate = CcTest::i_isolate();
HandleScope handles(isolate);
......@@ -829,6 +934,14 @@ TEST(SmiAdd) {
SmiAddTest(masm, &exit, 0x70, Smi::kMaxValue, -5);
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.
__ bind(&exit);
ExitCode(masm);
......@@ -886,6 +999,7 @@ static void SmiSubTest(MacroAssembler* masm,
__ j(not_equal, exit);
}
static void SmiSubOverflowTest(MacroAssembler* masm,
Label* exit,
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