Loop peeling for inner loops.

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
parent eebcea14
......@@ -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
......@@ -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_
......@@ -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
}
......
......@@ -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;
......
......@@ -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)
......
......@@ -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")
......
......@@ -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;
}
}
......
......@@ -70,8 +70,6 @@ class StaticType {
private:
Kind kind_;
DISALLOW_COPY_AND_ASSIGN(StaticType);
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment