From: kmillikin@chromium.org Date: Tue, 22 Feb 2011 10:32:16 +0000 (+0000) Subject: Partial refactoring of subgraphs. X-Git-Tag: upstream/4.7.83~20130 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3c02d036a8d5b3a201bce2f05bc76f5ce53f32ca;p=platform%2Fupstream%2Fv8.git 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 --- diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 6c4035c..db99b89 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -485,16 +485,17 @@ HConstant* HGraph::GetConstantFalse() { void HSubgraph::AppendJoin(HSubgraph* then_graph, HSubgraph* else_graph, 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. HBasicBlock* join_block = graph_->CreateBasicBlock(); then_graph->exit_block()->Goto(join_block); else_graph->exit_block()->Goto(join_block); join_block->SetJoinId(node->id()); exit_block_ = join_block; - } else if (then_graph->HasExit()) { + } else if (then_graph->exit_block() != NULL) { exit_block_ = then_graph->exit_block_; - } else if (else_graph->HasExit()) { + } else if (else_graph->exit_block() != NULL) { exit_block_ = else_graph->exit_block_; } else { exit_block_ = NULL; @@ -526,8 +527,12 @@ HBasicBlock* HSubgraph::JoinBlocks(HBasicBlock* a, HBasicBlock* b, int id) { void HSubgraph::AppendEndless(HSubgraph* body, IterationStatement* statement, HBasicBlock* break_block) { - ConnectExitTo(body->entry_block()); - body->ConnectExitTo(body->entry_block(), true); + if (exit_block() != NULL) { + 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()); exit_block_ = break_block; body->entry_block()->PostProcessLoopHeader(statement); @@ -539,8 +544,12 @@ void HSubgraph::AppendDoWhile(HSubgraph* body, HSubgraph* go_back, HSubgraph* exit, HBasicBlock* break_block) { - ConnectExitTo(body->entry_block()); - go_back->ConnectExitTo(body->entry_block(), true); + if (exit_block() != NULL) { + 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()); exit_block_ = JoinBlocks(exit->exit_block(), break_block, statement->ExitId()); @@ -554,20 +563,26 @@ void HSubgraph::AppendWhile(HSubgraph* condition, HSubgraph* continue_subgraph, HSubgraph* exit, 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()); exit_block_ = JoinBlocks(exit->exit_block(), break_block, statement->ExitId()); 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()); exit_block_ = JoinBlocks(exit_block_, continue_subgraph->exit_block(), statement->ExitId()); } 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); } @@ -588,7 +603,7 @@ void HSubgraph::Append(HSubgraph* next, void HSubgraph::FinishExit(HControlInstruction* instruction) { - ASSERT(HasExit()); + ASSERT(exit_block() != NULL); exit_block_->Finish(instruction); exit_block_->ClearEnvironment(); exit_block_ = NULL; @@ -1936,14 +1951,14 @@ AstContext::~AstContext() { EffectContext::~EffectContext() { ASSERT(owner()->HasStackOverflow() || - !owner()->subgraph()->HasExit() || + owner()->current_block() == NULL || owner()->environment()->length() == original_length_); } ValueContext::~ValueContext() { ASSERT(owner()->HasStackOverflow() || - !owner()->subgraph()->HasExit() || + owner()->current_block() == NULL || owner()->environment()->length() == original_length_ + 1); } @@ -2001,7 +2016,7 @@ void TestContext::BuildBranch(HValue* value) { HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); HTest* test = new HTest(value, empty_true, empty_false); - builder->CurrentBlock()->Finish(test); + builder->current_block()->Finish(test); HValue* const no_return_value = NULL; HBasicBlock* true_target = if_true(); @@ -2017,7 +2032,7 @@ void TestContext::BuildBranch(HValue* value) { } else { 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) { void HGraphBuilder::VisitArgumentList(ZoneList* arguments) { for (int i = 0; i < arguments->length(); 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) { current_subgraph_->Append(body, NULL, NULL); body->entry_block()->SetJoinId(info->function()->id()); - if (graph_->HasExit()) { + if (graph()->exit_block() != NULL) { graph_->FinishExit(new HReturn(graph_->GetConstantUndefined())); } } @@ -2219,21 +2234,21 @@ void HGraphBuilder::AddToSubgraph(HSubgraph* graph, HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { - ASSERT(current_subgraph_->HasExit()); - current_subgraph_->exit_block()->AddInstruction(instr); + ASSERT(current_block() != NULL); + current_block()->AddInstruction(instr); return instr; } void HGraphBuilder::AddSimulate(int id) { - ASSERT(current_subgraph_->HasExit()); - current_subgraph_->exit_block()->AddSimulate(id); + ASSERT(current_block() != NULL); + current_block()->AddSimulate(id); } void HGraphBuilder::AddPhi(HPhi* instr) { - ASSERT(current_subgraph_->HasExit()); - current_subgraph_->exit_block()->AddPhi(instr); + ASSERT(current_block() != NULL); + current_block()->AddPhi(instr); } @@ -2296,7 +2311,7 @@ void HGraphBuilder::SetupScope(Scope* scope) { void HGraphBuilder::VisitStatements(ZoneList* statements) { for (int i = 0; i < statements->length(); 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( void HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { HBasicBlock* continue_block = break_scope()->Get(stmt->target(), CONTINUE); - subgraph()->exit_block()->Goto(continue_block); - subgraph()->set_exit_block(NULL); + current_block()->Goto(continue_block); + set_current_block(NULL); } void HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { HBasicBlock* break_block = break_scope()->Get(stmt->target(), BREAK); - subgraph()->exit_block()->Goto(break_block); - subgraph()->set_exit_block(NULL); + current_block()->Goto(break_block); + set_current_block(NULL); } @@ -2472,9 +2487,9 @@ void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { VISIT_FOR_VALUE(stmt->expression()); return_value = environment()->Pop(); } - subgraph()->exit_block()->AddLeaveInlined(return_value, + current_block()->AddLeaveInlined(return_value, function_return_); - subgraph()->set_exit_block(NULL); + set_current_block(NULL); } } } @@ -2495,7 +2510,7 @@ HCompare* HGraphBuilder::BuildSwitchCompare(HSubgraph* subgraph, CaseClause* clause) { AddToSubgraph(subgraph, clause->label()); 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, clause_value, Token::EQ_STRICT); @@ -2576,7 +2591,7 @@ void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { // 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 // 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_) { last_false_block = graph()->CreateBasicBlock(); HBasicBlock* empty = graph()->CreateBasicBlock(); @@ -2619,7 +2634,7 @@ void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { } // 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(); previous_subgraph->exit_block()-> Finish(new HGoto(subgraph->entry_block())); @@ -2641,7 +2656,7 @@ void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { // If the last statement block has a fall-through, connect it to the // 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)); } @@ -2651,9 +2666,9 @@ void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { } if (single_exit_block->HasPredecessor()) { - current_subgraph_->set_exit_block(single_exit_block); + set_current_block(single_exit_block); } else { - current_subgraph_->set_exit_block(NULL); + set_current_block(NULL); } } @@ -2695,7 +2710,7 @@ void HSubgraph::PreProcessOsrEntry(IterationStatement* statement) { void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { - ASSERT(subgraph()->HasExit()); + ASSERT(current_block() != NULL); subgraph()->PreProcessOsrEntry(stmt); HSubgraph* body_graph = CreateLoopHeaderSubgraph(environment()); @@ -2705,7 +2720,7 @@ void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { } 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()); } else { HSubgraph* go_back = CreateEmptySubgraph(); @@ -2730,7 +2745,7 @@ bool HGraphBuilder::ShouldPeel(HSubgraph* cond, HSubgraph* body) { void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { - ASSERT(subgraph()->HasExit()); + ASSERT(current_block() != NULL); subgraph()->PreProcessOsrEntry(stmt); HSubgraph* cond_graph = NULL; @@ -2776,12 +2791,12 @@ void HGraphBuilder::AppendPeeledWhile(IterationStatement* stmt, HSubgraph* exit_graph, HBasicBlock* break_block) { HSubgraph* loop = NULL; - if (body_graph->HasExit() && stmt != peeled_statement_ && + if (body_graph->exit_block() != NULL && stmt != peeled_statement_ && ShouldPeel(cond_graph, body_graph)) { // Save the last peeled iteration statement to prevent infinite recursion. IterationStatement* outer_peeled_statement = peeled_statement_; peeled_statement_ = stmt; - loop = CreateGotoSubgraph(body_graph->environment()); + loop = CreateGotoSubgraph(body_graph->exit_block()->last_environment()); ADD_TO_SUBGRAPH(loop, stmt); peeled_statement_ = outer_peeled_statement; } @@ -2796,7 +2811,7 @@ void HGraphBuilder::VisitForStatement(ForStatement* stmt) { Visit(stmt->init()); CHECK_BAILOUT; } - ASSERT(subgraph()->HasExit()); + ASSERT(current_block() != NULL); subgraph()->PreProcessOsrEntry(stmt); HSubgraph* cond_graph = NULL; @@ -2825,8 +2840,9 @@ void HGraphBuilder::VisitForStatement(ForStatement* stmt) { HSubgraph* next_graph = NULL; body_graph->ResolveContinue(stmt, break_info.continue_block()); - if (stmt->next() != NULL && body_graph->HasExit()) { - next_graph = CreateGotoSubgraph(body_graph->environment()); + if (stmt->next() != NULL && body_graph->exit_block() != NULL) { + next_graph = + CreateGotoSubgraph(body_graph->exit_block()->last_environment()); ADD_TO_SUBGRAPH(next_graph, stmt->next()); body_graph->Append(next_graph, NULL, NULL); next_graph->entry_block()->SetJoinId(stmt->ContinueId()); @@ -3103,9 +3119,9 @@ HBasicBlock* HGraphBuilder::BuildTypeSwitch(HValue* receiver, maps->at(i), if_true->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. // There is no need to merge it at the join block only to discard it. if (ast_context()->IsEffect()) { @@ -3114,15 +3130,15 @@ HBasicBlock* HGraphBuilder::BuildTypeSwitch(HValue* receiver, 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. - if (subgraph()->HasExit()) { + if (current_block() != NULL) { if (ast_context()->IsEffect()) { environment()->Drop(1); } - subgraph()->exit_block()->Goto(join_block); + current_block()->Goto(join_block); } if (join_block->predecessors()->is_empty()) return NULL; @@ -3279,10 +3295,10 @@ void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr, HBasicBlock* new_exit_block = 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 // 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()); } } @@ -3613,10 +3629,10 @@ void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, HBasicBlock* new_exit_block = 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 // 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()); } } @@ -3973,7 +3989,7 @@ void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr, HBasicBlock* new_exit_block = 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 // predecessor environments so there's no need to handle it here. if (new_exit_block != NULL && !ast_context()->IsEffect()) { @@ -4142,7 +4158,7 @@ bool HGraphBuilder::TryInline(Call* expr) { 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 // test context, undefined is false. HValue* return_value = graph()->GetConstantUndefined(); @@ -4171,7 +4187,7 @@ bool HGraphBuilder::TryInline(Call* expr) { AddSimulate(expr->ReturnId()); // 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. if (test_context != NULL) { @@ -4201,11 +4217,11 @@ bool HGraphBuilder::TryInline(Call* expr) { // 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 // flow to handle. - subgraph()->set_exit_block(NULL); + set_current_block(NULL); } else { function_return_->SetJoinId(expr->id()); - subgraph()->set_exit_block(function_return_); + set_current_block(function_return_); } call_context_ = saved_call_context; @@ -4434,7 +4450,7 @@ void HGraphBuilder::VisitCall(Call* expr) { AddCheckConstantFunction(expr, receiver, receiver_map, true); if (TryInline(expr)) { - if (subgraph()->HasExit()) { + if (current_block() != NULL) { HValue* return_value = Pop(); // 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 @@ -4505,7 +4521,7 @@ void HGraphBuilder::VisitCall(Call* expr) { environment()->SetExpressionStackAt(receiver_index, global_receiver); if (TryInline(expr)) { - if (subgraph()->HasExit()) { + if (current_block() != NULL) { HValue* return_value = Pop(); // 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 @@ -4673,10 +4689,12 @@ void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { false_graph->entry_block(), true_graph->entry_block()); 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->environment()->Push(graph_->GetConstantFalse()); + false_graph->exit_block()->last_environment()->Push( + graph_->GetConstantFalse()); current_subgraph_->AppendJoin(true_graph, false_graph, expr); ast_context()->ReturnValue(Pop()); @@ -4973,12 +4991,12 @@ void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { // Translate right subexpression by visiting it in the same AST // context as the entire expression. - subgraph()->set_exit_block(eval_right); + set_current_block(eval_right); Visit(expr->right()); } else if (ast_context()->IsValue()) { VISIT_FOR_VALUE(expr->left()); - ASSERT(current_subgraph_->HasExit()); + ASSERT(current_block() != NULL); HValue* left = Top(); HEnvironment* environment_copy = environment()->Copy(); @@ -4987,7 +5005,8 @@ void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { right_subgraph = CreateBranchSubgraph(environment_copy); 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. HBasicBlock* empty_block = graph()->CreateBasicBlock(); HBasicBlock* join_block = graph()->CreateBasicBlock(); @@ -4995,11 +5014,11 @@ void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { HTest* test = is_logical_and ? new HTest(left, right_subgraph->entry_block(), empty_block) : new HTest(left, empty_block, right_subgraph->entry_block()); - subgraph()->exit_block()->Finish(test); + current_block()->Finish(test); empty_block->Goto(join_block); right_subgraph->exit_block()->Goto(join_block); join_block->SetJoinId(expr->id()); - subgraph()->set_exit_block(join_block); + set_current_block(join_block); ast_context()->ReturnValue(Pop()); } else { ASSERT(ast_context()->IsEffect()); @@ -5021,13 +5040,13 @@ void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { // no good AST ID to put on that first HSimulate. empty_block->SetJoinId(expr->id()); right_block->SetJoinId(expr->RightId()); - subgraph()->set_exit_block(right_block); + set_current_block(right_block); VISIT_FOR_EFFECT(expr->right()); empty_block->Goto(join_block); - subgraph()->exit_block()->Goto(join_block); + current_block()->Goto(join_block); 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, // so there is no need to handle it here. } diff --git a/src/hydrogen.h b/src/hydrogen.h index 8a5e8df..e6e3a02 100644 --- a/src/hydrogen.h +++ b/src/hydrogen.h @@ -200,13 +200,12 @@ class HSubgraph: public ZoneObject { } HGraph* graph() const { return graph_; } - HEnvironment* environment() const { - ASSERT(HasExit()); - return exit_block_->last_environment(); + HBasicBlock* entry_block() const { return entry_block_; } + HBasicBlock* exit_block() const { return exit_block_; } + void set_exit_block(HBasicBlock* block) { + exit_block_ = block; } - bool HasExit() const { return exit_block_ != NULL; } - void PreProcessOsrEntry(IterationStatement* statement); void AppendJoin(HSubgraph* then_graph, HSubgraph* else_graph, AstNode* node); @@ -237,17 +236,6 @@ class HSubgraph: public ZoneObject { entry_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: HGraph* graph_; // The graph this is a subgraph of. @@ -657,8 +645,13 @@ class HGraphBuilder: public AstVisitor { BreakAndContinueScope* break_scope() const { return break_scope_; } void set_break_scope(BreakAndContinueScope* head) { break_scope_ = head; } - HEnvironment* environment() const { return subgraph()->environment(); } - HBasicBlock* CurrentBlock() const { return subgraph()->exit_block(); } + HBasicBlock* current_block() 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. HInstruction* AddInstruction(HInstruction* instr);