Added fast case for shift operations when the left parameter is a double and we know...
authorricow@chromium.org <ricow@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 15 Mar 2010 14:24:37 +0000 (14:24 +0000)
committerricow@chromium.org <ricow@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 15 Mar 2010 14:24:37 +0000 (14:24 +0000)
Review URL: http://codereview.chromium.org/955001

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4132 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/ia32/codegen-ia32.cc

index 832e773bed7b4ff3845182a595d3d40562ff7592..7841304d7933224bc8accc9e669c1b84431f6309 100644 (file)
@@ -1478,12 +1478,41 @@ Result CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
                                           left->number_info(),
                                           right->number_info(),
                                           overwrite_mode);
-    CheckTwoForSminess(masm_, left->reg(), right->reg(), answer.reg(),
-                       left->number_info(), right->number_info(), deferred);
 
-    // Untag both operands.
-    __ mov(answer.reg(), left->reg());
-    __ SmiUntag(answer.reg());
+    Label do_op, left_nonsmi;
+    // if right is a smi we make a fast case if left is either a smi
+    // or a heapnumber.
+    if (CpuFeatures::IsSupported(SSE2) && right->number_info().IsSmi()) {
+      __ mov(answer.reg(), left->reg());
+      // Fast case - both are actually smis.
+      if (!left->number_info().IsSmi()) {
+        __ 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 we do not fit in a smi.
+      __ cmp(answer.reg(), 0xc0000000);
+      deferred->Branch(negative);
+    } else {
+      CheckTwoForSminess(masm_, left->reg(), right->reg(), answer.reg(),
+                         left->number_info(), right->number_info(), deferred);
+
+      // Untag both operands.
+      __ mov(answer.reg(), left->reg());
+      __ SmiUntag(answer.reg());
+    }
+
     __ SmiUntag(ecx);
     // Perform the operation.
     switch (op) {