Index: src/parser.cc |
diff --git a/src/parser.cc b/src/parser.cc |
index 184f0a2a27efd2c7104c67dcfa63469b1f71ed84..69cd2fcbfbfbcd25eb490ce5720ef1c9a25bfbca 100644 |
--- a/src/parser.cc |
+++ b/src/parser.cc |
@@ -823,14 +823,23 @@ class ParserFinder { |
// form expr.a = ...; expr.b = ...; etc. |
class InitializationBlockFinder : public ParserFinder { |
public: |
- InitializationBlockFinder() |
- : first_in_block_(NULL), last_in_block_(NULL), block_size_(0) {} |
+ // We find and mark the initialization blocks on top level code only. |
+ // This is because the optimization prevents reuse of the map transitions, |
+ // so it should be used only for code that will only be run once. |
Vyacheslav Egorov (Chromium)
2011/07/06 14:19:05
Comment should mention that we do not apply this o
|
+ InitializationBlockFinder(Scope* top_scope, Target* target) |
+ : enabled_(top_scope->DeclarationScope()->is_global_scope() && |
+ !IsLoopTarget(target)), |
+ first_in_block_(NULL), |
+ last_in_block_(NULL), |
+ block_size_(0) {} |
~InitializationBlockFinder() { |
+ if (!enabled_) return; |
if (InBlock()) EndBlock(); |
} |
void Update(Statement* stat) { |
+ if (!enabled_) return; |
Assignment* assignment = AsAssignment(stat); |
if (InBlock()) { |
if (BlockContinues(assignment)) { |
@@ -851,6 +860,14 @@ class InitializationBlockFinder : public ParserFinder { |
// the overhead exceeds the savings below this limit. |
static const int kMinInitializationBlock = 3; |
+ static bool IsLoopTarget(Target* target) { |
+ while (target != NULL) { |
+ if (target->node()->AsIterationStatement() != NULL) return true; |
+ target = target->previous(); |
+ } |
+ return false; |
+ } |
+ |
// Returns true if the expressions appear to denote the same object. |
// In the context of initialization blocks, we only consider expressions |
// of the form 'expr.x' or expr["x"]. |
@@ -913,6 +930,7 @@ class InitializationBlockFinder : public ParserFinder { |
bool InBlock() { return first_in_block_ != NULL; } |
+ const bool enabled_; |
Assignment* first_in_block_; |
Assignment* last_in_block_; |
int block_size_; |
@@ -1078,7 +1096,7 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor, |
TargetScope scope(&this->target_stack_); |
ASSERT(processor != NULL); |
- InitializationBlockFinder block_finder; |
+ InitializationBlockFinder block_finder(top_scope_, target_stack_); |
ThisNamedPropertyAssigmentFinder this_property_assignment_finder(isolate()); |
bool directive_prologue = true; // Parsing directive prologue. |
@@ -1133,12 +1151,7 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor, |
} |
} |
- // We find and mark the initialization blocks on top level code only. |
- // This is because the optimization prevents reuse of the map transitions, |
- // so it should be used only for code that will only be run once. |
- if (top_scope_->is_global_scope()) { |
- block_finder.Update(stat); |
- } |
+ block_finder.Update(stat); |
// Find and mark all assignments to named properties in this (this.x =) |
if (top_scope_->is_function_scope()) { |
this_property_assignment_finder.Update(top_scope_, stat); |
@@ -1478,9 +1491,13 @@ Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) { |
Block* result = new(zone()) Block(labels, 16, false); |
Target target(&this->target_stack_, result); |
Expect(Token::LBRACE, CHECK_OK); |
+ InitializationBlockFinder block_finder(top_scope_, target_stack_); |
while (peek() != Token::RBRACE) { |
Statement* stat = ParseStatement(NULL, CHECK_OK); |
- if (stat && !stat->IsEmpty()) result->AddStatement(stat); |
+ if (stat && !stat->IsEmpty()) { |
+ result->AddStatement(stat); |
+ block_finder.Update(stat); |
+ } |
} |
Expect(Token::RBRACE, CHECK_OK); |
return result; |