Index: src/hydrogen.cc |
diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
index 1aa05e5993e63c8bb31d502478275995be2d09dd..6c4035c909ab3516a792572e912fa4a7bd3fbf5f 100644 |
--- a/src/hydrogen.cc |
+++ b/src/hydrogen.cc |
@@ -502,47 +502,13 @@ void HSubgraph::AppendJoin(HSubgraph* then_graph, |
} |
-void HSubgraph::ResolveContinue(IterationStatement* statement) { |
- HBasicBlock* continue_block = BundleContinue(statement); |
+void HSubgraph::ResolveContinue(IterationStatement* statement, |
+ HBasicBlock* continue_block) { |
if (continue_block != NULL) { |
- exit_block_ = JoinBlocks(exit_block(), |
- continue_block, |
- statement->ContinueId()); |
+ continue_block->SetJoinId(statement->ContinueId()); |
} |
-} |
- |
- |
-HBasicBlock* HSubgraph::BundleBreak(BreakableStatement* statement) { |
- return BundleBreakContinue(statement, false, statement->ExitId()); |
-} |
- |
- |
-HBasicBlock* HSubgraph::BundleContinue(IterationStatement* statement) { |
- return BundleBreakContinue(statement, true, statement->ContinueId()); |
-} |
- |
- |
-HBasicBlock* HSubgraph::BundleBreakContinue(BreakableStatement* statement, |
- bool is_continue, |
- int join_id) { |
- HBasicBlock* result = NULL; |
- const ZoneList<BreakContinueInfo*>* infos = break_continue_info(); |
- for (int i = 0; i < infos->length(); ++i) { |
- BreakContinueInfo* info = infos->at(i); |
- if (info->is_continue() == is_continue && |
- info->target() == statement && |
- !info->IsResolved()) { |
- if (result == NULL) { |
- result = graph_->CreateBasicBlock(); |
- } |
- info->block()->Goto(result); |
- info->Resolve(); |
- } |
- } |
- |
- if (result != NULL) result->SetJoinId(join_id); |
- |
- return result; |
+ exit_block_ = |
+ JoinBlocks(exit_block(), continue_block, statement->ContinueId()); |
} |
@@ -557,11 +523,13 @@ HBasicBlock* HSubgraph::JoinBlocks(HBasicBlock* a, HBasicBlock* b, int id) { |
} |
-void HSubgraph::AppendEndless(HSubgraph* body, IterationStatement* statement) { |
+void HSubgraph::AppendEndless(HSubgraph* body, |
+ IterationStatement* statement, |
+ HBasicBlock* break_block) { |
ConnectExitTo(body->entry_block()); |
- body->ResolveContinue(statement); |
body->ConnectExitTo(body->entry_block(), true); |
- exit_block_ = body->BundleBreak(statement); |
+ if (break_block != NULL) break_block->SetJoinId(statement->ExitId()); |
+ exit_block_ = break_block; |
body->entry_block()->PostProcessLoopHeader(statement); |
} |
@@ -569,11 +537,11 @@ void HSubgraph::AppendEndless(HSubgraph* body, IterationStatement* statement) { |
void HSubgraph::AppendDoWhile(HSubgraph* body, |
IterationStatement* statement, |
HSubgraph* go_back, |
- HSubgraph* exit) { |
+ HSubgraph* exit, |
+ HBasicBlock* break_block) { |
ConnectExitTo(body->entry_block()); |
go_back->ConnectExitTo(body->entry_block(), true); |
- |
- HBasicBlock* break_block = body->BundleBreak(statement); |
+ if (break_block != NULL) break_block->SetJoinId(statement->ExitId()); |
exit_block_ = |
JoinBlocks(exit->exit_block(), break_block, statement->ExitId()); |
body->entry_block()->PostProcessLoopHeader(statement); |
@@ -584,10 +552,11 @@ void HSubgraph::AppendWhile(HSubgraph* condition, |
HSubgraph* body, |
IterationStatement* statement, |
HSubgraph* continue_subgraph, |
- HSubgraph* exit) { |
+ HSubgraph* exit, |
+ HBasicBlock* break_block) { |
ConnectExitTo(condition->entry_block()); |
- HBasicBlock* break_block = body->BundleBreak(statement); |
+ if (break_block != NULL) break_block->SetJoinId(statement->ExitId()); |
exit_block_ = |
JoinBlocks(exit->exit_block(), break_block, statement->ExitId()); |
@@ -604,13 +573,15 @@ void HSubgraph::AppendWhile(HSubgraph* condition, |
} |
-void HSubgraph::Append(HSubgraph* next, BreakableStatement* stmt) { |
+void HSubgraph::Append(HSubgraph* next, |
+ BreakableStatement* stmt, |
+ HBasicBlock* break_block) { |
exit_block_->Goto(next->entry_block()); |
exit_block_ = next->exit_block_; |
if (stmt != NULL) { |
next->entry_block()->SetJoinId(stmt->EntryId()); |
- HBasicBlock* break_block = next->BundleBreak(stmt); |
+ if (break_block != NULL) break_block->SetJoinId(stmt->EntryId()); |
exit_block_ = JoinBlocks(exit_block(), break_block, stmt->ExitId()); |
} |
} |
@@ -624,16 +595,6 @@ void HSubgraph::FinishExit(HControlInstruction* instruction) { |
} |
-void HSubgraph::FinishBreakContinue(BreakableStatement* target, |
- bool is_continue) { |
- ASSERT(!exit_block_->IsFinished()); |
- BreakContinueInfo* info = new BreakContinueInfo(target, exit_block_, |
- is_continue); |
- break_continue_info_.Add(info); |
- exit_block_ = NULL; |
-} |
- |
- |
HGraph::HGraph(CompilationInfo* info) |
: HSubgraph(this), |
next_block_id_(0), |
@@ -2113,7 +2074,6 @@ class HGraphBuilder::SubgraphScope BASE_EMBEDDED { |
} |
~SubgraphScope() { |
- old_subgraph_->AddBreakContinueInfo(subgraph_); |
builder_->current_subgraph_ = old_subgraph_; |
} |
@@ -2195,7 +2155,7 @@ HGraph* HGraphBuilder::CreateGraph(CompilationInfo* info) { |
HSubgraph* body = CreateGotoSubgraph(environment()); |
AddToSubgraph(body, stmts); |
if (HasStackOverflow()) return NULL; |
- current_subgraph_->Append(body, NULL); |
+ current_subgraph_->Append(body, NULL, NULL); |
body->entry_block()->SetJoinId(info->function()->id()); |
if (graph_->HasExit()) { |
@@ -2397,8 +2357,11 @@ HSubgraph* HGraphBuilder::CreateLoopHeaderSubgraph(HEnvironment* env) { |
void HGraphBuilder::VisitBlock(Block* stmt) { |
if (stmt->labels() != NULL) { |
HSubgraph* block_graph = CreateGotoSubgraph(environment()); |
- ADD_TO_SUBGRAPH(block_graph, stmt->statements()); |
- current_subgraph_->Append(block_graph, stmt); |
+ BreakAndContinueInfo break_info(stmt); |
+ { BreakAndContinueScope push(&break_info, this); |
+ ADD_TO_SUBGRAPH(block_graph, stmt->statements()); |
+ } |
+ subgraph()->Append(block_graph, stmt, break_info.break_block()); |
} else { |
VisitStatements(stmt->statements()); |
} |
@@ -2439,13 +2402,48 @@ void HGraphBuilder::VisitIfStatement(IfStatement* stmt) { |
} |
+HBasicBlock* HGraphBuilder::BreakAndContinueScope::Get( |
+ BreakableStatement* stmt, |
+ BreakType type) { |
+ BreakAndContinueScope* current = this; |
+ while (current != NULL && current->info()->target() != stmt) { |
+ current = current->next(); |
+ } |
+ ASSERT(current != NULL); // Always found (unless stack is malformed). |
+ HBasicBlock* block = NULL; |
+ switch (type) { |
+ case BREAK: |
+ block = current->info()->break_block(); |
+ if (block == NULL) { |
+ block = current->owner()->graph()->CreateBasicBlock(); |
+ current->info()->set_break_block(block); |
+ } |
+ break; |
+ |
+ case CONTINUE: |
+ block = current->info()->continue_block(); |
+ if (block == NULL) { |
+ block = current->owner()->graph()->CreateBasicBlock(); |
+ current->info()->set_continue_block(block); |
+ } |
+ break; |
+ } |
+ |
+ return block; |
+} |
+ |
+ |
void HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { |
- current_subgraph_->FinishBreakContinue(stmt->target(), true); |
+ HBasicBlock* continue_block = break_scope()->Get(stmt->target(), CONTINUE); |
+ subgraph()->exit_block()->Goto(continue_block); |
+ subgraph()->set_exit_block(NULL); |
} |
void HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { |
- current_subgraph_->FinishBreakContinue(stmt->target(), false); |
+ HBasicBlock* break_block = break_scope()->Get(stmt->target(), BREAK); |
+ subgraph()->exit_block()->Goto(break_block); |
+ subgraph()->set_exit_block(NULL); |
} |
@@ -2628,10 +2626,13 @@ void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { |
} |
if (subgraph != NULL) { |
- ADD_TO_SUBGRAPH(subgraph, clause->statements()); |
- HBasicBlock* break_block = subgraph->BundleBreak(stmt); |
- if (break_block != NULL) { |
- break_block->Finish(new HGoto(single_exit_block)); |
+ BreakAndContinueInfo break_info(stmt); |
+ { BreakAndContinueScope push(&break_info, this); |
+ ADD_TO_SUBGRAPH(subgraph, clause->statements()); |
+ } |
+ if (break_info.break_block() != NULL) { |
+ break_info.break_block()->SetJoinId(stmt->ExitId()); |
+ break_info.break_block()->Finish(new HGoto(single_exit_block)); |
} |
} |
@@ -2698,11 +2699,14 @@ void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { |
subgraph()->PreProcessOsrEntry(stmt); |
HSubgraph* body_graph = CreateLoopHeaderSubgraph(environment()); |
- ADD_TO_SUBGRAPH(body_graph, stmt->body()); |
- body_graph->ResolveContinue(stmt); |
+ BreakAndContinueInfo break_info(stmt); |
+ { BreakAndContinueScope push(&break_info, this); |
+ ADD_TO_SUBGRAPH(body_graph, stmt->body()); |
+ } |
+ body_graph->ResolveContinue(stmt, break_info.continue_block()); |
if (!body_graph->HasExit() || stmt->cond()->ToBooleanIsTrue()) { |
- current_subgraph_->AppendEndless(body_graph, stmt); |
+ subgraph()->AppendEndless(body_graph, stmt, break_info.break_block()); |
} else { |
HSubgraph* go_back = CreateEmptySubgraph(); |
HSubgraph* exit = CreateEmptySubgraph(); |
@@ -2714,7 +2718,8 @@ void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { |
go_back->entry_block()->SetJoinId(stmt->BackEdgeId()); |
exit->entry_block()->SetJoinId(stmt->ExitId()); |
} |
- current_subgraph_->AppendDoWhile(body_graph, stmt, go_back, exit); |
+ subgraph()->AppendDoWhile(body_graph, stmt, go_back, exit, |
+ break_info.break_block()); |
} |
} |
@@ -2735,7 +2740,6 @@ void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { |
// If the condition is constant true, do not generate a condition subgraph. |
if (stmt->cond()->ToBooleanIsTrue()) { |
body_graph = CreateLoopHeaderSubgraph(environment()); |
- ADD_TO_SUBGRAPH(body_graph, stmt->body()); |
} else { |
cond_graph = CreateLoopHeaderSubgraph(environment()); |
body_graph = CreateEmptySubgraph(); |
@@ -2748,16 +2752,20 @@ void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { |
body_graph->entry_block()->SetJoinId(stmt->BodyId()); |
exit_graph->entry_block()->SetJoinId(stmt->ExitId()); |
} |
- ADD_TO_SUBGRAPH(body_graph, stmt->body()); |
} |
- body_graph->ResolveContinue(stmt); |
+ BreakAndContinueInfo break_info(stmt); |
+ { BreakAndContinueScope push(&break_info, this); |
+ ADD_TO_SUBGRAPH(body_graph, stmt->body()); |
+ } |
+ body_graph->ResolveContinue(stmt, break_info.continue_block()); |
if (cond_graph != NULL) { |
- AppendPeeledWhile(stmt, cond_graph, body_graph, exit_graph); |
+ AppendPeeledWhile(stmt, cond_graph, body_graph, exit_graph, |
+ break_info.break_block()); |
} else { |
// TODO(fschneider): Implement peeling for endless loops as well. |
- current_subgraph_->AppendEndless(body_graph, stmt); |
+ subgraph()->AppendEndless(body_graph, stmt, break_info.break_block()); |
} |
} |
@@ -2765,7 +2773,8 @@ void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { |
void HGraphBuilder::AppendPeeledWhile(IterationStatement* stmt, |
HSubgraph* cond_graph, |
HSubgraph* body_graph, |
- HSubgraph* exit_graph) { |
+ HSubgraph* exit_graph, |
+ HBasicBlock* break_block) { |
HSubgraph* loop = NULL; |
if (body_graph->HasExit() && stmt != peeled_statement_ && |
ShouldPeel(cond_graph, body_graph)) { |
@@ -2776,8 +2785,8 @@ void HGraphBuilder::AppendPeeledWhile(IterationStatement* stmt, |
ADD_TO_SUBGRAPH(loop, stmt); |
peeled_statement_ = outer_peeled_statement; |
} |
- current_subgraph_->AppendWhile(cond_graph, body_graph, stmt, loop, |
- exit_graph); |
+ subgraph()->AppendWhile(cond_graph, body_graph, stmt, loop, exit_graph, |
+ break_block); |
} |
@@ -2808,22 +2817,26 @@ void HGraphBuilder::VisitForStatement(ForStatement* stmt) { |
} else { |
body_graph = CreateLoopHeaderSubgraph(environment()); |
} |
- ADD_TO_SUBGRAPH(body_graph, stmt->body()); |
+ BreakAndContinueInfo break_info(stmt); |
+ { BreakAndContinueScope push(&break_info, this); |
+ ADD_TO_SUBGRAPH(body_graph, stmt->body()); |
+ } |
HSubgraph* next_graph = NULL; |
- body_graph->ResolveContinue(stmt); |
+ body_graph->ResolveContinue(stmt, break_info.continue_block()); |
if (stmt->next() != NULL && body_graph->HasExit()) { |
next_graph = CreateGotoSubgraph(body_graph->environment()); |
ADD_TO_SUBGRAPH(next_graph, stmt->next()); |
- body_graph->Append(next_graph, NULL); |
+ body_graph->Append(next_graph, NULL, NULL); |
next_graph->entry_block()->SetJoinId(stmt->ContinueId()); |
} |
if (cond_graph != NULL) { |
- AppendPeeledWhile(stmt, cond_graph, body_graph, exit_graph); |
+ AppendPeeledWhile(stmt, cond_graph, body_graph, exit_graph, |
+ break_info.break_block()); |
} else { |
- current_subgraph_->AppendEndless(body_graph, stmt); |
+ subgraph()->AppendEndless(body_graph, stmt, break_info.break_block()); |
} |
} |