Chromium Code Reviews| Index: src/hydrogen.cc |
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
| index 147563e90104c7d094c93b937bb91c0f34534fc6..450e95d9c5bc350b34c9e7f5e8effbf1ddbf3702 100644 |
| --- a/src/hydrogen.cc |
| +++ b/src/hydrogen.cc |
| @@ -745,19 +745,20 @@ bool HGraph::IsStandardConstant(HConstant* constant) { |
| HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder) |
| : builder_(builder), |
| finished_(false), |
| - deopt_then_(false), |
| - deopt_else_(false), |
| did_then_(false), |
| did_else_(false), |
| + did_else_if_(false), |
| did_and_(false), |
| did_or_(false), |
| captured_(false), |
| needs_compare_(true), |
| + pending_merge_block_(false), |
| split_edge_merge_block_(NULL), |
| - merge_block_(NULL) { |
| + merge_at_join_blocks_(NULL), |
| + normal_merge_at_join_block_count_(0), |
| + deopt_merge_at_join_block_count_(0) { |
| HEnvironment* env = builder->environment(); |
| first_true_block_ = builder->CreateBasicBlock(env->Copy()); |
| - last_true_block_ = NULL; |
| first_false_block_ = builder->CreateBasicBlock(env->Copy()); |
| } |
| @@ -767,19 +768,20 @@ HGraphBuilder::IfBuilder::IfBuilder( |
| HIfContinuation* continuation) |
| : builder_(builder), |
| finished_(false), |
| - deopt_then_(false), |
| - deopt_else_(false), |
| did_then_(false), |
| did_else_(false), |
| + did_else_if_(false), |
| did_and_(false), |
| did_or_(false), |
| captured_(false), |
| needs_compare_(false), |
| + pending_merge_block_(false), |
| first_true_block_(NULL), |
| - last_true_block_(NULL), |
| first_false_block_(NULL), |
| split_edge_merge_block_(NULL), |
| - merge_block_(NULL) { |
| + merge_at_join_blocks_(NULL), |
| + normal_merge_at_join_block_count_(0), |
| + deopt_merge_at_join_block_count_(0) { |
| continuation->Continue(&first_true_block_, |
| &first_false_block_); |
| } |
| @@ -787,6 +789,20 @@ HGraphBuilder::IfBuilder::IfBuilder( |
| HControlInstruction* HGraphBuilder::IfBuilder::AddCompare( |
| HControlInstruction* compare) { |
| + ASSERT(did_then_ == did_else_); |
| + if (did_else_) { |
| + // Handle if-then-elseif |
| + did_else_if_ = true; |
| + did_else_ = false; |
| + did_then_ = false; |
| + did_and_ = false; |
| + did_or_ = false; |
| + pending_merge_block_ = false; |
| + split_edge_merge_block_ = NULL; |
| + HEnvironment* env = builder_->environment(); |
| + first_true_block_ = builder_->CreateBasicBlock(env->Copy()); |
| + first_false_block_ = builder_->CreateBasicBlock(env->Copy()); |
| + } |
| if (split_edge_merge_block_ != NULL) { |
| HEnvironment* env = first_false_block_->last_environment(); |
| HBasicBlock* split_edge = |
| @@ -842,14 +858,15 @@ void HGraphBuilder::IfBuilder::And() { |
| void HGraphBuilder::IfBuilder::CaptureContinuation( |
| HIfContinuation* continuation) { |
| + ASSERT(!did_else_if_); |
| ASSERT(!finished_); |
| ASSERT(!captured_); |
| - HBasicBlock* true_block = last_true_block_ == NULL |
| - ? first_true_block_ |
| - : last_true_block_; |
| - HBasicBlock* false_block = did_else_ && (first_false_block_ != NULL) |
| - ? builder_->current_block() |
| - : first_false_block_; |
| + |
| + HBasicBlock* true_block = NULL; |
| + HBasicBlock* false_block = NULL; |
| + Finish(&true_block, &false_block); |
| + ASSERT(true_block != NULL); |
| + ASSERT(false_block != NULL); |
| continuation->Capture(true_block, false_block); |
| captured_ = true; |
| End(); |
| @@ -857,14 +874,13 @@ void HGraphBuilder::IfBuilder::CaptureContinuation( |
| void HGraphBuilder::IfBuilder::JoinContinuation(HIfContinuation* continuation) { |
| + ASSERT(!did_else_if_); |
| ASSERT(!finished_); |
| ASSERT(!captured_); |
| - ASSERT(did_then_); |
| - if (!did_else_) Else(); |
| - HBasicBlock* true_block = last_true_block_ == NULL |
| - ? first_true_block_ |
| - : last_true_block_; |
| - HBasicBlock* false_block = builder_->current_block(); |
| + HBasicBlock* true_block = NULL; |
| + HBasicBlock* false_block = NULL; |
| + Finish(&true_block, &false_block); |
| + merge_at_join_blocks_ = NULL; |
| if (true_block != NULL && !true_block->IsFinished()) { |
| ASSERT(continuation->IsTrueReachable()); |
| builder_->GotoNoSimulate(true_block, continuation->true_branch()); |
| @@ -895,6 +911,7 @@ void HGraphBuilder::IfBuilder::Then() { |
| builder_->FinishCurrentBlock(branch); |
| } |
| builder_->set_current_block(first_true_block_); |
| + pending_merge_block_ = true; |
| } |
| @@ -902,20 +919,17 @@ void HGraphBuilder::IfBuilder::Else() { |
| ASSERT(did_then_); |
| ASSERT(!captured_); |
| ASSERT(!finished_); |
| - last_true_block_ = builder_->current_block(); |
| + AddMergeAtJoinBlock(false); |
| builder_->set_current_block(first_false_block_); |
| + pending_merge_block_ = true; |
| did_else_ = true; |
| } |
| void HGraphBuilder::IfBuilder::Deopt(const char* reason) { |
| ASSERT(did_then_); |
| - if (did_else_) { |
| - deopt_else_ = true; |
| - } else { |
| - deopt_then_ = true; |
| - } |
| builder_->Add<HDeoptimize>(reason, Deoptimizer::EAGER); |
| + AddMergeAtJoinBlock(true); |
| } |
| @@ -923,51 +937,78 @@ void HGraphBuilder::IfBuilder::Return(HValue* value) { |
| HValue* parameter_count = builder_->graph()->GetConstantMinus1(); |
| builder_->FinishExitCurrentBlock( |
| builder_->New<HReturn>(value, parameter_count)); |
| - if (did_else_) { |
| - first_false_block_ = NULL; |
| - } else { |
| - first_true_block_ = NULL; |
| + AddMergeAtJoinBlock(false); |
| +} |
| + |
| + |
| +void HGraphBuilder::IfBuilder::Finish() { |
| + ASSERT(!finished_); |
| + if (!did_then_) { |
| + Then(); |
| + } |
| + AddMergeAtJoinBlock(false); |
| + if (!did_else_) { |
| + Else(); |
| + AddMergeAtJoinBlock(false); |
| + } |
| + finished_ = true; |
| +} |
| + |
| + |
| +void HGraphBuilder::IfBuilder::Finish(HBasicBlock** then_continuation, |
| + HBasicBlock** else_continuation) { |
| + Finish(); |
| + |
| + MergeAtJoinBlock* else_record = merge_at_join_blocks_; |
| + if (else_continuation != NULL) { |
| + *else_continuation = else_record->block_; |
| } |
| + MergeAtJoinBlock* then_record = else_record->next_; |
| + if (then_continuation != NULL) { |
| + *then_continuation = then_record->block_; |
| + } |
| + ASSERT(then_record->next_ == NULL); |
| } |
| void HGraphBuilder::IfBuilder::End() { |
| - if (!captured_) { |
| - ASSERT(did_then_); |
| - if (!did_else_) { |
| - last_true_block_ = builder_->current_block(); |
| - } |
| - if (last_true_block_ == NULL || last_true_block_->IsFinished()) { |
| - ASSERT(did_else_); |
| - // Return on true. Nothing to do, just continue the false block. |
| - } else if (first_false_block_ == NULL || |
| - (did_else_ && builder_->current_block()->IsFinished())) { |
| - // Deopt on false. Nothing to do except switching to the true block. |
| - builder_->set_current_block(last_true_block_); |
| - } else { |
| - merge_block_ = builder_->graph()->CreateBasicBlock(); |
| - ASSERT(!finished_); |
| - if (!did_else_) Else(); |
| - ASSERT(!last_true_block_->IsFinished()); |
| - HBasicBlock* last_false_block = builder_->current_block(); |
| - ASSERT(!last_false_block->IsFinished()); |
| - if (deopt_then_) { |
| - builder_->GotoNoSimulate(last_false_block, merge_block_); |
| - builder_->PadEnvironmentForContinuation(last_true_block_, |
| - merge_block_); |
| - builder_->GotoNoSimulate(last_true_block_, merge_block_); |
| - } else { |
| - builder_->GotoNoSimulate(last_true_block_, merge_block_); |
| - if (deopt_else_) { |
| - builder_->PadEnvironmentForContinuation(last_false_block, |
| - merge_block_); |
| - } |
| - builder_->GotoNoSimulate(last_false_block, merge_block_); |
| + if (captured_) return; |
| + Finish(); |
| + |
| + int total_merged_blocks = normal_merge_at_join_block_count_ + |
| + deopt_merge_at_join_block_count_; |
| + ASSERT(total_merged_blocks >= 1); |
| + HBasicBlock* merge_block = total_merged_blocks == 1 |
| + ? NULL : builder_->graph()->CreateBasicBlock(); |
| + |
| + // Merge non-deopt blocks first to ensure environment has right size for |
| + // padding. |
| + MergeAtJoinBlock* current = merge_at_join_blocks_; |
| + while (current != NULL) { |
| + if (!current->deopt_ && current->block_ != NULL) { |
| + // If there is only one block that makes it through to the end of the |
| + // if, then just set it as the current block and continue rather then |
| + // creating an unnecessary merge block. |
| + if (total_merged_blocks == 1) { |
| + builder_->set_current_block(current->block_); |
| + return; |
| } |
| - builder_->set_current_block(merge_block_); |
| + builder_->GotoNoSimulate(current->block_, merge_block); |
| } |
| + current = current->next_; |
| } |
| - finished_ = true; |
| + |
| + // Merge deopt blocks, padding when necessary. |
| + current = merge_at_join_blocks_; |
| + while (current != NULL) { |
| + if (current->deopt_ && current->block_ != NULL) { |
| + builder_->PadEnvironmentForContinuation(current->block_, |
| + merge_block); |
| + builder_->GotoNoSimulate(current->block_, merge_block); |
| + } |
| + current = current->next_; |
| + } |
| + builder_->set_current_block(merge_block); |
| } |
| @@ -1051,6 +1092,7 @@ void HGraphBuilder::LoopBuilder::Break() { |
| } |
| builder_->GotoNoSimulate(exit_trampoline_block_); |
| + builder_->set_current_block(NULL); |
| } |
| @@ -1119,9 +1161,7 @@ void HGraphBuilder::FinishExitCurrentBlock(HControlInstruction* instruction) { |
| ASSERT(!FLAG_emit_opt_code_positions || !info_->IsOptimizing() || |
| position_ != RelocInfo::kNoPosition); |
| current_block()->FinishExit(instruction, position_); |
| - if (instruction->IsReturn() || instruction->IsAbnormalExit()) { |
| - set_current_block(NULL); |
| - } |
| + set_current_block(NULL); |
|
Michael Starzinger
2013/11/12 09:50:00
This change confuses me. HGraphBuilder::FinishExit
danno
2013/11/14 14:46:40
Done.
|
| } |