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
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; }
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; }
public:
Statement() : statement_pos_(RelocInfo::kNoPosition) {}
+ explicit Statement(Statement* other);
+
virtual Statement* AsStatement() { return this; }
virtual ReturnStatement* AsReturnStatement() { return NULL; }
Expression() : bitfields_(0) {}
+ explicit Expression(Expression* other);
+
virtual Expression* AsExpression() { return this; }
virtual bool IsValidLeftHandSide() { return false; }
bitfields_ |= NumBitOpsField::encode(num_bit_ops);
}
-
private:
static const int kMaxNumBitOps = (1 << 5) - 1;
ASSERT(labels == NULL || labels->length() > 0);
}
+ explicit BreakableStatement(BreakableStatement* other);
+
private:
ZoneStringList* labels_;
Type type_;
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();
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_; }
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;
}
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,
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_;
}
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_;
// 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;
};
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.
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(); }
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_;
class EmptyStatement: public Statement {
public:
+ EmptyStatement() {}
+
+ explicit EmptyStatement(EmptyStatement* other);
+
virtual void Accept(AstVisitor* v);
// Type testing & conversion.
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
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.
ASSERT(Token::IsUnaryOp(op));
}
+ UnaryOperation(UnaryOperation* other, Expression* expression);
+
virtual void Accept(AstVisitor* v);
// Type testing & conversion
ASSERT(Token::IsBinaryOp(op));
}
+ BinaryOperation(BinaryOperation* other, Expression* left, Expression* right);
+
virtual void Accept(AstVisitor* v);
// Type testing & conversion
ASSERT(Token::IsCountOp(op));
}
+ CountOperation(CountOperation* other, Expression* expression);
+
virtual void Accept(AstVisitor* v);
virtual CountOperation* AsCountOperation() { return this; }
ASSERT(Token::IsCompareOp(op));
}
+ CompareOperation(CompareOperation* other,
+ Expression* left,
+ Expression* right);
+
virtual void Accept(AstVisitor* v);
virtual bool IsPrimitive();
ASSERT(Token::IsAssignmentOp(op));
}
+ Assignment(Assignment* other, Expression* target, Expression* value);
+
virtual void Accept(AstVisitor* v);
virtual Assignment* AsAssignment() { return this; }
};
+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_
#ifdef DEBUG
if (FLAG_print_graph_text && !builder.HasStackOverflow()) {
- builder.graph()->PrintText(builder.postorder());
+ builder.graph()->PrintText(function, builder.postorder());
}
#endif
}
#ifdef DEBUG
if (FLAG_print_graph_text && !builder.HasStackOverflow()) {
- builder.graph()->PrintText(builder.postorder());
+ builder.graph()->PrintText(literal, builder.postorder());
}
#endif
}
}
+// 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();
}
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();
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_;
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_);
}
-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;
FlowGraph* body);
#ifdef DEBUG
- void PrintText(ZoneList<Node*>* postorder);
+ void PrintText(FunctionLiteral* fun, ZoneList<Node*>* postorder);
#endif
private:
global_exit_(NULL),
preorder_(4),
postorder_(4),
- definitions_(4) {
- }
+ definitions_(4) {}
void Build(FunctionLiteral* lit);
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)
// 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")
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_; }
factory_(factory),
log_(log),
is_pre_parsing_(is_pre_parsing == PREPARSE),
- pre_data_(pre_data) {
+ pre_data_(pre_data),
+ seen_loop_stmt_(false) {
}
if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
if (loop != NULL) loop->Initialize(cond, body);
+
+ seen_loop_stmt_ = true;
+
return loop;
}
Statement* body = ParseStatement(NULL, CHECK_OK);
if (loop != NULL) loop->Initialize(cond, body);
+
+ seen_loop_stmt_ = true;
+
return loop;
}
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;
}
Statement* body = ParseStatement(NULL, CHECK_OK);
if (loop) loop->Initialize(expression, enumerable, body);
+ seen_loop_stmt_ = true;
+
// Parsed for-in loop.
return loop;
}
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;
}
// 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,
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;
}
}
private:
Kind kind_;
-
- DISALLOW_COPY_AND_ASSIGN(StaticType);
};