Reviewers: Lasse Reichstein,

Description:
Added fast case for shift operations when the left parameter is a double and we
know that the right parameter is a smi.

Please review this at http://codereview.chromium.org/955001

SVN Base: http://v8.googlecode.com/svn/branches/bleeding_edge/

Affected files:
  M     src/ia32/codegen-ia32.cc


Index: src/ia32/codegen-ia32.cc
===================================================================
--- src/ia32/codegen-ia32.cc    (revision 4124)
+++ src/ia32/codegen-ia32.cc    (working copy)
@@ -1438,6 +1438,90 @@
     return answer;
   }

+  // If we have sse2 and we know that right is a smi we handle both
+  // the smi and heapnumber case for left inline.
+  if ((op == Token::SAR || op == Token::SHR || op == Token::SHL) &&
+      CpuFeatures::IsSupported(SSE2) &&
+      right->number_info().IsSmi()) {
+    CpuFeatures::Scope use_sse2(SSE2);
+    // Move left out of ecx if necessary.
+    if (left->is_register() && left->reg().is(ecx)) {
+      *left = allocator_->Allocate();
+      ASSERT(left->is_valid());
+      __ mov(left->reg(), ecx);
+    }
+    Label left_nonsmi, done_left, do_op;
+    right->ToRegister(ecx);
+    left->ToRegister();
+    ASSERT(left->is_register() && !left->reg().is(ecx));
+    ASSERT(right->is_register() && right->reg().is(ecx));
+    // We will modify right, it must be spilled.
+    frame_->Spill(ecx);
+    answer = allocator_->Allocate();
+
+    DeferredInlineBinaryOperation* deferred =
+      new DeferredInlineBinaryOperation(op,
+                                        answer.reg(),
+                                        left->reg(),
+                                        ecx,
+                                        left->number_info(),
+                                        right->number_info(),
+                                        overwrite_mode);
+    __ mov(answer.reg(), left->reg());
+    // Fast case - both are actually smis.
+    __ test(answer.reg(), Immediate(kSmiTagMask));
+    __ j(not_zero, &left_nonsmi);
+    __ SmiUntag(answer.reg());
+    __ jmp(&do_op);
+
+    __ bind(&left_nonsmi);
+    // Branch if not a heapnumber.
+    __ cmp(FieldOperand(answer.reg(), HeapObject::kMapOffset),
+           Factory::heap_number_map());
+    deferred->Branch(not_equal);
+
+    // Load integer value into answer register using truncation.
+    __ cvttsd2si(answer.reg(),
+                 FieldOperand(answer.reg(), HeapNumber::kValueOffset));
+    // Branch if overflow.
+    __ cmp(answer.reg(), 0x80000000);
+    deferred->Branch(equal);
+
+    __ bind(&do_op);
+    // Since we know that ecx is a smi simply go ahead and untag it.
+    __ SmiUntag(ecx);
+    // Perform the operation - test if result fits in a smi afterwards.
+    switch (op) {
+      case Token::SAR:
+        __ sar_cl(answer.reg());
+        break;
+      case Token::SHR: {
+        __ shr_cl(answer.reg());
+        break;
+      }
+      case Token::SHL: {
+        __ shl_cl(answer.reg());
+        break;
+      }
+      default:
+        UNREACHABLE();
+    }
+
+    // Smi tag ecx in case we need to branch to runtime.
+    __ SmiTag(ecx);
+
+    // Check that the result is in smi-range.
+    __ test(answer.reg(), Immediate(0xc0000000));
+    deferred->Branch(not_zero);
+
+    __ SmiTag(answer.reg());
+    deferred->BindExit();
+    left->Unuse();
+    right->Unuse();
+    ASSERT(answer.is_valid());
+    return answer;
+  }
+
   // Special handling of shift operations because they use fixed
   // registers.
   if (op == Token::SHL || op == Token::SHR || op == Token::SAR) {


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

Reply via email to