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.

Reply via email to