Revision: 4598
Author: [email protected]
Date: Thu May  6 01:15:15 2010
Log: Correct bug with left shift on X64 platform from change 4571 (http://code.google.com/p/v8/source/detail?r=4571). Speed up left shift with a constant left hand side on X64 platform. Add unit test for this bug. Remove unused failure target argument from MacroAssembler::SmiShiftLeft and MacroAssembler::SmiShiftLeftConstant.
Review URL: http://codereview.chromium.org/1934004
http://code.google.com/p/v8/source/detail?r=4598

Modified:
 /branches/bleeding_edge/src/x64/codegen-x64.cc
 /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/test/mjsunit/smi-ops.js

=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.cc      Wed May  5 01:56:16 2010
+++ /branches/bleeding_edge/src/x64/codegen-x64.cc      Thu May  6 01:15:15 2010
@@ -6526,43 +6526,37 @@

     case Token::SHL:
       if (reversed) {
-        // Move operand into rcx and also into a second register.
-        // If operand is already in a register, take advantage of that.
-        // This lets us modify rcx, but still bail out to deferred code.
-        Result right;
-        Result right_copy_in_rcx;
-        TypeInfo right_type_info = operand->type_info();
         operand->ToRegister();
+
+        // We need rcx to be available to hold operand, and to be spilled.
+        // SmiShiftLeft implicitly modifies rcx.
         if (operand->reg().is(rcx)) {
-          right = allocator()->Allocate();
-          __ movq(right.reg(), rcx);
-          frame_->Spill(rcx);
-          right_copy_in_rcx = *operand;
+          frame_->Spill(operand->reg());
+          answer = allocator()->Allocate();
         } else {
-          right_copy_in_rcx = allocator()->Allocate(rcx);
-          __ movq(rcx, operand->reg());
-          right = *operand;
-        }
-        operand->Unuse();
-
-        answer = allocator()->Allocate();
+          Result rcx_reg = allocator()->Allocate(rcx);
+          // answer must not be rcx.
+          answer = allocator()->Allocate();
+          // rcx_reg goes out of scope.
+        }
+
         DeferredInlineSmiOperationReversed* deferred =
             new DeferredInlineSmiOperationReversed(op,
                                                    answer.reg(),
                                                    smi_value,
-                                                   right.reg(),
+                                                   operand->reg(),
                                                    overwrite_mode);
-        __ movq(answer.reg(), Immediate(int_value));
-        __ SmiToInteger32(rcx, rcx);
-        if (!right_type_info.IsSmi()) {
-          Condition is_smi = masm_->CheckSmi(right.reg());
+        if (!operand->type_info().IsSmi()) {
+          Condition is_smi = masm_->CheckSmi(operand->reg());
           deferred->Branch(NegateCondition(is_smi));
         } else if (FLAG_debug_code) {
-          __ AbortIfNotSmi(right.reg(),
+          __ AbortIfNotSmi(operand->reg(),
"Static type info claims non-smi is smi in (const SHL smi).");
         }
-        __ shl_cl(answer.reg());
-        __ Integer32ToSmi(answer.reg(), answer.reg());
+
+        __ Move(answer.reg(), smi_value);
+        __ SmiShiftLeft(answer.reg(), answer.reg(), operand->reg());
+        operand->Unuse();

         deferred->BindExit();
       } else {
@@ -6595,8 +6589,7 @@
           __ JumpIfNotSmi(operand->reg(), deferred->entry_label());
           __ SmiShiftLeftConstant(answer.reg(),
                                   operand->reg(),
-                                  shift_value,
-                                  deferred->entry_label());
+                                  shift_value);
           deferred->BindExit();
           operand->Unuse();
         }
@@ -6837,8 +6830,7 @@
       case Token::SHL: {
         __ SmiShiftLeft(answer.reg(),
                         left->reg(),
-                        rcx,
-                        deferred->entry_label());
+                        rcx);
         break;
       }
       default:
@@ -9934,7 +9926,7 @@
           __ SmiShiftLogicalRight(left, left, right, slow);
           break;
         case Token::SHL:
