Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(418)

Unified Diff: src/hydrogen.cc

Issue 66983002: Add ability to do "else-if" clauses in IfBuilder (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Review feedback Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/hydrogen.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/hydrogen.cc
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index b47ec8010d25d10a76a1b203fa4bde3e5f39ba01..c73d8d6d80b394d64085b550ebbfd809b47403d9 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -605,7 +605,8 @@ void HGraph::Verify(bool do_full_verify) const {
block->predecessors()->first()->last_environment()->ast_id();
for (int k = 0; k < block->predecessors()->length(); k++) {
HBasicBlock* predecessor = block->predecessors()->at(k);
- ASSERT(predecessor->end()->IsGoto());
+ ASSERT(predecessor->end()->IsGoto() ||
+ predecessor->end()->IsDeoptimize());
ASSERT(predecessor->last_environment()->ast_id() == id);
}
}
@@ -745,19 +746,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 +769,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 +790,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,29 +859,30 @@ 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;
+ builder_->set_current_block(NULL);
End();
}
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 +913,7 @@ void HGraphBuilder::IfBuilder::Then() {
builder_->FinishCurrentBlock(branch);
}
builder_->set_current_block(first_true_block_);
+ pending_merge_block_ = true;
}
@@ -902,20 +921,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 +939,99 @@ 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::AddMergeAtJoinBlock(bool deopt) {
+ if (!pending_merge_block_) return;
+ HBasicBlock* block = builder_->current_block();
+ ASSERT(block == NULL || !block->IsFinished());
+ MergeAtJoinBlock* record =
+ new(builder_->zone()) MergeAtJoinBlock(block, deopt,
+ merge_at_join_blocks_);
+ merge_at_join_blocks_ = record;
+ if (block != NULL) {
+ ASSERT(block->end() == NULL);
+ if (deopt) {
+ normal_merge_at_join_block_count_++;
+ } else {
+ deopt_merge_at_join_block_count_++;
+ }
}
+ builder_->set_current_block(NULL);
+ pending_merge_block_ = 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 +1115,7 @@ void HGraphBuilder::LoopBuilder::Break() {
}
builder_->GotoNoSimulate(exit_trampoline_block_);
+ builder_->set_current_block(NULL);
}
@@ -1859,6 +1924,7 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
HInstruction* result = AddElementAccess(
external_elements, key, val, bounds_check, elements_kind, is_store);
negative_checker.ElseDeopt("Negative key encountered");
+ negative_checker.End();
length_checker.End();
return result;
} else {
@@ -1940,9 +2006,10 @@ HValue* HGraphBuilder::BuildAllocateArrayFromLength(
IsFastPackedElementsKind(array_builder->kind())) {
// We'll come back later with better (holey) feedback.
if_builder.Deopt("Holey array despite packed elements_kind feedback");
+ } else {
+ Push(checked_length); // capacity
+ Push(checked_length); // length
}
- Push(checked_length); // capacity
- Push(checked_length); // length
if_builder.End();
// Figure out total size
« no previous file with comments | « src/hydrogen.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698