Split the AST LoopStatement type into separate types for do/while,

while, and for loops.

Previously they were distinguished by a type field, which required
runtime asserts to avoid invalid nodes (since not all loop types have
the same internal structure).  Now they C++ type system is used to
require well-formed loop ASTs.

Because they do not share compilation code, we had very large
functions in the code generators that merely did a runtime dispatch to
a specific implementation based on the type.
Review URL: http://codereview.chromium.org/269049

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3048 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent c6729115
......@@ -1539,68 +1539,54 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
}
void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
void CodeGenerator::VisitDoWhileStatement(DoWhileStatement* node) {
#ifdef DEBUG
int original_height = frame_->height();
#endif
VirtualFrame::SpilledScope spilled_scope;
Comment cmnt(masm_, "[ LoopStatement");
Comment cmnt(masm_, "[ DoWhileStatement");
CodeForStatementPosition(node);
node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
// Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a
// known result for the test expression, with no side effects.
enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW;
if (node->cond() == NULL) {
ASSERT(node->type() == LoopStatement::FOR_LOOP);
info = ALWAYS_TRUE;
} else {
Literal* lit = node->cond()->AsLiteral();
if (lit != NULL) {
if (lit->IsTrue()) {
info = ALWAYS_TRUE;
} else if (lit->IsFalse()) {
info = ALWAYS_FALSE;
}
}
}
switch (node->type()) {
case LoopStatement::DO_LOOP: {
JumpTarget body(JumpTarget::BIDIRECTIONAL);
// Label the top of the loop for the backward CFG edge. If the test
// is always true we can use the continue target, and if the test is
// always false there is no need.
if (info == ALWAYS_TRUE) {
ConditionAnalysis info = AnalyzeCondition(node->cond());
switch (info) {
case ALWAYS_TRUE:
node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
node->continue_target()->Bind();
} else if (info == ALWAYS_FALSE) {
break;
case ALWAYS_FALSE:
node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
} else {
ASSERT(info == DONT_KNOW);
break;
case DONT_KNOW:
node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
body.Bind();
break;
}
CheckStack(); // TODO(1222600): ignore if body contains calls.
VisitAndSpill(node->body());
// Compile the test.
if (info == ALWAYS_TRUE) {
if (has_valid_frame()) {
switch (info) {
case ALWAYS_TRUE:
// If control can fall off the end of the body, jump back to the
// top.
if (has_valid_frame()) {
node->continue_target()->Jump();
}
} else if (info == ALWAYS_FALSE) {
// If we have a continue in the body, we only have to bind its jump
// target.
break;
case ALWAYS_FALSE:
// If we have a continue in the body, we only have to bind its
// jump target.
if (node->continue_target()->is_linked()) {
node->continue_target()->Bind();
}
} else {
ASSERT(info == DONT_KNOW);
break;
case DONT_KNOW:
// We have to compile the test expression if it can be reached by
// control flow falling out of the body or via continue.
if (node->continue_target()->is_linked()) {
......@@ -1615,14 +1601,30 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
Branch(true, &body);
}
}
}
break;
}
case LoopStatement::WHILE_LOOP: {
if (node->break_target()->is_linked()) {
node->break_target()->Bind();
}
ASSERT(!has_valid_frame() || frame_->height() == original_height);
}
void CodeGenerator::VisitWhileStatement(WhileStatement* node) {
#ifdef DEBUG
int original_height = frame_->height();
#endif
VirtualFrame::SpilledScope spilled_scope;
Comment cmnt(masm_, "[ WhileStatement");
CodeForStatementPosition(node);
// If the test is never true and has no side effects there is no need
// to compile the test or body.
if (info == ALWAYS_FALSE) break;
ConditionAnalysis info = AnalyzeCondition(node->cond());
if (info == ALWAYS_FALSE) return;
node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
// Label the top of the loop with the continue target for the backward
// CFG edge.
......@@ -1652,21 +1654,34 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
node->continue_target()->Jump();
}
}
break;
if (node->break_target()->is_linked()) {
node->break_target()->Bind();
}
ASSERT(!has_valid_frame() || frame_->height() == original_height);
}
case LoopStatement::FOR_LOOP: {
JumpTarget loop(JumpTarget::BIDIRECTIONAL);
void CodeGenerator::VisitForStatement(ForStatement* node) {
#ifdef DEBUG
int original_height = frame_->height();
#endif
VirtualFrame::SpilledScope spilled_scope;
Comment cmnt(masm_, "[ ForStatement");
CodeForStatementPosition(node);
if (node->init() != NULL) {
VisitAndSpill(node->init());
}
// There is no need to compile the test or body.
if (info == ALWAYS_FALSE) break;
// If the test is never true there is no need to compile the test or
// body.
ConditionAnalysis info = AnalyzeCondition(node->cond());
if (info == ALWAYS_FALSE) return;
node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
// If there is no update statement, label the top of the loop with the
// continue target, otherwise with the loop target.
JumpTarget loop(JumpTarget::BIDIRECTIONAL);
if (node->next() == NULL) {
node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
node->continue_target()->Bind();
......@@ -1715,15 +1730,9 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
}
}
}
break;
}
}
if (node->break_target()->is_linked()) {
node->break_target()->Bind();
}
node->continue_target()->Unuse();
node->break_target()->Unuse();
ASSERT(!has_valid_frame() || frame_->height() == original_height);
}
......@@ -1918,12 +1927,12 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) {
}
void CodeGenerator::VisitTryCatch(TryCatch* node) {
void CodeGenerator::VisitTryCatchStatement(TryCatchStatement* node) {
#ifdef DEBUG
int original_height = frame_->height();
#endif
VirtualFrame::SpilledScope spilled_scope;
Comment cmnt(masm_, "[ TryCatch");
Comment cmnt(masm_, "[ TryCatchStatement");
CodeForStatementPosition(node);
JumpTarget try_block;
......@@ -2043,12 +2052,12 @@ void CodeGenerator::VisitTryCatch(TryCatch* node) {
}
void CodeGenerator::VisitTryFinally(TryFinally* node) {
void CodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* node) {
#ifdef DEBUG
int original_height = frame_->height();
#endif
VirtualFrame::SpilledScope spilled_scope;
Comment cmnt(masm_, "[ TryFinally");
Comment cmnt(masm_, "[ TryFinallyStatement");
CodeForStatementPosition(node);
// State: Used to keep track of reason for entering the finally
......
......@@ -365,6 +365,14 @@ class CodeGenerator: public AstVisitor {
inline void GenerateMathSin(ZoneList<Expression*>* args);
inline void GenerateMathCos(ZoneList<Expression*>* args);
// Simple condition analysis.
enum ConditionAnalysis {
ALWAYS_TRUE,
ALWAYS_FALSE,
DONT_KNOW
};
ConditionAnalysis AnalyzeCondition(Expression* cond);
// Methods used to indicate which source code is generated for. Source
// positions are collected by the assembler and emitted with the relocation
// information.
......
......@@ -91,20 +91,6 @@ void VariableProxy::BindTo(Variable* var) {
}
#ifdef DEBUG
const char* LoopStatement::OperatorString() const {
switch (type()) {
case DO_LOOP: return "DO";
case FOR_LOOP: return "FOR";
case WHILE_LOOP: return "WHILE";
}
return NULL;
}
#endif // DEBUG
Token::Value Assignment::binary_op() const {
switch (op_) {
case Token::ASSIGN_BIT_OR: return Token::BIT_OR;
......
......@@ -64,10 +64,12 @@ namespace internal {
V(WithEnterStatement) \
V(WithExitStatement) \
V(SwitchStatement) \
V(LoopStatement) \
V(DoWhileStatement) \
V(WhileStatement) \
V(ForStatement) \
V(ForInStatement) \
V(TryCatch) \
V(TryFinally) \
V(TryCatchStatement) \
V(TryFinallyStatement) \
V(DebuggerStatement)
#define EXPRESSION_NODE_LIST(V) \
......@@ -294,13 +296,59 @@ class IterationStatement: public BreakableStatement {
};
class LoopStatement: public IterationStatement {
class DoWhileStatement: public IterationStatement {
public:
enum Type { DO_LOOP, FOR_LOOP, WHILE_LOOP };
explicit DoWhileStatement(ZoneStringList* labels)
: IterationStatement(labels), cond_(NULL) {
}
void Initialize(Expression* cond, Statement* body) {
IterationStatement::Initialize(body);
cond_ = cond;
}
virtual void Accept(AstVisitor* v);
Expression* cond() const { return cond_; }
private:
Expression* cond_;
};
class WhileStatement: public IterationStatement {
public:
explicit WhileStatement(ZoneStringList* labels)
: IterationStatement(labels),
cond_(NULL),
may_have_function_literal_(true) {
}
void Initialize(Expression* cond, Statement* body) {
IterationStatement::Initialize(body);
cond_ = cond;
}
virtual void Accept(AstVisitor* v);
Expression* cond() const { return cond_; }
bool may_have_function_literal() const {
return may_have_function_literal_;
}
LoopStatement(ZoneStringList* labels, Type type)
private:
Expression* cond_;
// True if there is a function literal subexpression in the condition.
bool may_have_function_literal_;
friend class AstOptimizer;
};
class ForStatement: public IterationStatement {
public:
explicit ForStatement(ZoneStringList* labels)
: IterationStatement(labels),
type_(type),
init_(NULL),
cond_(NULL),
next_(NULL),
......@@ -311,8 +359,6 @@ class LoopStatement: public IterationStatement {
Expression* cond,
Statement* next,
Statement* body) {
ASSERT(init == NULL || type_ == FOR_LOOP);
ASSERT(next == NULL || type_ == FOR_LOOP);
IterationStatement::Initialize(body);
init_ = init;
cond_ = cond;
......@@ -321,7 +367,6 @@ class LoopStatement: public IterationStatement {
virtual void Accept(AstVisitor* v);
Type type() const { return type_; }
Statement* init() const { return init_; }
Expression* cond() const { return cond_; }
Statement* next() const { return next_; }
......@@ -329,12 +374,7 @@ class LoopStatement: public IterationStatement {
return may_have_function_literal_;
}
#ifdef DEBUG
const char* OperatorString() const;
#endif
private:
Type type_;
Statement* init_;
Expression* cond_;
Statement* next_;
......@@ -569,9 +609,11 @@ class TryStatement: public Statement {
};
class TryCatch: public TryStatement {
class TryCatchStatement: public TryStatement {
public:
TryCatch(Block* try_block, Expression* catch_var, Block* catch_block)
TryCatchStatement(Block* try_block,
Expression* catch_var,
Block* catch_block)
: TryStatement(try_block),
catch_var_(catch_var),
catch_block_(catch_block) {
......@@ -589,9 +631,9 @@ class TryCatch: public TryStatement {
};
class TryFinally: public TryStatement {
class TryFinallyStatement: public TryStatement {
public:
TryFinally(Block* try_block, Block* finally_block)
TryFinallyStatement(Block* try_block, Block* finally_block)
: TryStatement(try_block),
finally_block_(finally_block) { }
......
......@@ -469,6 +469,25 @@ bool CodeGenerator::PatchInlineRuntimeEntry(Handle<String> name,
}
// Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a
// known result for the test expression, with no side effects.
CodeGenerator::ConditionAnalysis CodeGenerator::AnalyzeCondition(
Expression* cond) {
if (cond == NULL) return ALWAYS_TRUE;
Literal* lit = cond->AsLiteral();
if (lit == NULL) return DONT_KNOW;
if (lit->IsTrue()) {
return ALWAYS_TRUE;
} else if (lit->IsFalse()) {
return ALWAYS_FALSE;
}
return DONT_KNOW;
}
static inline void RecordPositions(CodeGenerator* cgen, int pos) {
if (pos != RelocInfo::kNoPosition) {
cgen->masm()->RecordStatementPosition(pos);
......
......@@ -61,6 +61,7 @@
// FindInlineRuntimeLUT
// CheckForInlineRuntimeCall
// PatchInlineRuntimeEntry
// AnalyzeCondition
// CodeForFunctionPosition
// CodeForReturnPosition
// CodeForStatementPosition
......
This diff is collapsed.
......@@ -548,6 +548,14 @@ class CodeGenerator: public AstVisitor {
inline void GenerateMathSin(ZoneList<Expression*>* args);
inline void GenerateMathCos(ZoneList<Expression*>* args);
// Simple condition analysis.
enum ConditionAnalysis {
ALWAYS_TRUE,
ALWAYS_FALSE,
DONT_KNOW
};
ConditionAnalysis AnalyzeCondition(Expression* cond);
// Methods used to indicate which source code is generated for. Source
// positions are collected by the assembler and emitted with the relocation
// information.
......
......@@ -177,8 +177,8 @@ class Parser {
Statement* ParseWithStatement(ZoneStringList* labels, bool* ok);
CaseClause* ParseCaseClause(bool* default_seen_ptr, bool* ok);
SwitchStatement* ParseSwitchStatement(ZoneStringList* labels, bool* ok);
LoopStatement* ParseDoStatement(ZoneStringList* labels, bool* ok);
LoopStatement* ParseWhileStatement(ZoneStringList* labels, bool* ok);
DoWhileStatement* ParseDoWhileStatement(ZoneStringList* labels, bool* ok);
WhileStatement* ParseWhileStatement(ZoneStringList* labels, bool* ok);
Statement* ParseForStatement(ZoneStringList* labels, bool* ok);
Statement* ParseThrowStatement(bool* ok);
Expression* MakeCatchContext(Handle<String> id, VariableProxy* value);
......@@ -1692,7 +1692,7 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
break;
case Token::DO:
stmt = ParseDoStatement(labels, ok);
stmt = ParseDoWhileStatement(labels, ok);
break;
case Token::WHILE:
......@@ -2361,7 +2361,7 @@ Block* Parser::WithHelper(Expression* obj,
exit->AddStatement(NEW(WithExitStatement()));
// Return a try-finally statement.
TryFinally* wrapper = NEW(TryFinally(body, exit));
TryFinallyStatement* wrapper = NEW(TryFinallyStatement(body, exit));
wrapper->set_escaping_targets(collector.targets());
result->AddStatement(wrapper);
}
......@@ -2537,7 +2537,8 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
// 'try { try { } catch { } } finally { }'
if (!is_pre_parsing_ && catch_block != NULL && finally_block != NULL) {
TryCatch* statement = NEW(TryCatch(try_block, catch_var, catch_block));
TryCatchStatement* statement =
NEW(TryCatchStatement(try_block, catch_var, catch_block));
statement->set_escaping_targets(collector.targets());
try_block = NEW(Block(NULL, 1, false));
try_block->AddStatement(statement);
......@@ -2548,11 +2549,11 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
if (!is_pre_parsing_) {
if (catch_block != NULL) {
ASSERT(finally_block == NULL);
result = NEW(TryCatch(try_block, catch_var, catch_block));
result = NEW(TryCatchStatement(try_block, catch_var, catch_block));
result->set_escaping_targets(collector.targets());
} else {
ASSERT(finally_block != NULL);
result = NEW(TryFinally(try_block, finally_block));
result = NEW(TryFinallyStatement(try_block, finally_block));
// Add the jump targets of the try block and the catch block.
for (int i = 0; i < collector.targets()->length(); i++) {
catch_collector.AddTarget(collector.targets()->at(i));
......@@ -2565,11 +2566,12 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
}
LoopStatement* Parser::ParseDoStatement(ZoneStringList* labels, bool* ok) {
DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels,
bool* ok) {
// DoStatement ::
// 'do' Statement 'while' '(' Expression ')' ';'
LoopStatement* loop = NEW(LoopStatement(labels, LoopStatement::DO_LOOP));
DoWhileStatement* loop = NEW(DoWhileStatement(labels));
Target target(this, loop);
Expect(Token::DO, CHECK_OK);
......@@ -2585,16 +2587,16 @@ LoopStatement* Parser::ParseDoStatement(ZoneStringList* labels, bool* ok) {
// ExpectSemicolon() functionality here.
if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
if (loop) loop->Initialize(NULL, cond, NULL, body);
if (loop != NULL) loop->Initialize(cond, body);
return loop;
}
LoopStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) {
WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) {
// WhileStatement ::
// 'while' '(' Expression ')' Statement
LoopStatement* loop = NEW(LoopStatement(labels, LoopStatement::WHILE_LOOP));
WhileStatement* loop = NEW(WhileStatement(labels));
Target target(this, loop);
Expect(Token::WHILE, CHECK_OK);
......@@ -2603,7 +2605,7 @@ LoopStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) {
Expect(Token::RPAREN, CHECK_OK);
Statement* body = ParseStatement(NULL, CHECK_OK);
if (loop) loop->Initialize(NULL, cond, NULL, body);
if (loop != NULL) loop->Initialize(cond, body);
return loop;
}
......@@ -2676,7 +2678,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
}
// Standard 'for' loop
LoopStatement* loop = NEW(LoopStatement(labels, LoopStatement::FOR_LOOP));
ForStatement* loop = NEW(ForStatement(labels));
Target target(this, loop);
// Parsed initializer at this point.
......
......@@ -147,20 +147,27 @@ void PrettyPrinter::VisitSwitchStatement(SwitchStatement* node) {
}
void PrettyPrinter::VisitLoopStatement(LoopStatement* node) {
void PrettyPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
PrintLabels(node->labels());
switch (node->type()) {
case LoopStatement::DO_LOOP:
ASSERT(node->init() == NULL);
ASSERT(node->next() == NULL);
Print("do ");
Visit(node->body());
Print(" while (");
Visit(node->cond());
Print(");");
break;
}
case LoopStatement::FOR_LOOP:
void PrettyPrinter::VisitWhileStatement(WhileStatement* node) {
PrintLabels(node->labels());
Print("while (");
Visit(node->cond());
Print(") ");
Visit(node->body());
}
void PrettyPrinter::VisitForStatement(ForStatement* node) {
PrintLabels(node->labels());
Print("for (");
if (node->init() != NULL) {
Visit(node->init());
......@@ -168,25 +175,14 @@ void PrettyPrinter::VisitLoopStatement(LoopStatement* node) {
} else {
Print("; ");
}
if (node->cond() != NULL)
Visit(node->cond());
if (node->cond() != NULL) Visit(node->cond());
Print("; ");
if (node->next() != NULL)
if (node->next() != NULL) {
Visit(node->next()); // prints extra ';', unfortunately
// to fix: should use Expression for next
}
Print(") ");
Visit(node->body());
break;
case LoopStatement::WHILE_LOOP:
ASSERT(node->init() == NULL);
ASSERT(node->next() == NULL);
Print("while (");
Visit(node->cond());
Print(") ");
Visit(node->body());
break;
}
}
......@@ -201,7 +197,7 @@ void PrettyPrinter::VisitForInStatement(ForInStatement* node) {
}
void PrettyPrinter::VisitTryCatch(TryCatch* node) {
void PrettyPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
Print("try ");
Visit(node->try_block());
Print(" catch (");
......@@ -211,7 +207,7 @@ void PrettyPrinter::VisitTryCatch(TryCatch* node) {
}
void PrettyPrinter::VisitTryFinally(TryFinally* node) {
void PrettyPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
Print("try ");
Visit(node->try_block());
Print(" finally ");
......@@ -841,12 +837,28 @@ void AstPrinter::VisitSwitchStatement(SwitchStatement* node) {
}
void AstPrinter::VisitLoopStatement(LoopStatement* node) {
IndentedScope indent(node->OperatorString());
void AstPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
IndentedScope indent("DO");
PrintLabelsIndented(NULL, node->labels());
PrintIndentedVisit("BODY", node->body());
PrintIndentedVisit("COND", node->cond());
}
void AstPrinter::VisitWhileStatement(WhileStatement* node) {
IndentedScope indent("WHILE");
PrintLabelsIndented(NULL, node->labels());
PrintIndentedVisit("COND", node->cond());
PrintIndentedVisit("BODY", node->body());
}
void AstPrinter::VisitForStatement(ForStatement* node) {
IndentedScope indent("FOR");
PrintLabelsIndented(NULL, node->labels());
if (node->init()) PrintIndentedVisit("INIT", node->init());
if (node->cond()) PrintIndentedVisit("COND", node->cond());
if (node->body()) PrintIndentedVisit("BODY", node->body());
PrintIndentedVisit("BODY", node->body());
if (node->next()) PrintIndentedVisit("NEXT", node->next());
}
......@@ -859,7 +871,7 @@ void AstPrinter::VisitForInStatement(ForInStatement* node) {
}
void AstPrinter::VisitTryCatch(TryCatch* node) {
void AstPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
IndentedScope indent("TRY CATCH");
PrintIndentedVisit("TRY", node->try_block());
PrintIndentedVisit("CATCHVAR", node->catch_var());
......@@ -867,7 +879,7 @@ void AstPrinter::VisitTryCatch(TryCatch* node) {
}
void AstPrinter::VisitTryFinally(TryFinally* node) {
void AstPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
IndentedScope indent("TRY FINALLY");
PrintIndentedVisit("TRY", node->try_block());
PrintIndentedVisit("FINALLY", node->finally_block());
......
......@@ -100,7 +100,21 @@ void AstOptimizer::VisitIfStatement(IfStatement* node) {
}
void AstOptimizer::VisitLoopStatement(LoopStatement* node) {
void AstOptimizer::VisitDoWhileStatement(DoWhileStatement* node) {
Visit(node->cond());
Visit(node->body());
}
void AstOptimizer::VisitWhileStatement(WhileStatement* node) {
has_function_literal_ = false;
Visit(node->cond());
node->may_have_function_literal_ = has_function_literal_;
Visit(node->body());
}
void AstOptimizer::VisitForStatement(ForStatement* node) {
if (node->init() != NULL) {
Visit(node->init());
}
......@@ -109,9 +123,7 @@ void AstOptimizer::VisitLoopStatement(LoopStatement* node) {
Visit(node->cond());
node->may_have_function_literal_ = has_function_literal_;
}
if (node->body() != NULL) {
Visit(node->body());
}
if (node->next() != NULL) {
Visit(node->next());
}
......@@ -125,14 +137,14 @@ void AstOptimizer::VisitForInStatement(ForInStatement* node) {
}
void AstOptimizer::VisitTryCatch(TryCatch* node) {
void AstOptimizer::VisitTryCatchStatement(TryCatchStatement* node) {
Visit(node->try_block());
Visit(node->catch_var());
Visit(node->catch_block());
}
void AstOptimizer::VisitTryFinally(TryFinally* node) {
void AstOptimizer::VisitTryFinallyStatement(TryFinallyStatement* node) {
Visit(node->try_block());
Visit(node->finally_block());
}
......@@ -553,6 +565,8 @@ class Processor: public AstVisitor {
virtual void Visit##type(type* node);
AST_NODE_LIST(DEF_VISIT)
#undef DEF_VISIT
void VisitIterationStatement(IterationStatement* stmt);
};
......@@ -596,25 +610,35 @@ void Processor::VisitIfStatement(IfStatement* node) {
}
void Processor::VisitLoopStatement(LoopStatement* node) {
// Rewrite loop body statement.
void Processor::VisitIterationStatement(IterationStatement* node) {
// Rewrite the body.
bool set_after_loop = is_set_;
Visit(node->body());
is_set_ = is_set_ && set_after_loop;
}
void Processor::VisitDoWhileStatement(DoWhileStatement* node) {
VisitIterationStatement(node);
}
void Processor::VisitWhileStatement(WhileStatement* node) {
VisitIterationStatement(node);
}
void Processor::VisitForStatement(ForStatement* node) {
VisitIterationStatement(node);
}
void Processor::VisitForInStatement(ForInStatement* node) {
// Rewrite for-in body statement.
bool set_after_for = is_set_;
Visit(node->body());
is_set_ = is_set_ && set_after_for;
VisitIterationStatement(node);
}
void Processor::VisitTryCatch(TryCatch* node) {
void Processor::VisitTryCatchStatement(TryCatchStatement* node) {
// Rewrite both try and catch blocks (reversed order).
bool set_after_catch = is_set_;
Visit(node->catch_block());
......@@ -626,7 +650,7 @@ void Processor::VisitTryCatch(TryCatch* node) {
}
void Processor::VisitTryFinally(TryFinally* node) {
void Processor::VisitTryFinallyStatement(TryFinallyStatement* node) {
// Rewrite both try and finally block (reversed order).
Visit(node->finally_block());
bool save = in_try_;
......
......@@ -159,14 +159,25 @@ void UsageComputer::VisitSwitchStatement(SwitchStatement* node) {
}
void UsageComputer::VisitLoopStatement(LoopStatement* node) {
if (node->init() != NULL)
Visit(node->init());
{ WeightScaler ws(this, 10.0); // executed in each iteration
if (node->cond() != NULL)
void UsageComputer::VisitDoWhileStatement(DoWhileStatement* node) {
WeightScaler ws(this, 10.0);
Read(node->cond());
if (node->next() != NULL)
Visit(node->next());
Visit(node->body());
}
void UsageComputer::VisitWhileStatement(WhileStatement* node) {
WeightScaler ws(this, 10.0);
Read(node->cond());
Visit(node->body());
}
void UsageComputer::VisitForStatement(ForStatement* node) {
if (node->init() != NULL) Visit(node->init());
{ WeightScaler ws(this, 10.0); // executed in each iteration
if (node->cond() != NULL) Read(node->cond());
if (node->next() != NULL) Visit(node->next());
Visit(node->body());
}
}
......@@ -180,7 +191,7 @@ void UsageComputer::VisitForInStatement(ForInStatement* node) {
}
void UsageComputer::VisitTryCatch(TryCatch* node) {
void UsageComputer::VisitTryCatchStatement(TryCatchStatement* node) {
Visit(node->try_block());
{ WeightScaler ws(this, 0.25);
Write(node->catch_var());
......@@ -189,7 +200,7 @@ void UsageComputer::VisitTryCatch(TryCatch* node) {
}
void UsageComputer::VisitTryFinally(TryFinally* node) {
void UsageComputer::VisitTryFinallyStatement(TryFinallyStatement* node) {
Visit(node->try_block());
Visit(node->finally_block());
}
......
This diff is collapsed.
......@@ -548,6 +548,14 @@ class CodeGenerator: public AstVisitor {
inline void GenerateMathSin(ZoneList<Expression*>* args);
inline void GenerateMathCos(ZoneList<Expression*>* args);
// Simple condition analysis.
enum ConditionAnalysis {
ALWAYS_TRUE,
ALWAYS_FALSE,
DONT_KNOW
};
ConditionAnalysis AnalyzeCondition(Expression* cond);
// Methods used to indicate which source code is generated for. Source
// positions are collected by the assembler and emitted with the relocation
// information.
......
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