Inline mod for integer powers of 2.
authorerik.corry@gmail.com <erik.corry@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 18 Jun 2009 07:33:44 +0000 (07:33 +0000)
committererik.corry@gmail.com <erik.corry@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 18 Jun 2009 07:33:44 +0000 (07:33 +0000)
Review URL: http://codereview.chromium.org/126293

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

src/ia32/codegen-ia32.cc

index 01caa9aae7ee13b37568d142cf2f9a6e0fb2b842..e88443005790ab5e1cdbd31e0f61ceb03069c7b7 100644 (file)
@@ -1387,7 +1387,11 @@ class DeferredInlineSmiOperation: public DeferredCode {
 void DeferredInlineSmiOperation::Generate() {
   __ push(src_);
   __ push(Immediate(value_));
-  GenericBinaryOpStub stub(op_, overwrite_mode_, SMI_CODE_INLINED);
+  // For mod we don't generate all the Smi code inline.
+  GenericBinaryOpStub stub(
+      op_,
+      overwrite_mode_,
+      (op_ == Token::MOD) ? SMI_CODE_IN_STUB : SMI_CODE_INLINED);
   __ CallStub(&stub);
   if (!dst_.is(eax)) __ mov(dst_, eax);
 }
@@ -1772,6 +1776,33 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
       break;
     }
 
+    // Generate inline code for mod of powers of 2 and negative powers of 2.
+    case Token::MOD:
+      if (!reversed &&
+          int_value != 0 &&
+          (IsPowerOf2(int_value) || IsPowerOf2(-int_value))) {
+        operand->ToRegister();
+        frame_->Spill(operand->reg());
+        DeferredCode* deferred = new DeferredInlineSmiOperation(op,
+                                                                operand->reg(),
+                                                                operand->reg(),
+                                                                smi_value,
+                                                                overwrite_mode);
+        // Check for negative or non-Smi left hand side.
+        __ test(operand->reg(), Immediate(kSmiTagMask | 0x80000000));
+        deferred->Branch(not_zero);
+        if (int_value < 0) int_value = -int_value;
+        if (int_value == 1) {
+          __ mov(operand->reg(), Immediate(Smi::FromInt(0)));
+        } else {
+          __ and_(operand->reg(), (int_value << kSmiTagSize) - 1);
+        }
+        deferred->BindExit();
+        frame_->Push(operand);
+        break;
+      }
+      // Fall through if we did not find a power of 2 on the right hand side!
+
     default: {
       Result constant_operand(value);
       if (reversed) {