Add AST analysis that flags expressions that will have ToInt32 applied to them.
authorwhesse@chromium.org <whesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 8 Mar 2010 15:28:57 +0000 (15:28 +0000)
committerwhesse@chromium.org <whesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 8 Mar 2010 15:28:57 +0000 (15:28 +0000)
Simplify AST analysis of side-effect-free int32 expressions.
Review URL: http://codereview.chromium.org/668256

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

src/ast.h
src/flag-definitions.h
src/rewriter.cc

index 52241c6..5d4f4f7 100644 (file)
--- a/src/ast.h
+++ b/src/ast.h
@@ -237,27 +237,19 @@ class Expression: public AstNode {
   // side-effect free compiler.
   bool side_effect_free() { return SideEffectFreeField::decode(bitfields_); }
   void set_side_effect_free(bool is_side_effect_free) {
-    bitfields_ = (bitfields_ & ~SideEffectFreeField::mask()) |
-                 SideEffectFreeField::encode(is_side_effect_free);
+    bitfields_ &= ~SideEffectFreeField::mask();
+    bitfields_ |= SideEffectFreeField::encode(is_side_effect_free);
   }
 
-  // The number of unary and binary operations contained in the expression
-  // rooted at this node.  Valid only if side_effect_free() is true.
-  int expression_size() { return ExpressionSizeField::decode(bitfields_); }
-  void set_expression_size(int expression_size) {
-    bitfields_ = (bitfields_ & ~ExpressionSizeField::mask()) |
-        ExpressionSizeField::encode(Min(expression_size, ExpressionSizeMax));
+  // Will ToInt32 ECMA 262-3 9.5) or ToUunt32 (ECMA 262-3 9.6)
+  // be applied to the value of this expression?
+  // If so, we may be able to optimize the calculation of the value.
+  bool to_int32() { return ToInt32Field::decode(bitfields_); }
+  void set_to_int32(bool to_int32) {
+    bitfields_ &= ~ToInt32Field::mask();
+    bitfields_ |= ToInt32Field::encode(to_int32);
   }
 
-  // The number of expression stack slots needed to compute the expression
-  // rooted at this node.  Does not count the slot needed by the value
-  // computed by this expression. Valid only if side_effect_free() is true.
-  int stack_height() { return StackHeightField::decode(bitfields_); }
-  void set_stack_height(int stack_height) {
-    bitfields_ &= ~StackHeightField::mask();
-    bitfields_ |=
-        StackHeightField::encode(Min(stack_height, StackHeightMax));
-  }
 
  private:
   uint32_t bitfields_;
@@ -266,30 +258,9 @@ class Expression: public AstNode {
   DefinitionInfo* def_;
   ZoneList<DefinitionInfo*>* defined_vars_;
 
-  static const int SideEffectFreeFieldStart = 0;
-  static const int SideEffectFreeFieldLength = 1;
-  class SideEffectFreeField: public BitField<bool,
-                                             SideEffectFreeFieldStart,
-                                             SideEffectFreeFieldLength> {
-  };
-
-  static const int ExpressionSizeFieldStart =
-      SideEffectFreeFieldStart + SideEffectFreeFieldLength;
-  static const int ExpressionSizeFieldLength = 5;
-  static const int ExpressionSizeMax = (1 << ExpressionSizeFieldLength) - 1;
-  class ExpressionSizeField: public BitField<int,
-                                             ExpressionSizeFieldStart,
-                                             ExpressionSizeFieldLength> {
-  };
-
-  static const int StackHeightFieldStart =
-      ExpressionSizeFieldStart + ExpressionSizeFieldLength;
-  static const int StackHeightFieldLength = 5;
-  static const int StackHeightMax = (1 << StackHeightFieldLength) - 1;
-  class StackHeightField: public BitField<int,
-                                          StackHeightFieldStart,
-                                          StackHeightFieldLength> {
-  };
+  // Using template BitField<type, start, size>.
+  class SideEffectFreeField : public BitField<bool, 0, 1> {};
+  class ToInt32Field : public BitField<bool, 1, 1> {};
 };
 
 
index 4b02cdf..573d893 100644 (file)
@@ -153,6 +153,8 @@ DEFINE_bool(always_fast_compiler, false,
             "try to use the speculative optimizing backend for all code")
 DEFINE_bool(trace_bailout, false,
             "print reasons for falling back to using the classic V8 backend")
+DEFINE_bool(safe_int32_compiler, false,
+            "enable optimized side-effect-free int32 expressions.")
 DEFINE_bool(use_flow_graph, false, "perform flow-graph based optimizations")
 
 // compilation-cache.cc
index 4ff78c0..15f1ca5 100644 (file)
@@ -245,12 +245,13 @@ void AstOptimizer::VisitVariableProxy(VariableProxy* node) {
       func_name_inferrer_.PushName(var->name());
     }
 
-    if (var->slot() != NULL) {
+    if (FLAG_safe_int32_compiler) {
       Slot* slot = var->slot();
-      node->set_side_effect_free(
-          (slot->type() == Slot::LOCAL  && !slot->is_arguments()) ||
-          slot->type() == Slot::PARAMETER);
-      // stack_height and expression_size remain 0.
+      if (slot != NULL) {
+        node->set_side_effect_free(
+            (slot->type() == Slot::LOCAL  && !slot->is_arguments()) ||
+            slot->type() == Slot::PARAMETER);
+      }
     }
   }
 }
@@ -261,7 +262,6 @@ void AstOptimizer::VisitLiteral(Literal* node) {
   if (literal->IsSmi()) {
     node->type()->SetAsLikelySmi();
     node->set_side_effect_free(true);
-    // stack_height and expression_size remain 0.
   } else if (literal->IsString()) {
     Handle<String> lit_str(Handle<String>::cast(literal));
     if (!Heap::prototype_symbol()->Equals(*lit_str)) {
@@ -269,7 +269,6 @@ void AstOptimizer::VisitLiteral(Literal* node) {
     }
   } else if (literal->IsHeapNumber()) {
     node->set_side_effect_free(true);
-    // stack_height and expression_size remain 0.
   }
 }
 
@@ -427,22 +426,26 @@ void AstOptimizer::VisitCallRuntime(CallRuntime* node) {
 
 void AstOptimizer::VisitUnaryOperation(UnaryOperation* node) {
   Visit(node->expression());
-  switch (node->op()) {
-    case Token::ADD:
-    case Token::SUB:
-      node->set_side_effect_free(node->expression()->side_effect_free());
-      node->set_expression_size(node->expression()->expression_size() + 1);
-      node->set_stack_height(node->expression()->stack_height());
-      break;
-    case Token::DELETE:
-    case Token::TYPEOF:
-    case Token::VOID:
-    case Token::BIT_NOT:
-    case Token::NOT:
-      break;
-    default:
-      UNREACHABLE();
-      break;
+  if (FLAG_safe_int32_compiler) {
+    switch (node->op()) {
+      case Token::BIT_NOT:
+        node->expression()->set_to_int32(true);
+        // Fall through.
+      case Token::ADD:
+      case Token::SUB:
+      case Token::NOT:
+        node->set_side_effect_free(node->expression()->side_effect_free());
+        break;
+      case Token::DELETE:
+      case Token::TYPEOF:
+      case Token::VOID:
+        break;
+      default:
+        UNREACHABLE();
+        break;
+    }
+  } else if (node->op() == Token::BIT_NOT) {
+    node->expression()->set_to_int32(true);
   }
 }
 
@@ -472,6 +475,8 @@ void AstOptimizer::VisitBinaryOperation(BinaryOperation* node) {
       node->type()->SetAsLikelySmiIfUnknown();
       node->left()->type()->SetAsLikelySmiIfUnknown();
       node->right()->type()->SetAsLikelySmiIfUnknown();
+      node->left()->set_to_int32(true);
+      node->right()->set_to_int32(true);
       break;
     case Token::ADD:
     case Token::SUB:
@@ -513,32 +518,31 @@ void AstOptimizer::VisitBinaryOperation(BinaryOperation* node) {
       }
     }
   }
-  switch (node->op()) {
-    case Token::COMMA:
-    case Token::OR:
-    case Token::AND:
-    case Token::BIT_OR:
-    case Token::BIT_XOR:
-    case Token::BIT_AND:
-    case Token::SHL:
-    case Token::SAR:
-    case Token::SHR:
-    case Token::MOD:
-      break;
-    case Token::ADD:
-    case Token::SUB:
-    case Token::MUL:
-    case Token::DIV:
-      node->set_side_effect_free(node->left()->side_effect_free() &&
-                                 node->right()->side_effect_free());
-      node->set_expression_size(node->left()->expression_size() +
-                                node->right()->expression_size() + 1);
-      node->set_stack_height(Max(node->left()->stack_height(),
-                                 node->right()->stack_height() + 1));
-      break;
-    default:
-      UNREACHABLE();
-      break;
+
+  if (FLAG_safe_int32_compiler) {
+    switch (node->op()) {
+      case Token::COMMA:
+      case Token::OR:
+      case Token::AND:
+        break;
+      case Token::BIT_OR:
+      case Token::BIT_XOR:
+      case Token::BIT_AND:
+      case Token::SHL:
+      case Token::SAR:
+      case Token::SHR:
+      case Token::ADD:
+      case Token::SUB:
+      case Token::MUL:
+      case Token::DIV:
+      case Token::MOD:
+        node->set_side_effect_free(node->left()->side_effect_free() &&
+                                   node->right()->side_effect_free());
+        break;
+      default:
+        UNREACHABLE();
+        break;
+    }
   }
 }