Remove some more uses of subgraphs and more cleanup of the graph builder.

Do not use subgraphs to implement the translation of simple branching
control flow, for the function body entry, or for labeled blocks.

Combine all the loop construction functions into a single one.

Resolve a possible problem with duplicate AST IDs used both for joined loop
break blocks, the normal loop exit, and for their common successor, by never
introducing the extra (successor) block and instead making the normal loop
exit a predecessor of the break join block.  There is a similar issue with
joined continue blocks.

Remove a (never needed) two-element zone list per each time we replace one
hydrogen value with another.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7027 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
kmillikin@chromium.org 2011-03-02 14:09:59 +00:00
parent 9390c69a54
commit d6a041b8f9
3 changed files with 182 additions and 231 deletions

View File

@ -285,24 +285,19 @@ void HValue::SetOperandAt(int index, HValue* value) {
void HValue::ReplaceAndDelete(HValue* other) { void HValue::ReplaceAndDelete(HValue* other) {
ReplaceValue(other); if (other != NULL) ReplaceValue(other);
Delete(); Delete();
} }
void HValue::ReplaceValue(HValue* other) { void HValue::ReplaceValue(HValue* other) {
ZoneList<HValue*> start_uses(2);
for (int i = 0; i < uses_.length(); ++i) { for (int i = 0; i < uses_.length(); ++i) {
HValue* use = uses_.at(i); HValue* use = uses_[i];
if (!use->block()->IsStartBlock()) { ASSERT(!use->block()->IsStartBlock());
InternalReplaceAtUse(use, other); InternalReplaceAtUse(use, other);
other->uses_.Add(use); other->uses_.Add(use);
} else {
start_uses.Add(use);
}
} }
uses_.Clear(); uses_.Rewind(0);
uses_.AddAll(start_uses);
} }

View File

@ -503,48 +503,27 @@ HBasicBlock* HGraphBuilder::JoinContinue(IterationStatement* statement,
HBasicBlock* exit_block, HBasicBlock* exit_block,
HBasicBlock* continue_block) { HBasicBlock* continue_block) {
if (continue_block != NULL) { if (continue_block != NULL) {
if (exit_block != NULL) exit_block->Goto(continue_block);
continue_block->SetJoinId(statement->ContinueId()); continue_block->SetJoinId(statement->ContinueId());
return continue_block;
} }
return CreateJoin(exit_block, continue_block, statement->ContinueId()); return exit_block;
} }
HBasicBlock* HGraphBuilder::CreateEndless(IterationStatement* statement, HBasicBlock* HGraphBuilder::CreateLoop(IterationStatement* statement,
HBasicBlock* body_entry, HBasicBlock* loop_entry,
HBasicBlock* body_exit, HBasicBlock* body_exit,
HBasicBlock* break_block) { HBasicBlock* loop_successor,
if (body_exit != NULL) body_exit->Goto(body_entry, true); HBasicBlock* break_block) {
if (break_block != NULL) break_block->SetJoinId(statement->ExitId());
body_entry->PostProcessLoopHeader(statement);
return break_block;
}
HBasicBlock* HGraphBuilder::CreateDoWhile(IterationStatement* statement,
HBasicBlock* body_entry,
HBasicBlock* go_back,
HBasicBlock* exit_block,
HBasicBlock* break_block) {
if (go_back != NULL) go_back->Goto(body_entry, true);
if (break_block != NULL) break_block->SetJoinId(statement->ExitId());
HBasicBlock* new_exit =
CreateJoin(exit_block, break_block, statement->ExitId());
body_entry->PostProcessLoopHeader(statement);
return new_exit;
}
HBasicBlock* HGraphBuilder::CreateWhile(IterationStatement* statement,
HBasicBlock* loop_entry,
HBasicBlock* cond_false,
HBasicBlock* body_exit,
HBasicBlock* break_block) {
if (break_block != NULL) break_block->SetJoinId(statement->ExitId());
HBasicBlock* new_exit =
CreateJoin(cond_false, break_block, statement->ExitId());
if (body_exit != NULL) body_exit->Goto(loop_entry, true); if (body_exit != NULL) body_exit->Goto(loop_entry, true);
loop_entry->PostProcessLoopHeader(statement); loop_entry->PostProcessLoopHeader(statement);
return new_exit; if (break_block != NULL) {
if (loop_successor != NULL) loop_successor->Goto(break_block);
break_block->SetJoinId(statement->ExitId());
return break_block;
}
return loop_successor;
} }
@ -621,20 +600,14 @@ HBasicBlock* HGraph::CreateBasicBlock() {
void HGraph::Canonicalize() { void HGraph::Canonicalize() {
if (!FLAG_use_canonicalizing) return;
HPhase phase("Canonicalize", this); HPhase phase("Canonicalize", this);
if (FLAG_use_canonicalizing) { for (int i = 0; i < blocks()->length(); ++i) {
for (int i = 0; i < blocks()->length(); ++i) { HInstruction* instr = blocks()->at(i)->first();
HBasicBlock* b = blocks()->at(i); while (instr != NULL) {
for (HInstruction* insn = b->first(); insn != NULL; insn = insn->next()) { HValue* value = instr->Canonicalize();
HValue* value = insn->Canonicalize(); if (value != instr) instr->ReplaceAndDelete(value);
if (value != insn) { instr = instr->next();
if (value != NULL) {
insn->ReplaceAndDelete(value);
} else {
insn->Delete();
}
}
}
} }
} }
} }
@ -1390,8 +1363,7 @@ void HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, HValueMap* map) {
instr->Mnemonic(), instr->Mnemonic(),
other->id(), other->id(),
other->Mnemonic()); other->Mnemonic());
instr->ReplaceValue(other); instr->ReplaceAndDelete(other);
instr->Delete();
} else { } else {
map->Add(instr); map->Add(instr);
} }
@ -2096,68 +2068,86 @@ void HGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs) {
HGraph* HGraphBuilder::CreateGraph(CompilationInfo* info) { HGraph* HGraphBuilder::CreateGraph(CompilationInfo* info) {
ASSERT(current_subgraph_ == NULL); ASSERT(subgraph() == NULL);
graph_ = new HGraph(info); graph_ = new HGraph(info);
{ {
HPhase phase("Block building"); HPhase phase("Block building");
graph_->Initialize(CreateBasicBlock(graph_->start_environment())); graph()->Initialize(CreateBasicBlock(graph()->start_environment()));
current_subgraph_ = graph_; current_subgraph_ = graph();
Scope* scope = info->scope(); Scope* scope = info->scope();
if (scope->HasIllegalRedeclaration()) {
Bailout("function with illegal redeclaration");
return NULL;
}
SetupScope(scope); SetupScope(scope);
VisitDeclarations(scope->declarations()); VisitDeclarations(scope->declarations());
AddInstruction(new HStackCheck()); AddInstruction(new HStackCheck());
ZoneList<Statement*>* stmts = info->function()->body(); // Add an edge to the body entry. This is warty: the graph's start
HSubgraph* body = CreateGotoSubgraph(environment()); // environment will be used by the Lithium translation as the initial
current_block()->Goto(body->entry_block()); // environment on graph entry, but it has now been mutated by the
AddToSubgraph(body, stmts); // Hydrogen translation of the instructions in the start block. This
// environment uses values which have not been defined yet. These
// Hydrogen instructions will then be replayed by the Lithium
// translation, so they cannot have an environment effect. The edge to
// the body's entry block (along with some special logic for the start
// block in HInstruction::InsertAfter) seals the start block from
// getting unwanted instructions inserted.
//
// TODO(kmillikin): Fix this. Stop mutating the initial environment.
// Make the Hydrogen instructions in the initial block into Hydrogen
// values (but not instructions), present in the initial environment and
// not replayed by the Lithium translation.
HEnvironment* initial_env = environment()->CopyWithoutHistory();
HBasicBlock* body_entry = CreateBasicBlock(initial_env);
current_block()->Goto(body_entry);
body_entry->SetJoinId(info->function()->id());
set_current_block(body_entry);
VisitStatements(info->function()->body());
if (HasStackOverflow()) return NULL; if (HasStackOverflow()) return NULL;
body->entry_block()->SetJoinId(info->function()->id());
set_current_block(body->exit_block());
if (graph()->exit_block() != NULL) { if (current_block() != NULL) {
HReturn* instr = new HReturn(graph()->GetConstantUndefined()); HReturn* instr = new HReturn(graph()->GetConstantUndefined());
graph()->exit_block()->FinishExit(instr); current_block()->FinishExit(instr);
graph()->set_exit_block(NULL); set_current_block(NULL);
} }
} }
graph_->OrderBlocks(); graph()->OrderBlocks();
graph_->AssignDominators(); graph()->AssignDominators();
graph_->EliminateRedundantPhis(); graph()->EliminateRedundantPhis();
if (!graph_->CollectPhis()) { if (!graph()->CollectPhis()) {
Bailout("Phi-use of arguments object"); Bailout("Phi-use of arguments object");
return NULL; return NULL;
} }
HInferRepresentation rep(graph_); HInferRepresentation rep(graph());
rep.Analyze(); rep.Analyze();
if (FLAG_use_range) { if (FLAG_use_range) {
HRangeAnalysis rangeAnalysis(graph_); HRangeAnalysis rangeAnalysis(graph());
rangeAnalysis.Analyze(); rangeAnalysis.Analyze();
} }
graph_->InitializeInferredTypes(); graph()->InitializeInferredTypes();
graph_->Canonicalize(); graph()->Canonicalize();
graph_->InsertRepresentationChanges(); graph()->InsertRepresentationChanges();
graph_->ComputeMinusZeroChecks(); graph()->ComputeMinusZeroChecks();
// Eliminate redundant stack checks on backwards branches. // Eliminate redundant stack checks on backwards branches.
HStackCheckEliminator sce(graph_); HStackCheckEliminator sce(graph());
sce.Process(); sce.Process();
// Perform common subexpression elimination and loop-invariant code motion. // Perform common subexpression elimination and loop-invariant code motion.
if (FLAG_use_gvn) { if (FLAG_use_gvn) {
HPhase phase("Global value numbering", graph_); HPhase phase("Global value numbering", graph());
HGlobalValueNumberer gvn(graph_); HGlobalValueNumberer gvn(graph());
gvn.Analyze(); gvn.Analyze();
} }
return graph_; return graph();
} }
@ -2285,14 +2275,6 @@ HSubgraph* HGraphBuilder::CreateInlinedSubgraph(HEnvironment* outer,
} }
HSubgraph* HGraphBuilder::CreateGotoSubgraph(HEnvironment* env) {
HSubgraph* subgraph = new HSubgraph(graph());
HEnvironment* new_env = env->CopyWithoutHistory();
subgraph->Initialize(CreateBasicBlock(new_env));
return subgraph;
}
HSubgraph* HGraphBuilder::CreateEmptySubgraph() { HSubgraph* HGraphBuilder::CreateEmptySubgraph() {
HSubgraph* subgraph = new HSubgraph(graph()); HSubgraph* subgraph = new HSubgraph(graph());
subgraph->Initialize(graph()->CreateBasicBlock()); subgraph->Initialize(graph()->CreateBasicBlock());
@ -2308,7 +2290,7 @@ HSubgraph* HGraphBuilder::CreateBranchSubgraph(HEnvironment* env) {
} }
HBasicBlock* HGraphBuilder::CreateLoopHeader() { HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() {
HBasicBlock* header = graph()->CreateBasicBlock(); HBasicBlock* header = graph()->CreateBasicBlock();
HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); HEnvironment* entry_env = environment()->CopyAsLoopHeader(header);
header->SetInitialEnvironment(entry_env); header->SetInitialEnvironment(entry_env);
@ -2318,21 +2300,16 @@ HBasicBlock* HGraphBuilder::CreateLoopHeader() {
void HGraphBuilder::VisitBlock(Block* stmt) { void HGraphBuilder::VisitBlock(Block* stmt) {
if (stmt->labels() != NULL) { BreakAndContinueInfo break_info(stmt);
HSubgraph* block_graph = CreateGotoSubgraph(environment()); { BreakAndContinueScope push(&break_info, this);
current_block()->Goto(block_graph->entry_block());
block_graph->entry_block()->SetJoinId(stmt->EntryId());
BreakAndContinueInfo break_info(stmt);
{ BreakAndContinueScope push(&break_info, this);
ADD_TO_SUBGRAPH(block_graph, stmt->statements());
}
HBasicBlock* break_block = break_info.break_block();
if (break_block != NULL) break_block->SetJoinId(stmt->EntryId());
set_current_block(CreateJoin(block_graph->exit_block(),
break_block,
stmt->ExitId()));
} else {
VisitStatements(stmt->statements()); VisitStatements(stmt->statements());
CHECK_BAILOUT;
}
HBasicBlock* break_block = break_info.break_block();
if (break_block != NULL) {
if (current_block() != NULL) current_block()->Goto(break_block);
break_block->SetJoinId(stmt->ExitId());
set_current_block(break_block);
} }
} }
@ -2354,21 +2331,23 @@ void HGraphBuilder::VisitIfStatement(IfStatement* stmt) {
AddSimulate(stmt->ElseId()); AddSimulate(stmt->ElseId());
Visit(stmt->else_statement()); Visit(stmt->else_statement());
} else { } else {
HSubgraph* then_graph = CreateEmptySubgraph(); HBasicBlock* cond_true = graph()->CreateBasicBlock();
HSubgraph* else_graph = CreateEmptySubgraph(); HBasicBlock* cond_false = graph()->CreateBasicBlock();
VISIT_FOR_CONTROL(stmt->condition(), VISIT_FOR_CONTROL(stmt->condition(), cond_true, cond_false);
then_graph->entry_block(), cond_true->SetJoinId(stmt->ThenId());
else_graph->entry_block()); cond_false->SetJoinId(stmt->ElseId());
then_graph->entry_block()->SetJoinId(stmt->ThenId()); set_current_block(cond_true);
ADD_TO_SUBGRAPH(then_graph, stmt->then_statement()); Visit(stmt->then_statement());
CHECK_BAILOUT;
HBasicBlock* other = current_block();
else_graph->entry_block()->SetJoinId(stmt->ElseId()); set_current_block(cond_false);
ADD_TO_SUBGRAPH(else_graph, stmt->else_statement()); Visit(stmt->else_statement());
CHECK_BAILOUT;
set_current_block(CreateJoin(then_graph->exit_block(), HBasicBlock* join = CreateJoin(other, current_block(), stmt->id());
else_graph->exit_block(), set_current_block(join);
stmt->id()));
} }
} }
@ -2670,7 +2649,7 @@ void HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) {
void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
ASSERT(current_block() != NULL); ASSERT(current_block() != NULL);
PreProcessOsrEntry(stmt); PreProcessOsrEntry(stmt);
HBasicBlock* loop_entry = CreateLoopHeader(); HBasicBlock* loop_entry = CreateLoopHeaderBlock();
current_block()->Goto(loop_entry, false); current_block()->Goto(loop_entry, false);
set_current_block(loop_entry); set_current_block(loop_entry);
@ -2681,25 +2660,22 @@ void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
} }
HBasicBlock* body_exit = HBasicBlock* body_exit =
JoinContinue(stmt, current_block(), break_info.continue_block()); JoinContinue(stmt, current_block(), break_info.continue_block());
HBasicBlock* loop_exit = NULL; HBasicBlock* loop_successor = NULL;
if (body_exit == NULL || stmt->cond()->ToBooleanIsTrue()) { if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) {
loop_exit = CreateEndless(stmt,
loop_entry,
body_exit,
break_info.break_block());
} else {
set_current_block(body_exit); set_current_block(body_exit);
HBasicBlock* cond_true = graph()->CreateBasicBlock(); // The block for a true condition, the actual predecessor block of the
HBasicBlock* cond_false = graph()->CreateBasicBlock(); // back edge.
VISIT_FOR_CONTROL(stmt->cond(), cond_true, cond_false); body_exit = graph()->CreateBasicBlock();
cond_true->SetJoinId(stmt->BackEdgeId()); loop_successor = graph()->CreateBasicBlock();
cond_false->SetJoinId(stmt->ExitId()); VISIT_FOR_CONTROL(stmt->cond(), body_exit, loop_successor);
loop_exit = CreateDoWhile(stmt, body_exit->SetJoinId(stmt->BackEdgeId());
loop_entry, loop_successor->SetJoinId(stmt->ExitId());
cond_true,
cond_false,
break_info.break_block());
} }
HBasicBlock* loop_exit = CreateLoop(stmt,
loop_entry,
body_exit,
loop_successor,
break_info.break_block());
set_current_block(loop_exit); set_current_block(loop_exit);
} }
@ -2707,19 +2683,19 @@ void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
ASSERT(current_block() != NULL); ASSERT(current_block() != NULL);
PreProcessOsrEntry(stmt); PreProcessOsrEntry(stmt);
HBasicBlock* loop_entry = CreateLoopHeader(); HBasicBlock* loop_entry = CreateLoopHeaderBlock();
current_block()->Goto(loop_entry, false); current_block()->Goto(loop_entry, false);
set_current_block(loop_entry); set_current_block(loop_entry);
// If the condition is constant true, do not generate a branch. // If the condition is constant true, do not generate a branch.
HBasicBlock* cond_false = NULL; HBasicBlock* loop_successor = NULL;
if (!stmt->cond()->ToBooleanIsTrue()) { if (!stmt->cond()->ToBooleanIsTrue()) {
HBasicBlock* cond_true = graph()->CreateBasicBlock(); HBasicBlock* body_entry = graph()->CreateBasicBlock();
cond_false = graph()->CreateBasicBlock(); loop_successor = graph()->CreateBasicBlock();
VISIT_FOR_CONTROL(stmt->cond(), cond_true, cond_false); VISIT_FOR_CONTROL(stmt->cond(), body_entry, loop_successor);
cond_true->SetJoinId(stmt->BodyId()); body_entry->SetJoinId(stmt->BodyId());
cond_false->SetJoinId(stmt->ExitId()); loop_successor->SetJoinId(stmt->ExitId());
set_current_block(cond_true); set_current_block(body_entry);
} }
BreakAndContinueInfo break_info(stmt); BreakAndContinueInfo break_info(stmt);
@ -2729,44 +2705,34 @@ void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
} }
HBasicBlock* body_exit = HBasicBlock* body_exit =
JoinContinue(stmt, current_block(), break_info.continue_block()); JoinContinue(stmt, current_block(), break_info.continue_block());
HBasicBlock* loop_exit = NULL; HBasicBlock* loop_exit = CreateLoop(stmt,
if (stmt->cond()->ToBooleanIsTrue()) { loop_entry,
// TODO(fschneider): Implement peeling for endless loops as well. body_exit,
loop_exit = CreateEndless(stmt, loop_successor,
loop_entry, break_info.break_block());
body_exit,
break_info.break_block());
} else {
loop_exit = CreateWhile(stmt,
loop_entry,
cond_false,
body_exit,
break_info.break_block());
}
set_current_block(loop_exit); set_current_block(loop_exit);
} }
void HGraphBuilder::VisitForStatement(ForStatement* stmt) { void HGraphBuilder::VisitForStatement(ForStatement* stmt) {
// Only visit the init statement in the peeled part of the loop. if (stmt->init() != NULL) {
if (stmt->init() != NULL && peeled_statement_ != stmt) {
Visit(stmt->init()); Visit(stmt->init());
CHECK_BAILOUT; CHECK_BAILOUT;
} }
ASSERT(current_block() != NULL); ASSERT(current_block() != NULL);
PreProcessOsrEntry(stmt); PreProcessOsrEntry(stmt);
HBasicBlock* loop_entry = CreateLoopHeader(); HBasicBlock* loop_entry = CreateLoopHeaderBlock();
current_block()->Goto(loop_entry, false); current_block()->Goto(loop_entry, false);
set_current_block(loop_entry); set_current_block(loop_entry);
HBasicBlock* cond_false = NULL; HBasicBlock* loop_successor = NULL;
if (stmt->cond() != NULL) { if (stmt->cond() != NULL) {
HBasicBlock* cond_true = graph()->CreateBasicBlock(); HBasicBlock* body_entry = graph()->CreateBasicBlock();
cond_false = graph()->CreateBasicBlock(); loop_successor = graph()->CreateBasicBlock();
VISIT_FOR_CONTROL(stmt->cond(), cond_true, cond_false); VISIT_FOR_CONTROL(stmt->cond(), body_entry, loop_successor);
cond_true->SetJoinId(stmt->BodyId()); body_entry->SetJoinId(stmt->BodyId());
cond_false->SetJoinId(stmt->ExitId()); loop_successor->SetJoinId(stmt->ExitId());
set_current_block(cond_true); set_current_block(body_entry);
} }
BreakAndContinueInfo break_info(stmt); BreakAndContinueInfo break_info(stmt);
@ -2784,19 +2750,11 @@ void HGraphBuilder::VisitForStatement(ForStatement* stmt) {
body_exit = current_block(); body_exit = current_block();
} }
HBasicBlock* loop_exit = NULL; HBasicBlock* loop_exit = CreateLoop(stmt,
if (stmt->cond() == NULL) { loop_entry,
loop_exit = CreateEndless(stmt, body_exit,
loop_entry, loop_successor,
body_exit, break_info.break_block());
break_info.break_block());
} else {
loop_exit = CreateWhile(stmt,
loop_entry,
cond_false,
body_exit,
break_info.break_block());
}
set_current_block(loop_exit); set_current_block(loop_exit);
} }
@ -2838,21 +2796,23 @@ void HGraphBuilder::VisitSharedFunctionInfoLiteral(
void HGraphBuilder::VisitConditional(Conditional* expr) { void HGraphBuilder::VisitConditional(Conditional* expr) {
HSubgraph* then_graph = CreateEmptySubgraph(); HBasicBlock* cond_true = graph()->CreateBasicBlock();
HSubgraph* else_graph = CreateEmptySubgraph(); HBasicBlock* cond_false = graph()->CreateBasicBlock();
VISIT_FOR_CONTROL(expr->condition(), VISIT_FOR_CONTROL(expr->condition(), cond_true, cond_false);
then_graph->entry_block(), cond_true->SetJoinId(expr->ThenId());
else_graph->entry_block()); cond_false->SetJoinId(expr->ElseId());
then_graph->entry_block()->SetJoinId(expr->ThenId()); // TOOD(kmillikin): Visit the subexpressions in the same AST context as
ADD_TO_SUBGRAPH(then_graph, expr->then_expression()); // the whole expression.
set_current_block(cond_true);
VISIT_FOR_VALUE(expr->then_expression());
HBasicBlock* other = current_block();
else_graph->entry_block()->SetJoinId(expr->ElseId()); set_current_block(cond_false);
ADD_TO_SUBGRAPH(else_graph, expr->else_expression()); VISIT_FOR_VALUE(expr->else_expression());
set_current_block(CreateJoin(then_graph->exit_block(), HBasicBlock* join = CreateJoin(other, current_block(), expr->id());
else_graph->exit_block(), set_current_block(join);
expr->id()));
ast_context()->ReturnValue(Pop()); ast_context()->ReturnValue(Pop());
} }
@ -4638,26 +4598,26 @@ void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
context->if_false(), context->if_false(),
context->if_true()); context->if_true());
} else if (ast_context()->IsValue()) { } else if (ast_context()->IsValue()) {
HSubgraph* true_graph = CreateEmptySubgraph(); HBasicBlock* materialize_false = graph()->CreateBasicBlock();
HSubgraph* false_graph = CreateEmptySubgraph(); HBasicBlock* materialize_true = graph()->CreateBasicBlock();
VISIT_FOR_CONTROL(expr->expression(), VISIT_FOR_CONTROL(expr->expression(),
false_graph->entry_block(), materialize_false,
true_graph->entry_block()); materialize_true);
true_graph->entry_block()->SetJoinId(expr->expression()->id()); materialize_false->SetJoinId(expr->expression()->id());
true_graph->exit_block()->last_environment()->Push( materialize_true->SetJoinId(expr->expression()->id());
graph_->GetConstantTrue());
false_graph->entry_block()->SetJoinId(expr->expression()->id()); set_current_block(materialize_false);
false_graph->exit_block()->last_environment()->Push( Push(graph()->GetConstantFalse());
graph_->GetConstantFalse()); set_current_block(materialize_true);
Push(graph()->GetConstantTrue());
set_current_block(CreateJoin(true_graph->exit_block(), HBasicBlock* join =
false_graph->exit_block(), CreateJoin(materialize_false, materialize_true, expr->id());
expr->id())); set_current_block(join);
ast_context()->ReturnValue(Pop()); ast_context()->ReturnValue(Pop());
} else { } else {
ASSERT(ast_context()->IsEffect()); ASSERT(ast_context()->IsEffect());
VISIT_FOR_EFFECT(expr->expression()); VisitForEffect(expr->expression());
} }
} else if (op == Token::BIT_NOT || op == Token::SUB) { } else if (op == Token::BIT_NOT || op == Token::SUB) {

View File

@ -605,7 +605,6 @@ class HGraphBuilder: public AstVisitor {
: oracle_(oracle), : oracle_(oracle),
graph_(NULL), graph_(NULL),
current_subgraph_(NULL), current_subgraph_(NULL),
peeled_statement_(NULL),
ast_context_(NULL), ast_context_(NULL),
call_context_(NULL), call_context_(NULL),
function_return_(NULL), function_return_(NULL),
@ -676,25 +675,24 @@ class HGraphBuilder: public AstVisitor {
HBasicBlock* CreateJoin(HBasicBlock* first, HBasicBlock* CreateJoin(HBasicBlock* first,
HBasicBlock* second, HBasicBlock* second,
int join_id); int join_id);
HBasicBlock* CreateWhile(IterationStatement* statement,
HBasicBlock* loop_entry, // Create a back edge in the flow graph. body_exit is the predecessor
HBasicBlock* cond_false, // block and loop_entry is the successor block. loop_successor is the
HBasicBlock* body_exit, // block where control flow exits the loop normally (e.g., via failure of
HBasicBlock* break_block); // the condition) and break_block is the block where control flow breaks
HBasicBlock* CreateDoWhile(IterationStatement* statement, // from the loop. All blocks except loop_entry can be NULL. The return
HBasicBlock* body_entry, // value is the new successor block which is the join of loop_successor
HBasicBlock* go_back, // and break_block, or NULL.
HBasicBlock* exit_block, HBasicBlock* CreateLoop(IterationStatement* statement,
HBasicBlock* break_block); HBasicBlock* loop_entry,
HBasicBlock* CreateEndless(IterationStatement* statement, HBasicBlock* body_exit,
HBasicBlock* body_entry, HBasicBlock* loop_successor,
HBasicBlock* body_exit, HBasicBlock* break_block);
HBasicBlock* break_block);
HBasicBlock* JoinContinue(IterationStatement* statement, HBasicBlock* JoinContinue(IterationStatement* statement,
HBasicBlock* exit_block, HBasicBlock* exit_block,
HBasicBlock* continue_block); HBasicBlock* continue_block);
void AddToSubgraph(HSubgraph* graph, ZoneList<Statement*>* stmts); void AddToSubgraph(HSubgraph* graph, ZoneList<Statement*>* stmts);
void AddToSubgraph(HSubgraph* graph, Statement* stmt); void AddToSubgraph(HSubgraph* graph, Statement* stmt);
void AddToSubgraph(HSubgraph* graph, Expression* expr); void AddToSubgraph(HSubgraph* graph, Expression* expr);
@ -737,9 +735,8 @@ class HGraphBuilder: public AstVisitor {
HBasicBlock* CreateBasicBlock(HEnvironment* env); HBasicBlock* CreateBasicBlock(HEnvironment* env);
HSubgraph* CreateEmptySubgraph(); HSubgraph* CreateEmptySubgraph();
HSubgraph* CreateGotoSubgraph(HEnvironment* env);
HSubgraph* CreateBranchSubgraph(HEnvironment* env); HSubgraph* CreateBranchSubgraph(HEnvironment* env);
HBasicBlock* CreateLoopHeader(); HBasicBlock* CreateLoopHeaderBlock();
HSubgraph* CreateInlinedSubgraph(HEnvironment* outer, HSubgraph* CreateInlinedSubgraph(HEnvironment* outer,
Handle<JSFunction> target, Handle<JSFunction> target,
FunctionLiteral* function); FunctionLiteral* function);
@ -851,7 +848,6 @@ class HGraphBuilder: public AstVisitor {
TypeFeedbackOracle* oracle_; TypeFeedbackOracle* oracle_;
HGraph* graph_; HGraph* graph_;
HSubgraph* current_subgraph_; HSubgraph* current_subgraph_;
IterationStatement* peeled_statement_;
// Expression context of the currently visited subexpression. NULL when // Expression context of the currently visited subexpression. NULL when
// visiting statements. // visiting statements.
AstContext* ast_context_; AstContext* ast_context_;