Chromium Code Reviews| Index: src/hydrogen.cc | 
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc | 
| index c4eae9a216650ed41f7bab76b88ef74e516dd3dd..e40685cd697acb2b44b0d4484af10421f9fc5858 100644 | 
| --- a/src/hydrogen.cc | 
| +++ b/src/hydrogen.cc | 
| @@ -535,24 +535,15 @@ HBasicBlock* HGraphBuilder::CreateDoWhile(IterationStatement* statement, | 
| HBasicBlock* HGraphBuilder::CreateWhile(IterationStatement* statement, | 
| - HBasicBlock* condition_entry, | 
| - HBasicBlock* exit_block, | 
| - HBasicBlock* body_exit, | 
| - HBasicBlock* break_block, | 
| HBasicBlock* loop_entry, | 
| - HBasicBlock* loop_exit) { | 
| + HBasicBlock* cond_false, | 
| + HBasicBlock* body_exit, | 
| + HBasicBlock* break_block) { | 
| if (break_block != NULL) break_block->SetJoinId(statement->ExitId()); | 
| HBasicBlock* new_exit = | 
| - CreateJoin(exit_block, break_block, statement->ExitId()); | 
| - | 
| - if (loop_entry != NULL) { | 
| - if (body_exit != NULL) body_exit->Goto(loop_entry, true); | 
| - loop_entry->SetJoinId(statement->EntryId()); | 
| - new_exit = CreateJoin(new_exit, loop_exit, statement->ExitId()); | 
| - } else { | 
| - if (body_exit != NULL) body_exit->Goto(condition_entry, true); | 
| - } | 
| - condition_entry->PostProcessLoopHeader(statement); | 
| + CreateJoin(cond_false, break_block, statement->ExitId()); | 
| + if (body_exit != NULL) body_exit->Goto(loop_entry, true); | 
| + loop_entry->PostProcessLoopHeader(statement); | 
| return new_exit; | 
| } | 
| @@ -2317,14 +2308,12 @@ HSubgraph* HGraphBuilder::CreateBranchSubgraph(HEnvironment* env) { | 
| } | 
| -HSubgraph* HGraphBuilder::CreateLoopHeaderSubgraph(HEnvironment* env) { | 
| - HSubgraph* subgraph = new HSubgraph(graph()); | 
| - HBasicBlock* block = graph()->CreateBasicBlock(); | 
| - HEnvironment* new_env = env->CopyAsLoopHeader(block); | 
| - block->SetInitialEnvironment(new_env); | 
| - subgraph->Initialize(block); | 
| - subgraph->entry_block()->AttachLoopInformation(); | 
| - return subgraph; | 
| +HBasicBlock* HGraphBuilder::CreateLoopHeader() { | 
| + HBasicBlock* header = graph()->CreateBasicBlock(); | 
| + HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); | 
| + header->SetInitialEnvironment(entry_env); | 
| + header->AttachLoopInformation(); | 
| + return header; | 
| } | 
| @@ -2681,120 +2670,80 @@ void HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) { | 
| void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { | 
| ASSERT(current_block() != NULL); | 
| PreProcessOsrEntry(stmt); | 
| + HBasicBlock* loop_entry = CreateLoopHeader(); | 
| + current_block()->Goto(loop_entry, false); | 
| + set_current_block(loop_entry); | 
| - HSubgraph* body_graph = CreateLoopHeaderSubgraph(environment()); | 
| - current_block()->Goto(body_graph->entry_block(), false); | 
| BreakAndContinueInfo break_info(stmt); | 
| { BreakAndContinueScope push(&break_info, this); | 
| - ADD_TO_SUBGRAPH(body_graph, stmt->body()); | 
| - } | 
| - HBasicBlock* body_exit = JoinContinue(stmt, | 
| - body_graph->exit_block(), | 
| - break_info.continue_block()); | 
| - body_graph->set_exit_block(body_exit); | 
| - | 
| - if (body_graph->exit_block() == NULL || stmt->cond()->ToBooleanIsTrue()) { | 
| - set_current_block(CreateEndless(stmt, | 
| - body_graph->entry_block(), | 
| - body_graph->exit_block(), | 
| - break_info.break_block())); | 
| + Visit(stmt->body()); | 
| + CHECK_BAILOUT; | 
| + } | 
| + HBasicBlock* body_exit = | 
| + JoinContinue(stmt, current_block(), break_info.continue_block()); | 
| + HBasicBlock* loop_exit = NULL; | 
| + if (body_exit == NULL || stmt->cond()->ToBooleanIsTrue()) { | 
| + loop_exit = CreateEndless(stmt, | 
| + loop_entry, | 
| + body_exit, | 
| + break_info.break_block()); | 
| } else { | 
| - HSubgraph* go_back = CreateEmptySubgraph(); | 
| - HSubgraph* exit = CreateEmptySubgraph(); | 
| - { | 
| - SubgraphScope scope(this, body_graph); | 
| - VISIT_FOR_CONTROL(stmt->cond(), | 
| - go_back->entry_block(), | 
| - exit->entry_block()); | 
| - go_back->entry_block()->SetJoinId(stmt->BackEdgeId()); | 
| - exit->entry_block()->SetJoinId(stmt->ExitId()); | 
| - } | 
| - set_current_block(CreateDoWhile(stmt, | 
| - body_graph->entry_block(), | 
| - go_back->exit_block(), | 
| - exit->exit_block(), | 
| - break_info.break_block())); | 
| + set_current_block(body_exit); | 
| + HBasicBlock* cond_true = graph()->CreateBasicBlock(); | 
| + HBasicBlock* cond_false = graph()->CreateBasicBlock(); | 
| + VISIT_FOR_CONTROL(stmt->cond(), cond_true, cond_false); | 
| + cond_true->SetJoinId(stmt->BackEdgeId()); | 
| + cond_false->SetJoinId(stmt->ExitId()); | 
| + loop_exit = CreateDoWhile(stmt, | 
| + loop_entry, | 
| + cond_true, | 
| + cond_false, | 
| + break_info.break_block()); | 
| } | 
| + set_current_block(loop_exit); | 
| } | 
| void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { | 
| ASSERT(current_block() != NULL); | 
| PreProcessOsrEntry(stmt); | 
| + HBasicBlock* loop_entry = CreateLoopHeader(); | 
| + current_block()->Goto(loop_entry, false); | 
| + set_current_block(loop_entry); | 
| - HSubgraph* cond_graph = NULL; | 
| - HSubgraph* body_graph = NULL; | 
| - HSubgraph* exit_graph = NULL; | 
| - | 
| - // If the condition is constant true, do not generate a condition subgraph. | 
| - if (stmt->cond()->ToBooleanIsTrue()) { | 
| - body_graph = CreateLoopHeaderSubgraph(environment()); | 
| - current_block()->Goto(body_graph->entry_block(), false); | 
| - } else { | 
| - cond_graph = CreateLoopHeaderSubgraph(environment()); | 
| - current_block()->Goto(cond_graph->entry_block(), false); | 
| - body_graph = CreateEmptySubgraph(); | 
| - exit_graph = CreateEmptySubgraph(); | 
| - { | 
| - SubgraphScope scope(this, cond_graph); | 
| - VISIT_FOR_CONTROL(stmt->cond(), | 
| - body_graph->entry_block(), | 
| - exit_graph->entry_block()); | 
| - body_graph->entry_block()->SetJoinId(stmt->BodyId()); | 
| - exit_graph->entry_block()->SetJoinId(stmt->ExitId()); | 
| - } | 
| + // If the condition is constant true, do not generate a branch. | 
| + HBasicBlock* cond_false = NULL; | 
| + if (!stmt->cond()->ToBooleanIsTrue()) { | 
| + HBasicBlock* cond_true = graph()->CreateBasicBlock(); | 
| + cond_false = graph()->CreateBasicBlock(); | 
| + VISIT_FOR_CONTROL(stmt->cond(), cond_true, cond_false); | 
| + cond_true->SetJoinId(stmt->BodyId()); | 
| + cond_false->SetJoinId(stmt->ExitId()); | 
| + set_current_block(cond_true); | 
| } | 
| BreakAndContinueInfo break_info(stmt); | 
| { BreakAndContinueScope push(&break_info, this); | 
| - ADD_TO_SUBGRAPH(body_graph, stmt->body()); | 
| - } | 
| - HBasicBlock* body_exit = JoinContinue(stmt, | 
| - body_graph->exit_block(), | 
| - break_info.continue_block()); | 
| - body_graph->set_exit_block(body_exit); | 
| - | 
| - if (cond_graph != NULL) { | 
| - set_current_block(CreatePeeledWhile(stmt, | 
| - cond_graph->entry_block(), | 
| - exit_graph->exit_block(), | 
| - body_graph->exit_block(), | 
| - break_info.break_block())); | 
| - } else { | 
| - // TODO(fschneider): Implement peeling for endless loops as well. | 
| - set_current_block(CreateEndless(stmt, | 
| - body_graph->entry_block(), | 
| - body_graph->exit_block(), | 
| - break_info.break_block())); | 
| + Visit(stmt->body()); | 
| + CHECK_BAILOUT; | 
| } | 
| -} | 
| - | 
| - | 
| -HBasicBlock* HGraphBuilder::CreatePeeledWhile(IterationStatement* stmt, | 
| - HBasicBlock* condition_entry, | 
| - HBasicBlock* exit_block, | 
| - HBasicBlock* body_exit, | 
| - HBasicBlock* break_block) { | 
| - HBasicBlock* loop_entry = NULL; | 
| + HBasicBlock* body_exit = | 
| + JoinContinue(stmt, current_block(), break_info.continue_block()); | 
| HBasicBlock* loop_exit = NULL; | 
| - if (FLAG_use_peeling && body_exit != NULL && stmt != peeled_statement_) { | 
| - // Save the last peeled iteration statement to prevent infinite recursion. | 
| - IterationStatement* outer_peeled_statement = peeled_statement_; | 
| - peeled_statement_ = stmt; | 
| - HSubgraph* loop = CreateGotoSubgraph(body_exit->last_environment()); | 
| - AddToSubgraph(loop, stmt); | 
| - peeled_statement_ = outer_peeled_statement; | 
| - if (HasStackOverflow()) return NULL; | 
| - loop_entry = loop->entry_block(); | 
| - loop_exit = loop->exit_block(); | 
| + if (stmt->cond()->ToBooleanIsTrue()) { | 
| + // TODO(fschneider): Implement peeling for endless loops as well. | 
| 
 
fschneider
2011/03/02 10:45:35
This comment can go away now.
 
Kevin Millikin (Chromium)
2011/03/02 11:08:43
Yeah, you're right.
 
 | 
| + loop_exit = CreateEndless(stmt, | 
| + loop_entry, | 
| + body_exit, | 
| + break_info.break_block()); | 
| + } else { | 
| + loop_exit = CreateWhile(stmt, | 
| + loop_entry, | 
| + cond_false, | 
| + body_exit, | 
| + break_info.break_block()); | 
| } | 
| - return CreateWhile(stmt, | 
| - condition_entry, | 
| - exit_block, | 
| - body_exit, | 
| - break_block, | 
| - loop_entry, | 
| - loop_exit); | 
| + set_current_block(loop_exit); | 
| } | 
| @@ -2806,59 +2755,49 @@ void HGraphBuilder::VisitForStatement(ForStatement* stmt) { | 
| } | 
| ASSERT(current_block() != NULL); | 
| PreProcessOsrEntry(stmt); | 
| + HBasicBlock* loop_entry = CreateLoopHeader(); | 
| + current_block()->Goto(loop_entry, false); | 
| + set_current_block(loop_entry); | 
| - HSubgraph* cond_graph = NULL; | 
| - HSubgraph* body_graph = NULL; | 
| - HSubgraph* exit_graph = NULL; | 
| + HBasicBlock* cond_false = NULL; | 
| if (stmt->cond() != NULL) { | 
| - cond_graph = CreateLoopHeaderSubgraph(environment()); | 
| - current_block()->Goto(cond_graph->entry_block(), false); | 
| - body_graph = CreateEmptySubgraph(); | 
| - exit_graph = CreateEmptySubgraph(); | 
| - { | 
| - SubgraphScope scope(this, cond_graph); | 
| - VISIT_FOR_CONTROL(stmt->cond(), | 
| - body_graph->entry_block(), | 
| - exit_graph->entry_block()); | 
| - body_graph->entry_block()->SetJoinId(stmt->BodyId()); | 
| - exit_graph->entry_block()->SetJoinId(stmt->ExitId()); | 
| - } | 
| - } else { | 
| - body_graph = CreateLoopHeaderSubgraph(environment()); | 
| - current_block()->Goto(body_graph->entry_block(), false); | 
| + HBasicBlock* cond_true = graph()->CreateBasicBlock(); | 
| + cond_false = graph()->CreateBasicBlock(); | 
| + VISIT_FOR_CONTROL(stmt->cond(), cond_true, cond_false); | 
| + cond_true->SetJoinId(stmt->BodyId()); | 
| + cond_false->SetJoinId(stmt->ExitId()); | 
| + set_current_block(cond_true); | 
| } | 
| + | 
| BreakAndContinueInfo break_info(stmt); | 
| { BreakAndContinueScope push(&break_info, this); | 
| - ADD_TO_SUBGRAPH(body_graph, stmt->body()); | 
| - } | 
| - | 
| - HSubgraph* next_graph = NULL; | 
| - HBasicBlock* body_exit = JoinContinue(stmt, | 
| - body_graph->exit_block(), | 
| - break_info.continue_block()); | 
| - body_graph->set_exit_block(body_exit); | 
| - | 
| - if (stmt->next() != NULL && body_graph->exit_block() != NULL) { | 
| - next_graph = | 
| - CreateGotoSubgraph(body_graph->exit_block()->last_environment()); | 
| - body_graph->exit_block()->Goto(next_graph->entry_block()); | 
| - next_graph->entry_block()->SetJoinId(stmt->ContinueId()); | 
| - ADD_TO_SUBGRAPH(next_graph, stmt->next()); | 
| - body_graph->set_exit_block(next_graph->exit_block()); | 
| - } | 
| - | 
| - if (cond_graph != NULL) { | 
| - set_current_block(CreatePeeledWhile(stmt, | 
| - cond_graph->entry_block(), | 
| - exit_graph->exit_block(), | 
| - body_graph->exit_block(), | 
| - break_info.break_block())); | 
| + Visit(stmt->body()); | 
| + CHECK_BAILOUT; | 
| + } | 
| + HBasicBlock* body_exit = | 
| + JoinContinue(stmt, current_block(), break_info.continue_block()); | 
| + | 
| + if (stmt->next() != NULL && body_exit != NULL) { | 
| + set_current_block(body_exit); | 
| + Visit(stmt->next()); | 
| + CHECK_BAILOUT; | 
| + body_exit = current_block(); | 
| + } | 
| + | 
| + HBasicBlock* loop_exit = NULL; | 
| + if (stmt->cond() == NULL) { | 
| + loop_exit = CreateEndless(stmt, | 
| + loop_entry, | 
| + body_exit, | 
| + break_info.break_block()); | 
| } else { | 
| - set_current_block(CreateEndless(stmt, | 
| - body_graph->entry_block(), | 
| - body_graph->exit_block(), | 
| - break_info.break_block())); | 
| + loop_exit = CreateWhile(stmt, | 
| + loop_entry, | 
| + cond_false, | 
| + body_exit, | 
| + break_info.break_block()); | 
| } | 
| + set_current_block(loop_exit); | 
| } |