-          __ SmiShiftLeft(left, left, right, slow);
+          __ SmiShiftLeft(left, left, right);
           break;
         default:
           UNREACHABLE();
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Tue May 4 07:49:50 2010 +++ /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Thu May 6 01:15:15 2010
@@ -1227,8 +1227,7 @@

 void MacroAssembler::SmiShiftLeftConstant(Register dst,
                                           Register src,
-                                          int shift_value,
-                                          Label* on_not_smi_result) {
+                                          int shift_value) {
   if (!dst.is(src)) {
     movq(dst, src);
   }
@@ -1240,8 +1239,7 @@

 void MacroAssembler::SmiShiftLeft(Register dst,
                                   Register src1,
-                                  Register src2,
-                                  Label* on_not_smi_result) {
+                                  Register src2) {
   ASSERT(!dst.is(rcx));
   Label result_ok;
   // Untag shift amount.
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.h Tue May 4 07:49:50 2010 +++ /branches/bleeding_edge/src/x64/macro-assembler-x64.h Thu May 6 01:15:15 2010
@@ -374,8 +374,7 @@

   void SmiShiftLeftConstant(Register dst,
                             Register src,
-                            int shift_value,
-                            Label* on_not_smi_result);
+                            int shift_value);
   void SmiShiftLogicalRightConstant(Register dst,
                                   Register src,
                                   int shift_value,
@@ -388,8 +387,7 @@
   // Uses and clobbers rcx, so dst may not be rcx.
   void SmiShiftLeft(Register dst,
                     Register src1,
-                    Register src2,
-                    Label* on_not_smi_result);
+                    Register src2);
   // Shifts a smi value to the right, shifting in zero bits at the top, and
   // returns the unsigned intepretation of the result if that is a smi.
   // Uses and clobbers rcx, so dst may not be rcx.
=======================================
--- /branches/bleeding_edge/test/cctest/test-macro-assembler-x64.cc Thu Dec 10 09:46:45 2009 +++ /branches/bleeding_edge/test/cctest/test-macro-assembler-x64.cc Thu May 6 01:15:15 2010
@@ -1737,99 +1737,51 @@
     // rax == id + i * 10.
     int shift = shifts[i];
     int result = x << shift;
-    if (Smi::IsValid(result)) {
-      __ Move(r8, Smi::FromInt(result));
-      __ Move(rcx, Smi::FromInt(x));
-      __ SmiShiftLeftConstant(r9, rcx, shift, exit);
-
-      __ incq(rax);
-      __ SmiCompare(r9, r8);
-      __ j(not_equal, exit);
-
-      __ incq(rax);
-      __ Move(rcx, Smi::FromInt(x));
-      __ SmiShiftLeftConstant(rcx, rcx, shift, exit);
-
-      __ incq(rax);
-      __ SmiCompare(rcx, r8);
-      __ j(not_equal, exit);
-
-      __ incq(rax);
-      __ Move(rdx, Smi::FromInt(x));
-      __ Move(rcx, Smi::FromInt(shift));
-      __ SmiShiftLeft(r9, rdx, rcx, exit);
-
-      __ incq(rax);
-      __ SmiCompare(r9, r8);
-      __ j(not_equal, exit);
-
-      __ incq(rax);
-      __ Move(rdx, Smi::FromInt(x));
-      __ Move(r11, Smi::FromInt(shift));
-      __ SmiShiftLeft(r9, rdx, r11, exit);
-
-      __ incq(rax);
-      __ SmiCompare(r9, r8);
-      __ j(not_equal, exit);
-
-      __ incq(rax);
-      __ Move(rdx, Smi::FromInt(x));
-      __ Move(r11, Smi::FromInt(shift));
-      __ SmiShiftLeft(rdx, rdx, r11, exit);
-
-      __ incq(rax);
-      __ SmiCompare(rdx, r8);
-      __ j(not_equal, exit);
-
-      __ incq(rax);
-    } else {
-      // Cannot happen with long smis.
-      Label fail_ok;
-      __ Move(rcx, Smi::FromInt(x));
-      __ movq(r11, rcx);
-      __ SmiShiftLeftConstant(r9, rcx, shift, &fail_ok);
-      __ jmp(exit);
-      __ bind(&fail_ok);
-
-      __ incq(rax);
-      __ SmiCompare(rcx, r11);
-      __ j(not_equal, exit);
-
-      __ incq(rax);
-      Label fail_ok2;
-      __ SmiShiftLeftConstant(rcx, rcx, shift, &fail_ok2);
-      __ jmp(exit);
-      __ bind(&fail_ok2);
-
-      __ incq(rax);
-      __ SmiCompare(rcx, r11);
-      __ j(not_equal, exit);
-
-      __ incq(rax);
-      __ Move(r8, Smi::FromInt(shift));
-      Label fail_ok3;
-      __ SmiShiftLeft(r9, rcx, r8, &fail_ok3);
-      __ jmp(exit);
-      __ bind(&fail_ok3);
-
-      __ incq(rax);
-      __ SmiCompare(rcx, r11);
-      __ j(not_equal, exit);
-
-      __ incq(rax);
-      __ Move(r8, Smi::FromInt(shift));
-      __ movq(rdx, r11);
-      Label fail_ok4;
-      __ SmiShiftLeft(rdx, rdx, r8, &fail_ok4);
-      __ jmp(exit);
-      __ bind(&fail_ok4);
-
-      __ incq(rax);
-      __ SmiCompare(rdx, r11);
-      __ j(not_equal, exit);
-
-      __ addq(rax, Immediate(3));
-    }
+    CHECK(Smi::IsValid(result));
+    __ Move(r8, Smi::FromInt(result));
+    __ Move(rcx, Smi::FromInt(x));
+    __ SmiShiftLeftConstant(r9, rcx, shift);
+
+    __ incq(rax);
+    __ SmiCompare(r9, r8);
+    __ j(not_equal, exit);
+
+    __ incq(rax);
+    __ Move(rcx, Smi::FromInt(x));
+    __ SmiShiftLeftConstant(rcx, rcx, shift);
+
+    __ incq(rax);
+    __ SmiCompare(rcx, r8);
+    __ j(not_equal, exit);
+
+    __ incq(rax);
+    __ Move(rdx, Smi::FromInt(x));
+    __ Move(rcx, Smi::FromInt(shift));
+    __ SmiShiftLeft(r9, rdx, rcx);
+
+    __ incq(rax);
+    __ SmiCompare(r9, r8);
+    __ j(not_equal, exit);
+
+    __ incq(rax);
+    __ Move(rdx, Smi::FromInt(x));
+    __ Move(r11, Smi::FromInt(shift));
+    __ SmiShiftLeft(r9, rdx, r11);
+
+    __ incq(rax);
+    __ SmiCompare(r9, r8);
+    __ j(not_equal, exit);
+
+    __ incq(rax);
+    __ Move(rdx, Smi::FromInt(x));
+    __ Move(r11, Smi::FromInt(shift));
+    __ SmiShiftLeft(rdx, rdx, r11);
+
+    __ incq(rax);
+    __ SmiCompare(rdx, r8);
+    __ j(not_equal, exit);
+
+    __ incq(rax);
   }
 }

=======================================
--- /branches/bleeding_edge/test/mjsunit/smi-ops.js     Thu Apr 22 02:02:10 2010
+++ /branches/bleeding_edge/test/mjsunit/smi-ops.js     Thu May  6 01:15:15 2010
@@ -678,3 +678,10 @@

 assertEquals(4589934592, LogicalShiftRightByMultipleOf32(-2000000000));
 assertEquals(4589934592, LogicalShiftRightByMultipleOf32(-2000000000));
+
+// Verify that the shift amount is reduced modulo 32, not modulo 64.
+function LeftShiftThreeBy(x) {return 3 << x;}
+assertEquals(24, LeftShiftThreeBy(3));
+assertEquals(24, LeftShiftThreeBy(35));
+assertEquals(24, LeftShiftThreeBy(67));
+assertEquals(24, LeftShiftThreeBy(-29));

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to