Partial refactoring of subgraphs.

Change the interface to the Hydrogen graph builder to appear like it
directly holds a current basic block and a current environment.
Remove some direct accesses to the current subgraph, and remove
subgraph accessors that simply forwarded to the exit block.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6887 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent b0fa9477
...@@ -485,16 +485,17 @@ HConstant* HGraph::GetConstantFalse() { ...@@ -485,16 +485,17 @@ HConstant* HGraph::GetConstantFalse() {
void HSubgraph::AppendJoin(HSubgraph* then_graph, void HSubgraph::AppendJoin(HSubgraph* then_graph,
HSubgraph* else_graph, HSubgraph* else_graph,
AstNode* node) { AstNode* node) {
if (then_graph->HasExit() && else_graph->HasExit()) { if (then_graph->exit_block() != NULL &&
else_graph->exit_block() != NULL) {
// We need to merge, create new merge block. // We need to merge, create new merge block.
HBasicBlock* join_block = graph_->CreateBasicBlock(); HBasicBlock* join_block = graph_->CreateBasicBlock();
then_graph->exit_block()->Goto(join_block); then_graph->exit_block()->Goto(join_block);
else_graph->exit_block()->Goto(join_block); else_graph->exit_block()->Goto(join_block);
join_block->SetJoinId(node->id()); join_block->SetJoinId(node->id());
exit_block_ = join_block; exit_block_ = join_block;
} else if (then_graph->HasExit()) { } else if (then_graph->exit_block() != NULL) {
exit_block_ = then_graph->exit_block_; exit_block_ = then_graph->exit_block_;
} else if (else_graph->HasExit()) { } else if (else_graph->exit_block() != NULL) {
exit_block_ = else_graph->exit_block_; exit_block_ = else_graph->exit_block_;
} else { } else {
exit_block_ = NULL; exit_block_ = NULL;
...@@ -526,8 +527,12 @@ HBasicBlock* HSubgraph::JoinBlocks(HBasicBlock* a, HBasicBlock* b, int id) { ...@@ -526,8 +527,12 @@ HBasicBlock* HSubgraph::JoinBlocks(HBasicBlock* a, HBasicBlock* b, int id) {
void HSubgraph::AppendEndless(HSubgraph* body, void HSubgraph::AppendEndless(HSubgraph* body,
IterationStatement* statement, IterationStatement* statement,
HBasicBlock* break_block) { HBasicBlock* break_block) {
ConnectExitTo(body->entry_block()); if (exit_block() != NULL) {
body->ConnectExitTo(body->entry_block(), true); exit_block()->Goto(body->entry_block(), false);
}
if (body->exit_block() != NULL) {
body->exit_block()->Goto(body->entry_block(), true);
}
if (break_block != NULL) break_block->SetJoinId(statement->ExitId()); if (break_block != NULL) break_block->SetJoinId(statement->ExitId());
exit_block_ = break_block; exit_block_ = break_block;
body->entry_block()->PostProcessLoopHeader(statement); body->entry_block()->PostProcessLoopHeader(statement);
...@@ -539,8 +544,12 @@ void HSubgraph::AppendDoWhile(HSubgraph* body, ...@@ -539,8 +544,12 @@ void HSubgraph::AppendDoWhile(HSubgraph* body,
HSubgraph* go_back, HSubgraph* go_back,
HSubgraph* exit, HSubgraph* exit,
HBasicBlock* break_block) { HBasicBlock* break_block) {
ConnectExitTo(body->entry_block()); if (exit_block() != NULL) {
go_back->ConnectExitTo(body->entry_block(), true); exit_block()->Goto(body->entry_block(), false);
}
if (go_back->exit_block() != NULL) {
go_back->exit_block()->Goto(body->entry_block(), true);
}
if (break_block != NULL) break_block->SetJoinId(statement->ExitId()); if (break_block != NULL) break_block->SetJoinId(statement->ExitId());
exit_block_ = exit_block_ =
JoinBlocks(exit->exit_block(), break_block, statement->ExitId()); JoinBlocks(exit->exit_block(), break_block, statement->ExitId());
...@@ -554,20 +563,26 @@ void HSubgraph::AppendWhile(HSubgraph* condition, ...@@ -554,20 +563,26 @@ void HSubgraph::AppendWhile(HSubgraph* condition,
HSubgraph* continue_subgraph, HSubgraph* continue_subgraph,
HSubgraph* exit, HSubgraph* exit,
HBasicBlock* break_block) { HBasicBlock* break_block) {
ConnectExitTo(condition->entry_block()); if (exit_block() != NULL) {
exit_block()->Goto(condition->entry_block(), false);
}
if (break_block != NULL) break_block->SetJoinId(statement->ExitId()); if (break_block != NULL) break_block->SetJoinId(statement->ExitId());
exit_block_ = exit_block_ =
JoinBlocks(exit->exit_block(), break_block, statement->ExitId()); JoinBlocks(exit->exit_block(), break_block, statement->ExitId());
if (continue_subgraph != NULL) { if (continue_subgraph != NULL) {
body->ConnectExitTo(continue_subgraph->entry_block(), true); if (body->exit_block() != NULL) {
body->exit_block()->Goto(continue_subgraph->entry_block(), true);
}
continue_subgraph->entry_block()->SetJoinId(statement->EntryId()); continue_subgraph->entry_block()->SetJoinId(statement->EntryId());
exit_block_ = JoinBlocks(exit_block_, exit_block_ = JoinBlocks(exit_block_,
continue_subgraph->exit_block(), continue_subgraph->exit_block(),
statement->ExitId()); statement->ExitId());
} else { } else {
body->ConnectExitTo(condition->entry_block(), true); if (body->exit_block() != NULL) {
body->exit_block()->Goto(condition->entry_block(), true);
}
} }
condition->entry_block()->PostProcessLoopHeader(statement); condition->entry_block()->PostProcessLoopHeader(statement);
} }
...@@ -588,7 +603,7 @@ void HSubgraph::Append(HSubgraph* next, ...@@ -588,7 +603,7 @@ void HSubgraph::Append(HSubgraph* next,
void HSubgraph::FinishExit(HControlInstruction* instruction) { void HSubgraph::FinishExit(HControlInstruction* instruction) {
ASSERT(HasExit()); ASSERT(exit_block() != NULL);
exit_block_->Finish(instruction); exit_block_->Finish(instruction);
exit_block_->ClearEnvironment(); exit_block_->ClearEnvironment();
exit_block_ = NULL; exit_block_ = NULL;
...@@ -1936,14 +1951,14 @@ AstContext::~AstContext() { ...@@ -1936,14 +1951,14 @@ AstContext::~AstContext() {
EffectContext::~EffectContext() { EffectContext::~EffectContext() {
ASSERT(owner()->HasStackOverflow() || ASSERT(owner()->HasStackOverflow() ||
!owner()->subgraph()->HasExit() || owner()->current_block() == NULL ||
owner()->environment()->length() == original_length_); owner()->environment()->length() == original_length_);
} }
ValueContext::~ValueContext() { ValueContext::~ValueContext() {
ASSERT(owner()->HasStackOverflow() || ASSERT(owner()->HasStackOverflow() ||
!owner()->subgraph()->HasExit() || owner()->current_block() == NULL ||
owner()->environment()->length() == original_length_ + 1); owner()->environment()->length() == original_length_ + 1);
} }
...@@ -2001,7 +2016,7 @@ void TestContext::BuildBranch(HValue* value) { ...@@ -2001,7 +2016,7 @@ void TestContext::BuildBranch(HValue* value) {
HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); HBasicBlock* empty_true = builder->graph()->CreateBasicBlock();
HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); HBasicBlock* empty_false = builder->graph()->CreateBasicBlock();
HTest* test = new HTest(value, empty_true, empty_false); HTest* test = new HTest(value, empty_true, empty_false);
builder->CurrentBlock()->Finish(test); builder->current_block()->Finish(test);
HValue* const no_return_value = NULL; HValue* const no_return_value = NULL;
HBasicBlock* true_target = if_true(); HBasicBlock* true_target = if_true();
...@@ -2017,7 +2032,7 @@ void TestContext::BuildBranch(HValue* value) { ...@@ -2017,7 +2032,7 @@ void TestContext::BuildBranch(HValue* value) {
} else { } else {
empty_false->Goto(false_target); empty_false->Goto(false_target);
} }
builder->subgraph()->set_exit_block(NULL); builder->set_current_block(NULL);
} }
...@@ -2124,7 +2139,7 @@ void HGraphBuilder::VisitArgument(Expression* expr) { ...@@ -2124,7 +2139,7 @@ void HGraphBuilder::VisitArgument(Expression* expr) {
void HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) { void HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) {
for (int i = 0; i < arguments->length(); i++) { for (int i = 0; i < arguments->length(); i++) {
VisitArgument(arguments->at(i)); VisitArgument(arguments->at(i));
if (HasStackOverflow() || !current_subgraph_->HasExit()) return; if (HasStackOverflow() || current_block() == NULL) return;
} }
} }
...@@ -2158,7 +2173,7 @@ HGraph* HGraphBuilder::CreateGraph(CompilationInfo* info) { ...@@ -2158,7 +2173,7 @@ HGraph* HGraphBuilder::CreateGraph(CompilationInfo* info) {
current_subgraph_->Append(body, NULL, NULL); current_subgraph_->Append(body, NULL, NULL);
body->entry_block()->SetJoinId(info->function()->id()); body->entry_block()->SetJoinId(info->function()->id());
if (graph_->HasExit()) { if (graph()->exit_block() != NULL) {
graph_->FinishExit(new HReturn(graph_->GetConstantUndefined())); graph_->FinishExit(new HReturn(graph_->GetConstantUndefined()));
} }
} }
...@@ -2219,21 +2234,21 @@ void HGraphBuilder::AddToSubgraph(HSubgraph* graph, ...@@ -2219,21 +2234,21 @@ void HGraphBuilder::AddToSubgraph(HSubgraph* graph,
HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
ASSERT(current_subgraph_->HasExit()); ASSERT(current_block() != NULL);
current_subgraph_->exit_block()->AddInstruction(instr); current_block()->AddInstruction(instr);
return instr; return instr;
} }
void HGraphBuilder::AddSimulate(int id) { void HGraphBuilder::AddSimulate(int id) {
ASSERT(current_subgraph_->HasExit()); ASSERT(current_block() != NULL);
current_subgraph_->exit_block()->AddSimulate(id); current_block()->AddSimulate(id);
} }
void HGraphBuilder::AddPhi(HPhi* instr) { void HGraphBuilder::AddPhi(HPhi* instr) {
ASSERT(current_subgraph_->HasExit()); ASSERT(current_block() != NULL);
current_subgraph_->exit_block()->AddPhi(instr); current_block()->AddPhi(instr);
} }
...@@ -2296,7 +2311,7 @@ void HGraphBuilder::SetupScope(Scope* scope) { ...@@ -2296,7 +2311,7 @@ void HGraphBuilder::SetupScope(Scope* scope) {
void HGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) { void HGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) {
for (int i = 0; i < statements->length(); i++) { for (int i = 0; i < statements->length(); i++) {
Visit(statements->at(i)); Visit(statements->at(i));
if (HasStackOverflow() || !current_subgraph_->HasExit()) break; if (HasStackOverflow() || current_block() == NULL) break;
} }
} }
...@@ -2435,15 +2450,15 @@ HBasicBlock* HGraphBuilder::BreakAndContinueScope::Get( ...@@ -2435,15 +2450,15 @@ HBasicBlock* HGraphBuilder::BreakAndContinueScope::Get(
void HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { void HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) {
HBasicBlock* continue_block = break_scope()->Get(stmt->target(), CONTINUE); HBasicBlock* continue_block = break_scope()->Get(stmt->target(), CONTINUE);
subgraph()->exit_block()->Goto(continue_block); current_block()->Goto(continue_block);
subgraph()->set_exit_block(NULL); set_current_block(NULL);
} }
void HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { void HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
HBasicBlock* break_block = break_scope()->Get(stmt->target(), BREAK); HBasicBlock* break_block = break_scope()->Get(stmt->target(), BREAK);
subgraph()->exit_block()->Goto(break_block); current_block()->Goto(break_block);
subgraph()->set_exit_block(NULL); set_current_block(NULL);
} }
...@@ -2472,9 +2487,9 @@ void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { ...@@ -2472,9 +2487,9 @@ void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
VISIT_FOR_VALUE(stmt->expression()); VISIT_FOR_VALUE(stmt->expression());
return_value = environment()->Pop(); return_value = environment()->Pop();
} }
subgraph()->exit_block()->AddLeaveInlined(return_value, current_block()->AddLeaveInlined(return_value,
function_return_); function_return_);
subgraph()->set_exit_block(NULL); set_current_block(NULL);
} }
} }
} }
...@@ -2495,7 +2510,7 @@ HCompare* HGraphBuilder::BuildSwitchCompare(HSubgraph* subgraph, ...@@ -2495,7 +2510,7 @@ HCompare* HGraphBuilder::BuildSwitchCompare(HSubgraph* subgraph,
CaseClause* clause) { CaseClause* clause) {
AddToSubgraph(subgraph, clause->label()); AddToSubgraph(subgraph, clause->label());
if (HasStackOverflow()) return NULL; if (HasStackOverflow()) return NULL;
HValue* clause_value = subgraph->environment()->Pop(); HValue* clause_value = subgraph->exit_block()->last_environment()->Pop();
HCompare* compare = new HCompare(switch_value, HCompare* compare = new HCompare(switch_value,
clause_value, clause_value,
Token::EQ_STRICT); Token::EQ_STRICT);
...@@ -2576,7 +2591,7 @@ void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { ...@@ -2576,7 +2591,7 @@ void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
// last_false_block is the (empty) false-block of the last comparison. If // last_false_block is the (empty) false-block of the last comparison. If
// there are no comparisons at all (a single default clause), it is just // there are no comparisons at all (a single default clause), it is just
// the last block of the current subgraph. // the last block of the current subgraph.
HBasicBlock* last_false_block = current_subgraph_->exit_block(); HBasicBlock* last_false_block = current_block();
if (prev_graph != current_subgraph_) { if (prev_graph != current_subgraph_) {
last_false_block = graph()->CreateBasicBlock(); last_false_block = graph()->CreateBasicBlock();
HBasicBlock* empty = graph()->CreateBasicBlock(); HBasicBlock* empty = graph()->CreateBasicBlock();
...@@ -2619,7 +2634,7 @@ void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { ...@@ -2619,7 +2634,7 @@ void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
} }
// Check for fall-through from previous statement block. // Check for fall-through from previous statement block.
if (previous_subgraph != NULL && previous_subgraph->HasExit()) { if (previous_subgraph != NULL && previous_subgraph->exit_block() != NULL) {
if (subgraph == NULL) subgraph = CreateEmptySubgraph(); if (subgraph == NULL) subgraph = CreateEmptySubgraph();
previous_subgraph->exit_block()-> previous_subgraph->exit_block()->
Finish(new HGoto(subgraph->entry_block())); Finish(new HGoto(subgraph->entry_block()));
...@@ -2641,7 +2656,7 @@ void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { ...@@ -2641,7 +2656,7 @@ void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
// If the last statement block has a fall-through, connect it to the // If the last statement block has a fall-through, connect it to the
// single exit block. // single exit block.
if (previous_subgraph != NULL && previous_subgraph->HasExit()) { if (previous_subgraph != NULL && previous_subgraph->exit_block() != NULL) {
previous_subgraph->exit_block()->Finish(new HGoto(single_exit_block)); previous_subgraph->exit_block()->Finish(new HGoto(single_exit_block));
} }
...@@ -2651,9 +2666,9 @@ void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { ...@@ -2651,9 +2666,9 @@ void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
} }
if (single_exit_block->HasPredecessor()) { if (single_exit_block->HasPredecessor()) {
current_subgraph_->set_exit_block(single_exit_block); set_current_block(single_exit_block);
} else { } else {
current_subgraph_->set_exit_block(NULL); set_current_block(NULL);
} }
} }
...@@ -2695,7 +2710,7 @@ void HSubgraph::PreProcessOsrEntry(IterationStatement* statement) { ...@@ -2695,7 +2710,7 @@ void HSubgraph::PreProcessOsrEntry(IterationStatement* statement) {
void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
ASSERT(subgraph()->HasExit()); ASSERT(current_block() != NULL);
subgraph()->PreProcessOsrEntry(stmt); subgraph()->PreProcessOsrEntry(stmt);
HSubgraph* body_graph = CreateLoopHeaderSubgraph(environment()); HSubgraph* body_graph = CreateLoopHeaderSubgraph(environment());
...@@ -2705,7 +2720,7 @@ void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { ...@@ -2705,7 +2720,7 @@ void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
} }
body_graph->ResolveContinue(stmt, break_info.continue_block()); body_graph->ResolveContinue(stmt, break_info.continue_block());
if (!body_graph->HasExit() || stmt->cond()->ToBooleanIsTrue()) { if (body_graph->exit_block() == NULL || stmt->cond()->ToBooleanIsTrue()) {
subgraph()->AppendEndless(body_graph, stmt, break_info.break_block()); subgraph()->AppendEndless(body_graph, stmt, break_info.break_block());
} else { } else {
HSubgraph* go_back = CreateEmptySubgraph(); HSubgraph* go_back = CreateEmptySubgraph();
...@@ -2730,7 +2745,7 @@ bool HGraphBuilder::ShouldPeel(HSubgraph* cond, HSubgraph* body) { ...@@ -2730,7 +2745,7 @@ bool HGraphBuilder::ShouldPeel(HSubgraph* cond, HSubgraph* body) {
void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
ASSERT(subgraph()->HasExit()); ASSERT(current_block() != NULL);
subgraph()->PreProcessOsrEntry(stmt); subgraph()->PreProcessOsrEntry(stmt);
HSubgraph* cond_graph = NULL; HSubgraph* cond_graph = NULL;
...@@ -2776,12 +2791,12 @@ void HGraphBuilder::AppendPeeledWhile(IterationStatement* stmt, ...@@ -2776,12 +2791,12 @@ void HGraphBuilder::AppendPeeledWhile(IterationStatement* stmt,
HSubgraph* exit_graph, HSubgraph* exit_graph,
HBasicBlock* break_block) { HBasicBlock* break_block) {
HSubgraph* loop = NULL; HSubgraph* loop = NULL;
if (body_graph->HasExit() && stmt != peeled_statement_ && if (body_graph->exit_block() != NULL && stmt != peeled_statement_ &&
ShouldPeel(cond_graph, body_graph)) { ShouldPeel(cond_graph, body_graph)) {
// Save the last peeled iteration statement to prevent infinite recursion. // Save the last peeled iteration statement to prevent infinite recursion.
IterationStatement* outer_peeled_statement = peeled_statement_; IterationStatement* outer_peeled_statement = peeled_statement_;
peeled_statement_ = stmt; peeled_statement_ = stmt;
loop = CreateGotoSubgraph(body_graph->environment()); loop = CreateGotoSubgraph(body_graph->exit_block()->last_environment());
ADD_TO_SUBGRAPH(loop, stmt); ADD_TO_SUBGRAPH(loop, stmt);
peeled_statement_ = outer_peeled_statement; peeled_statement_ = outer_peeled_statement;
} }
...@@ -2796,7 +2811,7 @@ void HGraphBuilder::VisitForStatement(ForStatement* stmt) { ...@@ -2796,7 +2811,7 @@ void HGraphBuilder::VisitForStatement(ForStatement* stmt) {
Visit(stmt->init()); Visit(stmt->init());
CHECK_BAILOUT; CHECK_BAILOUT;
} }
ASSERT(subgraph()->HasExit()); ASSERT(current_block() != NULL);
subgraph()->PreProcessOsrEntry(stmt); subgraph()->PreProcessOsrEntry(stmt);
HSubgraph* cond_graph = NULL; HSubgraph* cond_graph = NULL;
...@@ -2825,8 +2840,9 @@ void HGraphBuilder::VisitForStatement(ForStatement* stmt) { ...@@ -2825,8 +2840,9 @@ void HGraphBuilder::VisitForStatement(ForStatement* stmt) {
HSubgraph* next_graph = NULL; HSubgraph* next_graph = NULL;
body_graph->ResolveContinue(stmt, break_info.continue_block()); body_graph->ResolveContinue(stmt, break_info.continue_block());
if (stmt->next() != NULL && body_graph->HasExit()) { if (stmt->next() != NULL && body_graph->exit_block() != NULL) {
next_graph = CreateGotoSubgraph(body_graph->environment()); next_graph =
CreateGotoSubgraph(body_graph->exit_block()->last_environment());
ADD_TO_SUBGRAPH(next_graph, stmt->next()); ADD_TO_SUBGRAPH(next_graph, stmt->next());
body_graph->Append(next_graph, NULL, NULL); body_graph->Append(next_graph, NULL, NULL);
next_graph->entry_block()->SetJoinId(stmt->ContinueId()); next_graph->entry_block()->SetJoinId(stmt->ContinueId());
...@@ -3103,9 +3119,9 @@ HBasicBlock* HGraphBuilder::BuildTypeSwitch(HValue* receiver, ...@@ -3103,9 +3119,9 @@ HBasicBlock* HGraphBuilder::BuildTypeSwitch(HValue* receiver,
maps->at(i), maps->at(i),
if_true->entry_block(), if_true->entry_block(),
if_false->entry_block()); if_false->entry_block());
subgraph()->exit_block()->Finish(compare); current_block()->Finish(compare);
if (if_true->HasExit()) { if (if_true->exit_block() != NULL) {
// In an effect context the value of the type switch is not needed. // In an effect context the value of the type switch is not needed.
// There is no need to merge it at the join block only to discard it. // There is no need to merge it at the join block only to discard it.
if (ast_context()->IsEffect()) { if (ast_context()->IsEffect()) {
...@@ -3114,15 +3130,15 @@ HBasicBlock* HGraphBuilder::BuildTypeSwitch(HValue* receiver, ...@@ -3114,15 +3130,15 @@ HBasicBlock* HGraphBuilder::BuildTypeSwitch(HValue* receiver,
if_true->exit_block()->Goto(join_block); if_true->exit_block()->Goto(join_block);
} }
subgraph()->set_exit_block(if_false->exit_block()); set_current_block(if_false->exit_block());
} }
// Connect the default if necessary. // Connect the default if necessary.
if (subgraph()->HasExit()) { if (current_block() != NULL) {
if (ast_context()->IsEffect()) { if (ast_context()->IsEffect()) {
environment()->Drop(1); environment()->Drop(1);
} }
subgraph()->exit_block()->Goto(join_block); current_block()->Goto(join_block);
} }
if (join_block->predecessors()->is_empty()) return NULL; if (join_block->predecessors()->is_empty()) return NULL;
...@@ -3279,10 +3295,10 @@ void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr, ...@@ -3279,10 +3295,10 @@ void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr,
HBasicBlock* new_exit_block = HBasicBlock* new_exit_block =
BuildTypeSwitch(object, &maps, &subgraphs, default_graph, expr->id()); BuildTypeSwitch(object, &maps, &subgraphs, default_graph, expr->id());
subgraph()->set_exit_block(new_exit_block); set_current_block(new_exit_block);
// In an effect context, we did not materialized the value in the // In an effect context, we did not materialized the value in the
// predecessor environments so there's no need to handle it here. // predecessor environments so there's no need to handle it here.
if (subgraph()->HasExit() && !ast_context()->IsEffect()) { if (current_block() != NULL && !ast_context()->IsEffect()) {
ast_context()->ReturnValue(Pop()); ast_context()->ReturnValue(Pop());
} }
} }
...@@ -3613,10 +3629,10 @@ void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, ...@@ -3613,10 +3629,10 @@ void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
HBasicBlock* new_exit_block = HBasicBlock* new_exit_block =
BuildTypeSwitch(object, &maps, &subgraphs, default_graph, expr->id()); BuildTypeSwitch(object, &maps, &subgraphs, default_graph, expr->id());
subgraph()->set_exit_block(new_exit_block); set_current_block(new_exit_block);
// In an effect context, we did not materialized the value in the // In an effect context, we did not materialized the value in the
// predecessor environments so there's no need to handle it here. // predecessor environments so there's no need to handle it here.
if (subgraph()->HasExit() && !ast_context()->IsEffect()) { if (current_block() != NULL && !ast_context()->IsEffect()) {
ast_context()->ReturnValue(Pop()); ast_context()->ReturnValue(Pop());
} }
} }
...@@ -3973,7 +3989,7 @@ void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr, ...@@ -3973,7 +3989,7 @@ void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
HBasicBlock* new_exit_block = HBasicBlock* new_exit_block =
BuildTypeSwitch(receiver, &maps, &subgraphs, default_graph, expr->id()); BuildTypeSwitch(receiver, &maps, &subgraphs, default_graph, expr->id());
subgraph()->set_exit_block(new_exit_block); set_current_block(new_exit_block);
// In an effect context, we did not materialized the value in the // In an effect context, we did not materialized the value in the
// predecessor environments so there's no need to handle it here. // predecessor environments so there's no need to handle it here.
if (new_exit_block != NULL && !ast_context()->IsEffect()) { if (new_exit_block != NULL && !ast_context()->IsEffect()) {
...@@ -4142,7 +4158,7 @@ bool HGraphBuilder::TryInline(Call* expr) { ...@@ -4142,7 +4158,7 @@ bool HGraphBuilder::TryInline(Call* expr) {
if (FLAG_trace_inlining) TraceInline(target, true); if (FLAG_trace_inlining) TraceInline(target, true);
if (body->HasExit()) { if (body->exit_block() != NULL) {
// Add a return of undefined if control can fall off the body. In a // Add a return of undefined if control can fall off the body. In a
// test context, undefined is false. // test context, undefined is false.
HValue* return_value = graph()->GetConstantUndefined(); HValue* return_value = graph()->GetConstantUndefined();
...@@ -4171,7 +4187,7 @@ bool HGraphBuilder::TryInline(Call* expr) { ...@@ -4171,7 +4187,7 @@ bool HGraphBuilder::TryInline(Call* expr) {
AddSimulate(expr->ReturnId()); AddSimulate(expr->ReturnId());
// Jump to the function entry (without re-recording the environment). // Jump to the function entry (without re-recording the environment).
subgraph()->exit_block()->Finish(new HGoto(body->entry_block())); current_block()->Finish(new HGoto(body->entry_block()));
// Fix up the function exits. // Fix up the function exits.
if (test_context != NULL) { if (test_context != NULL) {
...@@ -4201,11 +4217,11 @@ bool HGraphBuilder::TryInline(Call* expr) { ...@@ -4201,11 +4217,11 @@ bool HGraphBuilder::TryInline(Call* expr) {
// TODO(kmillikin): Come up with a better way to handle this. It is too // TODO(kmillikin): Come up with a better way to handle this. It is too
// subtle. NULL here indicates that the enclosing context has no control // subtle. NULL here indicates that the enclosing context has no control
// flow to handle. // flow to handle.
subgraph()->set_exit_block(NULL); set_current_block(NULL);
} else { } else {
function_return_->SetJoinId(expr->id()); function_return_->SetJoinId(expr->id());
subgraph()->set_exit_block(function_return_); set_current_block(function_return_);
} }
call_context_ = saved_call_context; call_context_ = saved_call_context;
...@@ -4434,7 +4450,7 @@ void HGraphBuilder::VisitCall(Call* expr) { ...@@ -4434,7 +4450,7 @@ void HGraphBuilder::VisitCall(Call* expr) {
AddCheckConstantFunction(expr, receiver, receiver_map, true); AddCheckConstantFunction(expr, receiver, receiver_map, true);
if (TryInline(expr)) { if (TryInline(expr)) {
if (subgraph()->HasExit()) { if (current_block() != NULL) {
HValue* return_value = Pop(); HValue* return_value = Pop();
// If we inlined a function in a test context then we need to emit // If we inlined a function in a test context then we need to emit
// a simulate here to shadow the ones at the end of the // a simulate here to shadow the ones at the end of the
...@@ -4505,7 +4521,7 @@ void HGraphBuilder::VisitCall(Call* expr) { ...@@ -4505,7 +4521,7 @@ void HGraphBuilder::VisitCall(Call* expr) {
environment()->SetExpressionStackAt(receiver_index, global_receiver); environment()->SetExpressionStackAt(receiver_index, global_receiver);
if (TryInline(expr)) { if (TryInline(expr)) {
if (subgraph()->HasExit()) { if (current_block() != NULL) {
HValue* return_value = Pop(); HValue* return_value = Pop();
// If we inlined a function in a test context then we need to // If we inlined a function in a test context then we need to
// emit a simulate here to shadow the ones at the end of the // emit a simulate here to shadow the ones at the end of the
...@@ -4673,10 +4689,12 @@ void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { ...@@ -4673,10 +4689,12 @@ void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
false_graph->entry_block(), false_graph->entry_block(),
true_graph->entry_block()); true_graph->entry_block());
true_graph->entry_block()->SetJoinId(expr->expression()->id()); true_graph->entry_block()->SetJoinId(expr->expression()->id());
true_graph->environment()->Push(graph_->GetConstantTrue()); true_graph->exit_block()->last_environment()->Push(
graph_->GetConstantTrue());
false_graph->entry_block()->SetJoinId(expr->expression()->id()); false_graph->entry_block()->SetJoinId(expr->expression()->id());
false_graph->environment()->Push(graph_->GetConstantFalse()); false_graph->exit_block()->last_environment()->Push(
graph_->GetConstantFalse());
current_subgraph_->AppendJoin(true_graph, false_graph, expr); current_subgraph_->AppendJoin(true_graph, false_graph, expr);
ast_context()->ReturnValue(Pop()); ast_context()->ReturnValue(Pop());
...@@ -4973,12 +4991,12 @@ void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { ...@@ -4973,12 +4991,12 @@ void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
// Translate right subexpression by visiting it in the same AST // Translate right subexpression by visiting it in the same AST
// context as the entire expression. // context as the entire expression.
subgraph()->set_exit_block(eval_right); set_current_block(eval_right);
Visit(expr->right()); Visit(expr->right());
} else if (ast_context()->IsValue()) { } else if (ast_context()->IsValue()) {
VISIT_FOR_VALUE(expr->left()); VISIT_FOR_VALUE(expr->left());
ASSERT(current_subgraph_->HasExit()); ASSERT(current_block() != NULL);
HValue* left = Top(); HValue* left = Top();
HEnvironment* environment_copy = environment()->Copy(); HEnvironment* environment_copy = environment()->Copy();
...@@ -4987,7 +5005,8 @@ void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { ...@@ -4987,7 +5005,8 @@ void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
right_subgraph = CreateBranchSubgraph(environment_copy); right_subgraph = CreateBranchSubgraph(environment_copy);
ADD_TO_SUBGRAPH(right_subgraph, expr->right()); ADD_TO_SUBGRAPH(right_subgraph, expr->right());
ASSERT(subgraph()->HasExit() && right_subgraph->HasExit()); ASSERT(current_block() != NULL &&
right_subgraph->exit_block() != NULL);
// We need an extra block to maintain edge-split form. // We need an extra block to maintain edge-split form.
HBasicBlock* empty_block = graph()->CreateBasicBlock(); HBasicBlock* empty_block = graph()->CreateBasicBlock();
HBasicBlock* join_block = graph()->CreateBasicBlock(); HBasicBlock* join_block = graph()->CreateBasicBlock();
...@@ -4995,11 +5014,11 @@ void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { ...@@ -4995,11 +5014,11 @@ void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
HTest* test = is_logical_and HTest* test = is_logical_and
? new HTest(left, right_subgraph->entry_block(), empty_block) ? new HTest(left, right_subgraph->entry_block(), empty_block)
: new HTest(left, empty_block, right_subgraph->entry_block()); : new HTest(left, empty_block, right_subgraph->entry_block());
subgraph()->exit_block()->Finish(test); current_block()->Finish(test);
empty_block->Goto(join_block); empty_block->Goto(join_block);
right_subgraph->exit_block()->Goto(join_block); right_subgraph->exit_block()->Goto(join_block);
join_block->SetJoinId(expr->id()); join_block->SetJoinId(expr->id());
subgraph()->set_exit_block(join_block); set_current_block(join_block);
ast_context()->ReturnValue(Pop()); ast_context()->ReturnValue(Pop());
} else { } else {
ASSERT(ast_context()->IsEffect()); ASSERT(ast_context()->IsEffect());
...@@ -5021,13 +5040,13 @@ void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { ...@@ -5021,13 +5040,13 @@ void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
// no good AST ID to put on that first HSimulate. // no good AST ID to put on that first HSimulate.
empty_block->SetJoinId(expr->id()); empty_block->SetJoinId(expr->id());
right_block->SetJoinId(expr->RightId()); right_block->SetJoinId(expr->RightId());
subgraph()->set_exit_block(right_block); set_current_block(right_block);
VISIT_FOR_EFFECT(expr->right()); VISIT_FOR_EFFECT(expr->right());
empty_block->Goto(join_block); empty_block->Goto(join_block);
subgraph()->exit_block()->Goto(join_block); current_block()->Goto(join_block);
join_block->SetJoinId(expr->id()); join_block->SetJoinId(expr->id());
subgraph()->set_exit_block(join_block); set_current_block(join_block);
// We did not materialize any value in the predecessor environments, // We did not materialize any value in the predecessor environments,
// so there is no need to handle it here. // so there is no need to handle it here.
} }
......
...@@ -200,13 +200,12 @@ class HSubgraph: public ZoneObject { ...@@ -200,13 +200,12 @@ class HSubgraph: public ZoneObject {
} }
HGraph* graph() const { return graph_; } HGraph* graph() const { return graph_; }
HEnvironment* environment() const { HBasicBlock* entry_block() const { return entry_block_; }
ASSERT(HasExit()); HBasicBlock* exit_block() const { return exit_block_; }
return exit_block_->last_environment(); void set_exit_block(HBasicBlock* block) {
exit_block_ = block;
} }
bool HasExit() const { return exit_block_ != NULL; }
void PreProcessOsrEntry(IterationStatement* statement); void PreProcessOsrEntry(IterationStatement* statement);
void AppendJoin(HSubgraph* then_graph, HSubgraph* else_graph, AstNode* node); void AppendJoin(HSubgraph* then_graph, HSubgraph* else_graph, AstNode* node);
...@@ -237,17 +236,6 @@ class HSubgraph: public ZoneObject { ...@@ -237,17 +236,6 @@ class HSubgraph: public ZoneObject {
entry_block_ = block; entry_block_ = block;
exit_block_ = block; exit_block_ = block;
} }
HBasicBlock* entry_block() const { return entry_block_; }
HBasicBlock* exit_block() const { return exit_block_; }
void set_exit_block(HBasicBlock* block) {
exit_block_ = block;
}
void ConnectExitTo(HBasicBlock* other, bool include_stack_check = false) {
if (HasExit()) {
exit_block()->Goto(other, include_stack_check);
}
}
protected: protected:
HGraph* graph_; // The graph this is a subgraph of. HGraph* graph_; // The graph this is a subgraph of.
...@@ -657,8 +645,13 @@ class HGraphBuilder: public AstVisitor { ...@@ -657,8 +645,13 @@ class HGraphBuilder: public AstVisitor {
BreakAndContinueScope* break_scope() const { return break_scope_; } BreakAndContinueScope* break_scope() const { return break_scope_; }
void set_break_scope(BreakAndContinueScope* head) { break_scope_ = head; } void set_break_scope(BreakAndContinueScope* head) { break_scope_ = head; }
HEnvironment* environment() const { return subgraph()->environment(); } HBasicBlock* current_block() const { return subgraph()->exit_block(); }
HBasicBlock* CurrentBlock() const { return subgraph()->exit_block(); } void set_current_block(HBasicBlock* block) {
subgraph()->set_exit_block(block);
}
HEnvironment* environment() const {
return current_block()->last_environment();
}
// Adding instructions. // Adding instructions.
HInstruction* AddInstruction(HInstruction* instr); HInstruction* AddInstruction(HInstruction* instr);
......
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