Loop peeling for inner loops.
authorfschneider@chromium.org <fschneider@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 22 Mar 2010 13:21:32 +0000 (13:21 +0000)
committerfschneider@chromium.org <fschneider@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 22 Mar 2010 13:21:32 +0000 (13:21 +0000)
This change adds the option to peel off the first iteration of inner loops.

Loop peeling is off by default and can enabled by a flag. It also requires building a flow graph.

As part of this I added the possibility to clone AST nodes.

Review URL: http://codereview.chromium.org/998001

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

src/ast.cc
src/ast.h
src/compiler.cc
src/data-flow.cc
src/data-flow.h
src/flag-definitions.h
src/parser.cc
src/variables.h

index 9fc4af0..f87f865 100644 (file)
@@ -592,4 +592,388 @@ bool BinaryOperation::IsPrimitive() {
 bool CompareOperation::IsPrimitive() { return true; }
 
 
+// Implementation of a copy visitor. The visitor create a deep copy
+// of ast nodes. Nodes that do not require a deep copy are copied
+// with the default copy constructor.
+
+AstNode::AstNode(AstNode* other) : num_(kNoNumber) {
+  // AST node number should be unique. Assert that we only copy AstNodes
+  // before node numbers are assigned.
+  ASSERT(other->num_ == kNoNumber);
+}
+
+
+Statement::Statement(Statement* other)
+    : AstNode(other), statement_pos_(other->statement_pos_) {}
+
+
+Expression::Expression(Expression* other)
+    : AstNode(other),
+      bitfields_(other->bitfields_),
+      type_(other->type_) {}
+
+
+BreakableStatement::BreakableStatement(BreakableStatement* other)
+    : Statement(other), labels_(other->labels_), type_(other->type_) {}
+
+
+Block::Block(Block* other, ZoneList<Statement*>* statements)
+    : BreakableStatement(other),
+      statements_(statements->length()),
+      is_initializer_block_(other->is_initializer_block_) {
+  statements_.AddAll(*statements);
+}
+
+
+ExpressionStatement::ExpressionStatement(ExpressionStatement* other,
+                                         Expression* expression)
+    : Statement(other), expression_(expression) {}
+
+
+IfStatement::IfStatement(IfStatement* other,
+                         Expression* condition,
+                         Statement* then_statement,
+                         Statement* else_statement)
+    : Statement(other),
+      condition_(condition),
+      then_statement_(then_statement),
+      else_statement_(else_statement) {}
+
+
+EmptyStatement::EmptyStatement(EmptyStatement* other) : Statement(other) {}
+
+
+IterationStatement::IterationStatement(IterationStatement* other,
+                                       Statement* body)
+    : BreakableStatement(other), body_(body) {}
+
+
+ForStatement::ForStatement(ForStatement* other,
+                           Statement* init,
+                           Expression* cond,
+                           Statement* next,
+                           Statement* body)
+    : IterationStatement(other, body),
+      init_(init),
+      cond_(cond),
+      next_(next),
+      may_have_function_literal_(other->may_have_function_literal_),
+      loop_variable_(other->loop_variable_),
+      peel_this_loop_(other->peel_this_loop_) {}
+
+
+Assignment::Assignment(Assignment* other,
+                       Expression* target,
+                       Expression* value)
+    : Expression(other),
+      op_(other->op_),
+      target_(target),
+      value_(value),
+      pos_(other->pos_),
+      block_start_(other->block_start_),
+      block_end_(other->block_end_) {}
+
+
+Property::Property(Property* other, Expression* obj, Expression* key)
+    : Expression(other),
+      obj_(obj),
+      key_(key),
+      pos_(other->pos_),
+      type_(other->type_) {}
+
+
+Call::Call(Call* other,
+           Expression* expression,
+           ZoneList<Expression*>* arguments)
+    : Expression(other),
+      expression_(expression),
+      arguments_(arguments),
+      pos_(other->pos_) {}
+
+
+UnaryOperation::UnaryOperation(UnaryOperation* other, Expression* expression)
+    : Expression(other), op_(other->op_), expression_(expression) {}
+
+
+BinaryOperation::BinaryOperation(BinaryOperation* other,
+                                 Expression* left,
+                                 Expression* right)
+    : Expression(other),
+      op_(other->op_),
+      left_(left),
+      right_(right) {}
+
+
+CountOperation::CountOperation(CountOperation* other, Expression* expression)
+    : Expression(other),
+      is_prefix_(other->is_prefix_),
+      op_(other->op_),
+      expression_(expression) {}
+
+
+CompareOperation::CompareOperation(CompareOperation* other,
+                                   Expression* left,
+                                   Expression* right)
+    : Expression(other),
+      op_(other->op_),
+      left_(left),
+      right_(right),
+      is_for_loop_condition_(other->is_for_loop_condition_) {}
+
+
+Expression* CopyAstVisitor::DeepCopyExpr(Expression* expr) {
+  expr_ = NULL;
+  if (expr != NULL) Visit(expr);
+  return expr_;
+}
+
+
+Statement* CopyAstVisitor::DeepCopyStmt(Statement* stmt) {
+  stmt_ = NULL;
+  if (stmt != NULL) Visit(stmt);
+  return stmt_;
+}
+
+
+ZoneList<Expression*>* CopyAstVisitor::DeepCopyExprList(
+    ZoneList<Expression*>* expressions) {
+  ZoneList<Expression*>* copy =
+      new ZoneList<Expression*>(expressions->length());
+  for (int i = 0; i < expressions->length(); i++) {
+    copy->Add(DeepCopyExpr(expressions->at(i)));
+  }
+  return copy;
+}
+
+
+ZoneList<Statement*>* CopyAstVisitor::DeepCopyStmtList(
+    ZoneList<Statement*>* statements) {
+  ZoneList<Statement*>* copy = new ZoneList<Statement*>(statements->length());
+  for (int i = 0; i < statements->length(); i++) {
+    copy->Add(DeepCopyStmt(statements->at(i)));
+  }
+  return copy;
+}
+
+
+void CopyAstVisitor::VisitBlock(Block* stmt) {
+  stmt_ = new Block(stmt,
+                    DeepCopyStmtList(stmt->statements()));
+}
+
+
+void CopyAstVisitor::VisitExpressionStatement(
+    ExpressionStatement* stmt) {
+  stmt_ = new ExpressionStatement(stmt, DeepCopyExpr(stmt->expression()));
+}
+
+
+void CopyAstVisitor::VisitEmptyStatement(EmptyStatement* stmt) {
+  stmt_ = new EmptyStatement(stmt);
+}
+
+
+void CopyAstVisitor::VisitIfStatement(IfStatement* stmt) {
+  stmt_ = new IfStatement(stmt,
+                          DeepCopyExpr(stmt->condition()),
+                          DeepCopyStmt(stmt->then_statement()),
+                          DeepCopyStmt(stmt->else_statement()));
+}
+
+
+void CopyAstVisitor::VisitContinueStatement(ContinueStatement* stmt) {
+  SetStackOverflow();
+}
+
+
+void CopyAstVisitor::VisitBreakStatement(BreakStatement* stmt) {
+  SetStackOverflow();
+}
+
+
+void CopyAstVisitor::VisitReturnStatement(ReturnStatement* stmt) {
+  SetStackOverflow();
+}
+
+
+void CopyAstVisitor::VisitWithEnterStatement(
+    WithEnterStatement* stmt) {
+  SetStackOverflow();
+}
+
+
+void CopyAstVisitor::VisitWithExitStatement(WithExitStatement* stmt) {
+  SetStackOverflow();
+}
+
+
+void CopyAstVisitor::VisitSwitchStatement(SwitchStatement* stmt) {
+  SetStackOverflow();
+}
+
+
+void CopyAstVisitor::VisitDoWhileStatement(DoWhileStatement* stmt) {
+  SetStackOverflow();
+}
+
+
+void CopyAstVisitor::VisitWhileStatement(WhileStatement* stmt) {
+  SetStackOverflow();
+}
+
+
+void CopyAstVisitor::VisitForStatement(ForStatement* stmt) {
+  stmt_ = new ForStatement(stmt,
+                           DeepCopyStmt(stmt->init()),
+                           DeepCopyExpr(stmt->cond()),
+                           DeepCopyStmt(stmt->next()),
+                           DeepCopyStmt(stmt->body()));
+}
+
+
+void CopyAstVisitor::VisitForInStatement(ForInStatement* stmt) {
+  SetStackOverflow();
+}
+
+
+void CopyAstVisitor::VisitTryCatchStatement(TryCatchStatement* stmt) {
+  SetStackOverflow();
+}
+
+
+void CopyAstVisitor::VisitTryFinallyStatement(
+    TryFinallyStatement* stmt) {
+  SetStackOverflow();
+}
+
+
+void CopyAstVisitor::VisitDebuggerStatement(
+    DebuggerStatement* stmt) {
+  SetStackOverflow();
+}
+
+
+void CopyAstVisitor::VisitFunctionLiteral(FunctionLiteral* expr) {
+  SetStackOverflow();
+}
+
+
+void CopyAstVisitor::VisitFunctionBoilerplateLiteral(
+    FunctionBoilerplateLiteral* expr) {
+  SetStackOverflow();
+}
+
+
+void CopyAstVisitor::VisitConditional(Conditional* expr) {
+  SetStackOverflow();
+}
+
+
+void CopyAstVisitor::VisitSlot(Slot* expr) {
+  UNREACHABLE();
+}
+
+
+void CopyAstVisitor::VisitVariableProxy(VariableProxy* expr) {
+  expr_ = new VariableProxy(*expr);
+}
+
+
+void CopyAstVisitor::VisitLiteral(Literal* expr) {
+  expr_ = new Literal(*expr);
+}
+
+
+void CopyAstVisitor::VisitRegExpLiteral(RegExpLiteral* expr) {
+  SetStackOverflow();
+}
+
+
+void CopyAstVisitor::VisitObjectLiteral(ObjectLiteral* expr) {
+  SetStackOverflow();
+}
+
+
+void CopyAstVisitor::VisitArrayLiteral(ArrayLiteral* expr) {
+  SetStackOverflow();
+}
+
+
+void CopyAstVisitor::VisitCatchExtensionObject(
+    CatchExtensionObject* expr) {
+  SetStackOverflow();
+}
+
+
+void CopyAstVisitor::VisitAssignment(Assignment* expr) {
+  expr_ = new Assignment(expr,
+                         DeepCopyExpr(expr->target()),
+                         DeepCopyExpr(expr->value()));
+}
+
+
+void CopyAstVisitor::VisitThrow(Throw* expr) {
+  SetStackOverflow();
+}
+
+
+void CopyAstVisitor::VisitProperty(Property* expr) {
+  expr_ = new Property(expr,
+                       DeepCopyExpr(expr->obj()),
+                       DeepCopyExpr(expr->key()));
+}
+
+
+void CopyAstVisitor::VisitCall(Call* expr) {
+  expr_ = new Call(expr,
+                   DeepCopyExpr(expr->expression()),
+                   DeepCopyExprList(expr->arguments()));
+}
+
+
+void CopyAstVisitor::VisitCallNew(CallNew* expr) {
+  SetStackOverflow();
+}
+
+
+void CopyAstVisitor::VisitCallRuntime(CallRuntime* expr) {
+  SetStackOverflow();
+}
+
+
+void CopyAstVisitor::VisitUnaryOperation(UnaryOperation* expr) {
+  expr_ = new UnaryOperation(expr, DeepCopyExpr(expr->expression()));
+}
+
+
+void CopyAstVisitor::VisitCountOperation(CountOperation* expr) {
+  expr_ = new CountOperation(expr,
+                             DeepCopyExpr(expr->expression()));
+}
+
+
+void CopyAstVisitor::VisitBinaryOperation(BinaryOperation* expr) {
+  expr_ = new BinaryOperation(expr,
+                              DeepCopyExpr(expr->left()),
+                              DeepCopyExpr(expr->right()));
+}
+
+
+void CopyAstVisitor::VisitCompareOperation(CompareOperation* expr) {
+  expr_ = new CompareOperation(expr,
+                               DeepCopyExpr(expr->left()),
+                               DeepCopyExpr(expr->right()));
+}
+
+
+void CopyAstVisitor::VisitThisFunction(ThisFunction* expr) {
+  SetStackOverflow();
+}
+
+
+void CopyAstVisitor::VisitDeclaration(Declaration* decl) {
+  UNREACHABLE();
+}
+
+
 } }  // namespace v8::internal
