Speed up conversion of untagged int32 result if we know it must be a smi.
authorwhesse@chromium.org <whesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 25 Mar 2010 13:22:37 +0000 (13:22 +0000)
committerwhesse@chromium.org <whesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 25 Mar 2010 13:22:37 +0000 (13:22 +0000)
Review URL: http://codereview.chromium.org/1233003

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

src/ast.cc
src/ast.h
src/ia32/codegen-ia32.cc
src/ia32/codegen-ia32.h

index 7d26cd9..9204a84 100644 (file)
@@ -172,6 +172,72 @@ void TargetCollector::AddTarget(BreakTarget* target) {
 }
 
 
+bool Expression::GuaranteedSmiResult() {
+  BinaryOperation* node = AsBinaryOperation();
+  if (node == NULL) return false;
+  Token::Value op = node->op();
+  switch (op) {
+    case Token::COMMA:
+    case Token::OR:
+    case Token::AND:
+    case Token::ADD:
+    case Token::SUB:
+    case Token::MUL:
+    case Token::DIV:
+    case Token::MOD:
+    case Token::BIT_XOR:
+    case Token::SHL:
+      return false;
+      break;
+    case Token::BIT_OR:
+    case Token::BIT_AND: {
+      Literal* left = node->left()->AsLiteral();
+      Literal* right = node->right()->AsLiteral();
+      if (left != NULL && left->handle()->IsSmi()) {
+        int value = Smi::cast(*left->handle())->value();
+        if (op == Token::BIT_OR && ((value & 0xc0000000) == 0xc0000000)) {
+          // Result of bitwise or is always a negative Smi.
+          return true;
+        }
+        if (op == Token::BIT_AND && ((value & 0xc0000000) == 0)) {
+          // Result of bitwise and is always a positive Smi.
+          return true;
+        }
+      }
+      if (right != NULL && right->handle()->IsSmi()) {
+        int value = Smi::cast(*right->handle())->value();
+        if (op == Token::BIT_OR && ((value & 0xc0000000) == 0xc0000000)) {
+          // Result of bitwise or is always a negative Smi.
+          return true;
+        }
+        if (op == Token::BIT_AND && ((value & 0xc0000000) == 0)) {
+          // Result of bitwise and is always a positive Smi.
+          return true;
+        }
+      }
+      return false;
+      break;
+    }
+    case Token::SAR:
+    case Token::SHR: {
+      Literal* right = node->right()->AsLiteral();
+       if (right != NULL && right->handle()->IsSmi()) {
+        int value = Smi::cast(*right->handle())->value();
+        if ((value & 0x1F) > 1 ||
+            (op == Token::SAR && (value & 0x1F) == 1)) {
+          return true;
+        }
+       }
+       return false;
+       break;
+    }
+    default:
+      UNREACHABLE();
+      break;
+  }
+  return false;
+}
+
 // ----------------------------------------------------------------------------
 // Implementation of AstVisitor
 
index d153f98..fa85eee 100644 (file)
--- a/src/ast.h
+++ b/src/ast.h
@@ -255,6 +255,10 @@ class Expression: public AstNode {
         LoopConditionField::encode(flag);
   }
 
+  // The value of the expression is guaranteed to be a smi, because the
+  // top operation is a bit operation with a mask, or a shift.
+  bool GuaranteedSmiResult();
+
   // AST analysis results
 
   // True if the expression rooted at this node can be compiled by the
index 1181e22..d88c610 100644 (file)
@@ -490,7 +490,11 @@ void CodeGenerator::LoadInSafeInt32Mode(Expression* expr,
   Load(expr);
   Result value = frame_->Pop();
   ASSERT(frame_->HasNoUntaggedInt32Elements());
-  ConvertInt32ResultToNumber(&value);
+  if (expr->GuaranteedSmiResult()) {
+    ConvertInt32ResultToSmi(&value);
+  } else {
+    ConvertInt32ResultToNumber(&value);
+  }
   set_in_safe_int32_mode(false);
   set_unsafe_bailout(NULL);
   frame_->Push(&value);
@@ -504,6 +508,19 @@ void CodeGenerator::LoadWithSafeInt32ModeDisabled(Expression* expr) {
 }
 
 
+void CodeGenerator::ConvertInt32ResultToSmi(Result* value) {
+  ASSERT(value->is_untagged_int32());
+  if (value->is_register()) {
+    __ add(value->reg(), Operand(value->reg()));
+  } else {
+    ASSERT(value->is_constant());
+    ASSERT(value->handle()->IsSmi());
+  }
+  value->set_untagged_int32(false);
+  value->set_number_info(NumberInfo::Smi());
+}
+
+
 void CodeGenerator::ConvertInt32ResultToNumber(Result* value) {
   ASSERT(value->is_untagged_int32());
   if (value->is_register()) {
@@ -552,6 +569,7 @@ void CodeGenerator::ConvertInt32ResultToNumber(Result* value) {
     ASSERT(value->is_constant());
   }
   value->set_untagged_int32(false);
+  value->set_number_info(NumberInfo::Integer32());
 }
 
 
index c4a0777..ca4a44b 100644 (file)
@@ -373,6 +373,7 @@ class CodeGenerator: public AstVisitor {
   // Take the Result that is an untagged int32, and convert it to a tagged
   // Smi or HeapNumber.  Remove the untagged_int32 flag from the result.
   void ConvertInt32ResultToNumber(Result* value);
+  void ConvertInt32ResultToSmi(Result* value);
 
   // Track loop nesting level.
   int loop_nesting() const { return loop_nesting_; }