Revision: 17074
Author: [email protected]
Date: Wed Oct 2 11:46:01 2013 UTC
Log: Tweak SmiAdd for X64
[email protected]
Review URL: https://codereview.chromium.org/24754002
http://code.google.com/p/v8/source/detail?r=17074
Modified:
/branches/bleeding_edge/src/x64/macro-assembler-x64.cc
/branches/bleeding_edge/src/x64/macro-assembler-x64.h
/branches/bleeding_edge/test/cctest/test-macro-assembler-x64.cc
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Tue Oct 1
11:56:42 2013 UTC
+++ /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Wed Oct 2
11:46:01 2013 UTC
@@ -1502,10 +1502,14 @@
} 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);
@@ -1603,6 +1607,29 @@
j(not_equal, on_smi_result, near_jump);
}
}
+
+
+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,
@@ -1612,16 +1639,7 @@
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 @@
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);
}
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.h Tue Oct 1
11:56:42 2013 UTC
+++ /branches/bleeding_edge/src/x64/macro-assembler-x64.h Wed Oct 2
11:46:01 2013 UTC
@@ -569,8 +569,8 @@
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,
=======================================
--- /branches/bleeding_edge/test/cctest/test-macro-assembler-x64.cc Thu Sep
19 09:17:13 2013 UTC
+++ /branches/bleeding_edge/test/cctest/test-macro-assembler-x64.cc Wed
Oct 2 11:46:01 2013 UTC
@@ -749,8 +749,6 @@
int result = FUNCTION_CAST<F0>(buffer)();
CHECK_EQ(0, result);
}
-
-
static void SmiAddTest(MacroAssembler* masm,
@@ -800,15 +798,122 @@
__ cmpq(rcx, r8);
__ j(not_equal, exit);
}
+
+
+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 @@
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);
@@ -885,6 +998,7 @@
__ cmpq(rcx, r8);
__ j(not_equal, exit);
}
+
static void SmiSubOverflowTest(MacroAssembler* masm,
Label* exit,
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.