Reenable the duplicated test at the bottom of for and while loops. It

is enabled for a loop by the absence of function literal
subexpressions in the condition expression.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1503 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent d0e76971
...@@ -291,8 +291,13 @@ class LoopStatement: public IterationStatement { ...@@ -291,8 +291,13 @@ class LoopStatement: public IterationStatement {
enum Type { DO_LOOP, FOR_LOOP, WHILE_LOOP }; enum Type { DO_LOOP, FOR_LOOP, WHILE_LOOP };
LoopStatement(ZoneStringList* labels, Type type) LoopStatement(ZoneStringList* labels, Type type)
: IterationStatement(labels), type_(type), init_(NULL), : IterationStatement(labels),
cond_(NULL), next_(NULL) { } type_(type),
init_(NULL),
cond_(NULL),
next_(NULL),
has_function_literal_(false) {
}
void Initialize(Statement* init, void Initialize(Statement* init,
Expression* cond, Expression* cond,
...@@ -312,6 +317,7 @@ class LoopStatement: public IterationStatement { ...@@ -312,6 +317,7 @@ class LoopStatement: public IterationStatement {
Statement* init() const { return init_; } Statement* init() const { return init_; }
Expression* cond() const { return cond_; } Expression* cond() const { return cond_; }
Statement* next() const { return next_; } Statement* next() const { return next_; }
bool has_function_literal() const { return has_function_literal_; }
#ifdef DEBUG #ifdef DEBUG
const char* OperatorString() const; const char* OperatorString() const;
...@@ -322,6 +328,10 @@ class LoopStatement: public IterationStatement { ...@@ -322,6 +328,10 @@ class LoopStatement: public IterationStatement {
Statement* init_; Statement* init_;
Expression* cond_; Expression* cond_;
Statement* next_; Statement* next_;
// True if there is a function literal subexpression in the condition.
bool has_function_literal_;
friend class AstOptimizer;
}; };
......
...@@ -2228,18 +2228,24 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) { ...@@ -2228,18 +2228,24 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
} }
case LoopStatement::WHILE_LOOP: { case LoopStatement::WHILE_LOOP: {
// TODO(260): This flag controls whether to duplicate the test // Do not duplicate conditions with function literal
// at the bottom of the loop. Replace it with a better // subexpressions. This can cause us to compile the function
// indication of when it is safe to do so. // literal twice.
static const bool test_at_bottom = false; bool test_at_bottom = !node->has_function_literal();
JumpTarget body(this); // Initialized as forward-only.
IncrementLoopNesting(); IncrementLoopNesting();
// If the condition is always false and has no side effects, we // If the condition is always false and has no side effects, we
// do not need to compile anything. // do not need to compile anything.
if (info == ALWAYS_FALSE) break; if (info == ALWAYS_FALSE) break;
JumpTarget body;
if (test_at_bottom) {
body.Initialize(this, JumpTarget::BIDIRECTIONAL);
} else {
body.Initialize(this);
}
// Based on the condition analysis, compile the test as necessary. // Based on the condition analysis, compile the test as necessary.
if (info == ALWAYS_TRUE) { if (info == ALWAYS_TRUE) {
// We will not compile the test expression. Label the top of // We will not compile the test expression. Label the top of
...@@ -2252,7 +2258,6 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) { ...@@ -2252,7 +2258,6 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
// Continue is the test at the bottom, no need to label the // Continue is the test at the bottom, no need to label the
// test at the top. The body is a backward target. // test at the top. The body is a backward target.
node->continue_target()->Initialize(this); node->continue_target()->Initialize(this);
body.make_bidirectional();
} else { } else {
// Label the test at the top as the continue target. The // Label the test at the top as the continue target. The
// body is a forward-only target. // body is a forward-only target.
...@@ -2321,13 +2326,10 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) { ...@@ -2321,13 +2326,10 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
} }
case LoopStatement::FOR_LOOP: { case LoopStatement::FOR_LOOP: {
// TODO(260): This flag controls whether to duplicate the test // Do not duplicate conditions with function literal
// at the bottom of the loop. Replace it with a better // subexpressions. This can cause us to compile the function
// indication of when it is safe to do so. // literal twice.
static const bool test_at_bottom = false; bool test_at_bottom = !node->has_function_literal();
JumpTarget loop(this, JumpTarget::BIDIRECTIONAL);
JumpTarget body(this);
// Compile the init expression if present. // Compile the init expression if present.
if (node->init() != NULL) { if (node->init() != NULL) {
...@@ -2340,6 +2342,19 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) { ...@@ -2340,6 +2342,19 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
// do not need to compile anything else. // do not need to compile anything else.
if (info == ALWAYS_FALSE) break; if (info == ALWAYS_FALSE) break;
// Target for backward edge if no test at the bottom, otherwise
// unused.
JumpTarget loop(this, JumpTarget::BIDIRECTIONAL);
// Target for backward edge if there is a test at the bottom,
// otherwise used as target for test at the top.
JumpTarget body;
if (test_at_bottom) {
body.Initialize(this, JumpTarget::BIDIRECTIONAL);
} else {
body.Initialize(this);
}
// Based on the condition analysis, compile the test as necessary. // Based on the condition analysis, compile the test as necessary.
if (info == ALWAYS_TRUE) { if (info == ALWAYS_TRUE) {
// We will not compile the test expression. Label the top of // We will not compile the test expression. Label the top of
......
...@@ -93,8 +93,6 @@ class JumpTarget : public Malloced { // Shadows are dynamically allocated. ...@@ -93,8 +93,6 @@ class JumpTarget : public Malloced { // Shadows are dynamically allocated.
entry_frame_ = frame; entry_frame_ = frame;
} }
void make_bidirectional() { direction_ = BIDIRECTIONAL; }
// Predicates testing the state of the encapsulated label. // Predicates testing the state of the encapsulated label.
bool is_bound() const { return is_bound_; } bool is_bound() const { return is_bound_; }
bool is_linked() const { return is_linked_; } bool is_linked() const { return is_linked_; }
......
...@@ -42,6 +42,10 @@ class AstOptimizer: public AstVisitor { ...@@ -42,6 +42,10 @@ class AstOptimizer: public AstVisitor {
void Optimize(ZoneList<Statement*>* statements); void Optimize(ZoneList<Statement*>* statements);
private: private:
// Used for loop condition analysis. Cleared before visiting a loop
// condition, set when a function literal is visited.
bool has_function_literal_;
// Helpers // Helpers
void OptimizeArguments(ZoneList<Expression*>* arguments); void OptimizeArguments(ZoneList<Expression*>* arguments);
...@@ -89,14 +93,14 @@ void AstOptimizer::VisitIfStatement(IfStatement* node) { ...@@ -89,14 +93,14 @@ void AstOptimizer::VisitIfStatement(IfStatement* node) {
} }
void AstOptimizer::VisitLoopStatement(LoopStatement* node) { void AstOptimizer::VisitLoopStatement(LoopStatement* node) {
if (node->init() != NULL) { if (node->init() != NULL) {
Visit(node->init()); Visit(node->init());
} }
if (node->cond() != NULL) { if (node->cond() != NULL) {
has_function_literal_ = false;
Visit(node->cond()); Visit(node->cond());
node->has_function_literal_ = has_function_literal_;
} }
if (node->body() != NULL) { if (node->body() != NULL) {
Visit(node->body()); Visit(node->body());
...@@ -182,6 +186,7 @@ void AstOptimizer::VisitDebuggerStatement(DebuggerStatement* node) { ...@@ -182,6 +186,7 @@ void AstOptimizer::VisitDebuggerStatement(DebuggerStatement* node) {
void AstOptimizer::VisitFunctionLiteral(FunctionLiteral* node) { void AstOptimizer::VisitFunctionLiteral(FunctionLiteral* node) {
USE(node); USE(node);
has_function_literal_ = true;
} }
......
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