index 8248f62..e9d0d61 100644 (file)
--- a/src/ast.h
+++ b/src/ast.h
@@ -121,11 +121,15 @@ class AstNode: public ZoneObject {
   static const int kNoNumber = -1;
 
   AstNode() : num_(kNoNumber) {}
+
+  explicit AstNode(AstNode* other);
+
   virtual ~AstNode() { }
   virtual void Accept(AstVisitor* v) = 0;
 
   // Type testing & conversion.
   virtual Statement* AsStatement() { return NULL; }
+  virtual Block* AsBlock() { return NULL; }
   virtual ExpressionStatement* AsExpressionStatement() { return NULL; }
   virtual EmptyStatement* AsEmptyStatement() { return NULL; }
   virtual Expression* AsExpression() { return NULL; }
@@ -137,6 +141,7 @@ class AstNode: public ZoneObject {
   virtual TargetCollector* AsTargetCollector() { return NULL; }
   virtual BreakableStatement* AsBreakableStatement() { return NULL; }
   virtual IterationStatement* AsIterationStatement() { return NULL; }
+  virtual ForStatement* AsForStatement() { return NULL; }
   virtual UnaryOperation* AsUnaryOperation() { return NULL; }
   virtual CountOperation* AsCountOperation() { return NULL; }
   virtual BinaryOperation* AsBinaryOperation() { return NULL; }
@@ -160,6 +165,8 @@ class Statement: public AstNode {
  public:
   Statement() : statement_pos_(RelocInfo::kNoPosition) {}
 
+  explicit Statement(Statement* other);
+
   virtual Statement* AsStatement()  { return this; }
   virtual ReturnStatement* AsReturnStatement() { return NULL; }
 
@@ -198,6 +205,8 @@ class Expression: public AstNode {
 
   Expression() : bitfields_(0) {}
 
+  explicit Expression(Expression* other);
+
   virtual Expression* AsExpression()  { return this; }
 
   virtual bool IsValidLeftHandSide() { return false; }
@@ -265,7 +274,6 @@ class Expression: public AstNode {
     bitfields_ |= NumBitOpsField::encode(num_bit_ops);
   }
 
-
  private:
   static const int kMaxNumBitOps = (1 << 5) - 1;
 
@@ -327,6 +335,8 @@ class BreakableStatement: public Statement {
     ASSERT(labels == NULL || labels->length() > 0);
   }
 
+  explicit BreakableStatement(BreakableStatement* other);
+
  private:
   ZoneStringList* labels_;
   Type type_;
@@ -341,8 +351,14 @@ class Block: public BreakableStatement {
         statements_(capacity),
         is_initializer_block_(is_initializer_block) { }
 
+  // Construct a clone initialized from the original block and
+  // a deep copy of all statements of the original block.
+  Block(Block* other, ZoneList<Statement*>* statements);
+
   virtual void Accept(AstVisitor* v);
 
+  virtual Block* AsBlock() { return this; }
+
   virtual Assignment* StatementAsSimpleAssignment() {
     if (statements_.length() != 1) return NULL;
     return statements_[0]->StatementAsSimpleAssignment();
@@ -394,6 +410,7 @@ class IterationStatement: public BreakableStatement {
   virtual IterationStatement* AsIterationStatement() { return this; }
 
   Statement* body() const { return body_; }
+  void set_body(Statement* stmt) { body_ = stmt; }
 
   // Code generation
   BreakTarget* continue_target()  { return &continue_target_; }
@@ -402,6 +419,10 @@ class IterationStatement: public BreakableStatement {
   explicit IterationStatement(ZoneStringList* labels)
       : BreakableStatement(labels, TARGET_FOR_ANONYMOUS), body_(NULL) { }
 
+  // Construct a clone initialized from  original and
+  // a deep copy of the original body.
+  IterationStatement(IterationStatement* other, Statement* body);
+
   void Initialize(Statement* body) {
     body_ = body;
   }
@@ -475,7 +496,18 @@ class ForStatement: public IterationStatement {
         cond_(NULL),
         next_(NULL),
         may_have_function_literal_(true),
-        loop_variable_(NULL) {}
+        loop_variable_(NULL),
+        peel_this_loop_(false) {}
+
+  // Construct a for-statement initialized from another for-statement
+  // and deep copies of all parts of the original statement.
+  ForStatement(ForStatement* other,
+               Statement* init,
+               Expression* cond,
+               Statement* next,
+               Statement* body);
+
+  virtual ForStatement* AsForStatement() { return this; }
 
   void Initialize(Statement* init,
                   Expression* cond,
@@ -490,8 +522,11 @@ class ForStatement: public IterationStatement {
   virtual void Accept(AstVisitor* v);
 
   Statement* init() const  { return init_; }
+  void set_init(Statement* stmt) { init_ = stmt; }
   Expression* cond() const  { return cond_; }
+  void set_cond(Expression* expr) { cond_ = expr; }
   Statement* next() const  { return next_; }
+  void set_next(Statement* stmt) { next_ = stmt; }
   bool may_have_function_literal() const {
     return may_have_function_literal_;
   }
@@ -500,6 +535,9 @@ class ForStatement: public IterationStatement {
   Variable* loop_variable() { return loop_variable_; }
   void set_loop_variable(Variable* var) { loop_variable_ = var; }
 
+  bool peel_this_loop() { return peel_this_loop_; }
+  void set_peel_this_loop(bool b) { peel_this_loop_ = b; }
+
  private:
   Statement* init_;
   Expression* cond_;
@@ -507,6 +545,7 @@ class ForStatement: public IterationStatement {
   // True if there is a function literal subexpression in the condition.
   bool may_have_function_literal_;
   Variable* loop_variable_;
+  bool peel_this_loop_;
 
   friend class AstOptimizer;
 };
@@ -539,6 +578,10 @@ class ExpressionStatement: public Statement {
   explicit ExpressionStatement(Expression* expression)
       : expression_(expression) { }
 
+  // Construct an expression statement initialized from another
+  // expression statement and a deep copy of the original expression.
+  ExpressionStatement(ExpressionStatement* other, Expression* expression);
+
   virtual void Accept(AstVisitor* v);
 
   // Type testing & conversion.
@@ -681,6 +724,13 @@ class IfStatement: public Statement {
         then_statement_(then_statement),
         else_statement_(else_statement) { }
 
+  // Construct an if-statement initialized from another if-statement
+  // and deep copies of all parts of the original.
+  IfStatement(IfStatement* other,
+              Expression* condition,
+              Statement* then_statement,
+              Statement* else_statement);
+
   virtual void Accept(AstVisitor* v);
 
   bool HasThenStatement() const { return !then_statement()->IsEmpty(); }
@@ -688,7 +738,9 @@ class IfStatement: public Statement {
 
   Expression* condition() const { return condition_; }
   Statement* then_statement() const { return then_statement_; }
+  void set_then_statement(Statement* stmt) { then_statement_ = stmt; }
   Statement* else_statement() const { return else_statement_; }
+  void set_else_statement(Statement* stmt) { else_statement_ = stmt; }
 
  private:
   Expression* condition_;
@@ -783,6 +835,10 @@ class DebuggerStatement: public Statement {
 
 class EmptyStatement: public Statement {
  public:
+  EmptyStatement() {}
+
+  explicit EmptyStatement(EmptyStatement* other);
+
   virtual void Accept(AstVisitor* v);
 
   // Type testing & conversion.
@@ -1145,6 +1201,8 @@ class Property: public Expression {
   Property(Expression* obj, Expression* key, int pos, Type type = NORMAL)
       : obj_(obj), key_(key), pos_(pos), type_(type) { }
 
+  Property(Property* other, Expression* obj, Expression* key);
+
   virtual void Accept(AstVisitor* v);
 
   // Type testing & conversion
@@ -1179,6 +1237,8 @@ class Call: public Expression {
   Call(Expression* expression, ZoneList<Expression*>* arguments, int pos)
       : expression_(expression), arguments_(arguments), pos_(pos) { }
 
+  Call(Call* other, Expression* expression, ZoneList<Expression*>* arguments);
+
   virtual void Accept(AstVisitor* v);
 
   // Type testing and conversion.
@@ -1255,6 +1315,8 @@ class UnaryOperation: public Expression {
     ASSERT(Token::IsUnaryOp(op));
   }
 
+  UnaryOperation(UnaryOperation* other, Expression* expression);
+
   virtual void Accept(AstVisitor* v);
 
   // Type testing & conversion
@@ -1278,6 +1340,8 @@ class BinaryOperation: public Expression {
     ASSERT(Token::IsBinaryOp(op));
   }
 
+  BinaryOperation(BinaryOperation* other, Expression* left, Expression* right);
+
   virtual void Accept(AstVisitor* v);
 
   // Type testing & conversion
@@ -1329,6 +1393,8 @@ class CountOperation: public Expression {
     ASSERT(Token::IsCountOp(op));
   }
 
+  CountOperation(CountOperation* other, Expression* expression);
+
   virtual void Accept(AstVisitor* v);
 
   virtual CountOperation* AsCountOperation() { return this; }
@@ -1363,6 +1429,10 @@ class CompareOperation: public Expression {
     ASSERT(Token::IsCompareOp(op));
   }
 
+  CompareOperation(CompareOperation* other,
+                   Expression* left,
+                   Expression* right);
+
   virtual void Accept(AstVisitor* v);
 
   virtual bool IsPrimitive();
@@ -1418,6 +1488,8 @@ class Assignment: public Expression {
     ASSERT(Token::IsAssignmentOp(op));
   }
 
+  Assignment(Assignment* other, Expression* target, Expression* value);
+
   virtual void Accept(AstVisitor* v);
   virtual Assignment* AsAssignment() { return this; }
 
@@ -1993,6 +2065,28 @@ class AstVisitor BASE_EMBEDDED {
 };
 
 
+class CopyAstVisitor : public AstVisitor {
+ public:
+  Expression* DeepCopyExpr(Expression* expr);
+
+  Statement* DeepCopyStmt(Statement* stmt);
+
+ private:
+  ZoneList<Expression*>* DeepCopyExprList(ZoneList<Expression*>* expressions);
+
+  ZoneList<Statement*>* DeepCopyStmtList(ZoneList<Statement*>* statements);
+
+  // AST node visit functions.
+#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
+  AST_NODE_LIST(DECLARE_VISIT)
+#undef DECLARE_VISIT
+
+  // Holds the result of copying an expression.
+  Expression* expr_;
+  // Holds the result of copying a statement.
+  Statement* stmt_;
+};
+
 } }  // namespace v8::internal
 
 #endif  // V8_AST_H_
index 11098ba..3cdf1de 100755 (executable)
@@ -105,7 +105,7 @@ static Handle<Code> MakeCode(Handle<Context> context, CompilationInfo* info) {
 
 #ifdef DEBUG
     if (FLAG_print_graph_text && !builder.HasStackOverflow()) {
-      builder.graph()->PrintText(builder.postorder());
+      builder.graph()->PrintText(function, builder.postorder());
     }
 #endif
   }
@@ -513,7 +513,7 @@ Handle<JSFunction> Compiler::BuildBoilerplate(FunctionLiteral* literal,
 
 #ifdef DEBUG
       if (FLAG_print_graph_text && !builder.HasStackOverflow()) {
-        builder.graph()->PrintText(builder.postorder());
+        builder.graph()->PrintText(literal, builder.postorder());
       }
 #endif
     }
index 141718d..bf131f4 100644 (file)
@@ -195,6 +195,81 @@ void FlowGraphBuilder::Build(FunctionLiteral* lit) {
 }
 
 
+// This function peels off one iteration of a for-loop. The return value
+// is either a block statement containing the peeled loop or NULL in case
+// there is a stack overflow.
+static Statement* PeelForLoop(ForStatement* stmt) {
+  // Mark this for-statement as processed.
+  stmt->set_peel_this_loop(false);
+
+  // Create new block containing the init statement of the for-loop and
+  // an if-statement containing the peeled iteration and the original
+  // loop without the init-statement.
+  Block* block = new Block(NULL, 2, false);
+  if (stmt->init() != NULL) {
+    Statement* init = stmt->init();
+    // The init statement gets the statement position of the for-loop
+    // to make debugging of peeled loops possible.
+    init->set_statement_pos(stmt->statement_pos());
+    block->AddStatement(init);
+  }
+
+  // Copy the condition.
+  CopyAstVisitor copy_visitor;
+  Expression* cond_copy = stmt->cond() != NULL
+      ? copy_visitor.DeepCopyExpr(stmt->cond())
+      : new Literal(Factory::true_value());
+  if (copy_visitor.HasStackOverflow()) return NULL;
+
+  // Construct a block with the peeled body and the rest of the for-loop.
+  Statement* body_copy = copy_visitor.DeepCopyStmt(stmt->body());
+  if (copy_visitor.HasStackOverflow()) return NULL;
+
+  Statement* next_copy = stmt->next() != NULL
+      ? copy_visitor.DeepCopyStmt(stmt->next())
+      : new EmptyStatement();
+  if (copy_visitor.HasStackOverflow()) return NULL;
+
+  Block* peeled_body = new Block(NULL, 3, false);
+  peeled_body->AddStatement(body_copy);
+  peeled_body->AddStatement(next_copy);
+  peeled_body->AddStatement(stmt);
+
+  // Remove the duplicated init statement from the for-statement.
+  stmt->set_init(NULL);
+
+  // Create new test at the top and add it to the newly created block.
+  IfStatement* test = new IfStatement(cond_copy,
+                                      peeled_body,
+                                      new EmptyStatement());
+  block->AddStatement(test);
+  return block;
+}
+
+
+void FlowGraphBuilder::VisitStatements(ZoneList<Statement*>* stmts) {
+  for (int i = 0, len = stmts->length(); i < len; i++) {
+    stmts->at(i) = ProcessStatement(stmts->at(i));
+  }
+}
+
+
+Statement* FlowGraphBuilder::ProcessStatement(Statement* stmt) {
+  if (FLAG_loop_peeling &&
+      stmt->AsForStatement() != NULL &&
+      stmt->AsForStatement()->peel_this_loop()) {
+    Statement* tmp_stmt = PeelForLoop(stmt->AsForStatement());
+    if (tmp_stmt == NULL) {
+      SetStackOverflow();
+    } else {
+      stmt = tmp_stmt;
+    }
+  }
+  Visit(stmt);
+  return stmt;
+}
+
+
 void FlowGraphBuilder::VisitDeclaration(Declaration* decl) {
   UNREACHABLE();
 }
@@ -221,11 +296,11 @@ void FlowGraphBuilder::VisitIfStatement(IfStatement* stmt) {
   BranchNode* branch = new BranchNode();
   FlowGraph original = graph_;
   graph_ = FlowGraph::Empty();
-  Visit(stmt->then_statement());
+  stmt->set_then_statement(ProcessStatement(stmt->then_statement()));
 
   FlowGraph left = graph_;
   graph_ = FlowGraph::Empty();
-  Visit(stmt->else_statement());
+  stmt->set_else_statement(ProcessStatement(stmt->else_statement()));
 
   if (HasStackOverflow()) return;
   JoinNode* join = new JoinNode();
@@ -275,7 +350,7 @@ void FlowGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
 
 
 void FlowGraphBuilder::VisitForStatement(ForStatement* stmt) {
-  if (stmt->init() != NULL) Visit(stmt->init());
+  if (stmt->init() != NULL) stmt->set_init(ProcessStatement(stmt->init()));
 
   JoinNode* join = new JoinNode();
   FlowGraph original = graph_;
@@ -285,9 +360,9 @@ void FlowGraphBuilder::VisitForStatement(ForStatement* stmt) {
   BranchNode* branch = new BranchNode();
   FlowGraph condition = graph_;
   graph_ = FlowGraph::Empty();
-  Visit(stmt->body());
+  stmt->set_body(ProcessStatement(stmt->body()));
 
-  if (stmt->next() != NULL) Visit(stmt->next());
+  if (stmt->next() != NULL) stmt->set_next(ProcessStatement(stmt->next()));
 
   if (HasStackOverflow()) return;
   original.Loop(join, &condition, branch, &graph_);
@@ -1611,8 +1686,9 @@ void JoinNode::PrintText() {
 }
 
 
-void FlowGraph::PrintText(ZoneList<Node*>* postorder) {
+void FlowGraph::PrintText(FunctionLiteral* fun, ZoneList<Node*>* postorder) {
   PrintF("\n========\n");
+  PrintF("name = %s\n", *fun->name()->ToCString());
 
   // Number nodes and instructions in reverse postorder.
   node_count = 0;
index 74a370c..b175ed0 100644 (file)
@@ -470,7 +470,7 @@ class FlowGraph BASE_EMBEDDED {
             FlowGraph* body);
 
 #ifdef DEBUG
-  void PrintText(ZoneList<Node*>* postorder);
+  void PrintText(FunctionLiteral* fun, ZoneList<Node*>* postorder);
 #endif
 
  private:
@@ -490,8 +490,7 @@ class FlowGraphBuilder: public AstVisitor {
         global_exit_(NULL),
         preorder_(4),
         postorder_(4),
-        definitions_(4) {
-  }
+        definitions_(4) {}
 
   void Build(FunctionLiteral* lit);
 
@@ -502,6 +501,10 @@ class FlowGraphBuilder: public AstVisitor {
  private:
   ExitNode* global_exit() { return global_exit_; }
 
+  // Helpers to allow tranforming the ast during flow graph construction.
+  void VisitStatements(ZoneList<Statement*>* stmts);
+  Statement* ProcessStatement(Statement* stmt);
+
   // AST node visit functions.
 #define DECLARE_VISIT(type) virtual void Visit##type(type* node);
   AST_NODE_LIST(DECLARE_VISIT)
index 021362d..6d0b958 100644 (file)
@@ -160,6 +160,9 @@ DEFINE_bool(use_flow_graph, false, "perform flow-graph based optimizations")
 // compilation-cache.cc
 DEFINE_bool(compilation_cache, true, "enable compilation cache")
 
+// data-flow.cc
+DEFINE_bool(loop_peeling, false, "Peel off the first iteration of loops.")
+
 // debug.cc
 DEFINE_bool(remote_debugging, false, "enable remote debugging")
 DEFINE_bool(trace_debug_json, false, "trace debugging JSON request/response")
index cff56a3..c15a604 100644 (file)
@@ -148,6 +148,7 @@ class Parser {
   ParserLog* log_;
   bool is_pre_parsing_;
   ScriptDataImpl* pre_data_;
+  bool seen_loop_stmt_;  // Used for inner loop detection.
 
   bool inside_with() const  { return with_nesting_level_ > 0; }
   ParserFactory* factory() const  { return factory_; }
@@ -1205,7 +1206,8 @@ Parser::Parser(Handle<Script> script,
       factory_(factory),
       log_(log),
       is_pre_parsing_(is_pre_parsing == PREPARSE),
-      pre_data_(pre_data) {
+      pre_data_(pre_data),
+      seen_loop_stmt_(false) {
 }
 
 
@@ -2653,6 +2655,9 @@ DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels,
   if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
 
   if (loop != NULL) loop->Initialize(cond, body);
+
+  seen_loop_stmt_ = true;
+
   return loop;
 }
 
@@ -2671,6 +2676,9 @@ WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) {
   Statement* body = ParseStatement(NULL, CHECK_OK);
 
   if (loop != NULL) loop->Initialize(cond, body);
+
+  seen_loop_stmt_ = true;
+
   return loop;
 }
 
@@ -2704,6 +2712,9 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
           Block* result = NEW(Block(NULL, 2, false));
           result->AddStatement(variable_statement);
           result->AddStatement(loop);
+
+          seen_loop_stmt_ = true;
+
           // Parsed for-in loop w/ variable/const declaration.
           return result;
         }
@@ -2733,6 +2744,8 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
         Statement* body = ParseStatement(NULL, CHECK_OK);
         if (loop) loop->Initialize(expression, enumerable, body);
 
+        seen_loop_stmt_ = true;
+
         // Parsed for-in loop.
         return loop;
 
@@ -2765,9 +2778,17 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
   }
   Expect(Token::RPAREN, CHECK_OK);
 
+  seen_loop_stmt_ = false;
+
   Statement* body = ParseStatement(NULL, CHECK_OK);
 
+  // Mark this loop if it is an inner loop.
+  if (loop && !seen_loop_stmt_) loop->set_peel_this_loop(true);
+
   if (loop) loop->Initialize(init, cond, next, body);
+
+  seen_loop_stmt_ = true;
+
   return loop;
 }
 
@@ -3712,6 +3733,9 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
   // Function ::
   //   '(' FormalParameterList? ')' '{' FunctionBody '}'
 
+  // Reset flag used for inner loop detection.
+  seen_loop_stmt_ = false;
+
   bool is_named = !var_name.is_null();
 
   // The name associated with this function. If it's a function expression,
@@ -3822,6 +3846,12 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
     if (!is_pre_parsing_) {
       function_literal->set_function_token_position(function_token_position);
     }
+
+    // Set flag for inner loop detection. We treat loops that contain a function
+    // literal not as inner loops because we avoid duplicating function literals
+    // when peeling or unrolling such a loop.
+    seen_loop_stmt_ = true;
+
     return function_literal;
   }
 }
index a68aa33..618f6ac 100644 (file)
@@ -70,8 +70,6 @@ class StaticType {
 
  private:
   Kind kind_;
-
-  DISALLOW_COPY_AND_ASSIGN(StaticType);
 };