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

Unified Diff: src/hydrogen.cc

Issue 15993014: hydrogen: split switch optimization code into multiple functions (Closed) Base URL: gh:v8/v8.git@master
Patch Set: Created 7 years, 6 months 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 1cf6d836fb11ae9f8dc78d93e92f4e61ce4e01d3..3151fdcfbe9c9d544bacc6aa2460b7e39d8f8182 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -4910,6 +4910,80 @@ void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) {
}
+void HOptimizedGraphBuilder::GlueSwitchClauses(SwitchStatement* stmt,
+ ZoneList<HBasicBlock*>* bodies) {
+ // Save the current block to use for the default or to join with the
+ // exit. This block is NULL if we deoptimized.
+ HBasicBlock* last_block = current_block();
+
+ // Loop over the clauses and the linked list of tests in lockstep,
+ // translating the clause bodies.
+ HBasicBlock* fall_through_block = NULL;
+
+ ZoneList<CaseClause*>* clauses = stmt->cases();
+ int clause_count = clauses->length();
+
+ BreakAndContinueInfo break_info(stmt);
+ { BreakAndContinueScope push(&break_info, this);
+ for (int i = 0; i < clause_count; ++i) {
+ CaseClause* clause = clauses->at(i);
+
+ // Identify the block where normal (non-fall-through) control flow
+ // goes to.
+ HBasicBlock* normal_block = bodies->at(i);
+ if (clause->is_default()) {
+ ASSERT(normal_block == NULL);
+ if (last_block != NULL) {
+ normal_block = last_block;
+ last_block = NULL; // Cleared to indicate we've handled it.
+ }
+ }
+
+ // Identify a block to emit the body into.
+ if (normal_block == NULL) {
+ if (fall_through_block == NULL) {
+ // (a) Unreachable.
+ if (clause->is_default()) {
+ continue; // Might still be reachable clause bodies.
+ } else {
+ break;
+ }
+ } else {
+ // (b) Reachable only as fall through.
+ set_current_block(fall_through_block);
+ }
+ } else if (fall_through_block == NULL) {
+ // (c) Reachable only normally.
+ set_current_block(normal_block);
+ } else {
+ // (d) Reachable both ways.
+ HBasicBlock* join = CreateJoin(fall_through_block,
+ normal_block,
+ clause->EntryId());
+ set_current_block(join);
+ }
+
+ CHECK_BAILOUT(VisitStatements(clause->statements()));
+ fall_through_block = current_block();
+ }
+ }
+
+ // Create an up-to-3-way join. Use the break block if it exists since
+ // it's already a join block.
+ HBasicBlock* break_block = break_info.break_block();
+ if (break_block == NULL) {
+ set_current_block(CreateJoin(fall_through_block,
+ last_block,
+ stmt->ExitId()));
+ } else {
+ if (fall_through_block != NULL) fall_through_block->Goto(break_block);
+ if (last_block != NULL) last_block->Goto(break_block);
+ break_block->SetJoinId(stmt->ExitId());
+ set_current_block(break_block);
+ }
+}
+
+
void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
@@ -4952,12 +5026,14 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
set_current_block(first_test_block);
}
- // 1. Build all the tests, with dangling true branches
+ // Build all the tests, with dangling true branches
BailoutId default_id = BailoutId::None();
+ ZoneList<HBasicBlock*> bodies(clause_count, zone());
for (int i = 0; i < clause_count; ++i) {
CaseClause* clause = clauses->at(i);
if (clause->is_default()) {
default_id = clause->EntryId();
+ bodies.Add(NULL, zone());
continue;
}
@@ -4967,6 +5043,7 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
HBasicBlock* next_test_block = graph()->CreateBasicBlock();
HBasicBlock* body_block = graph()->CreateBasicBlock();
+ bodies.Add(body_block, zone());
HControlInstruction* compare;
@@ -4999,80 +5076,16 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
set_current_block(next_test_block);
}
- // Save the current block to use for the default or to join with the
- // exit. This block is NULL if we deoptimized.
+ // Join non-string case with the exit block of switch statement
HBasicBlock* last_block = current_block();
-
if (not_string_block != NULL) {
BailoutId join_id = !default_id.IsNone() ? default_id : stmt->ExitId();
last_block = CreateJoin(last_block, not_string_block, join_id);
+ set_current_block(last_block);
}
- // 2. Loop over the clauses and the linked list of tests in lockstep,
- // translating the clause bodies.
- HBasicBlock* curr_test_block = first_test_block;
- HBasicBlock* fall_through_block = NULL;
-
- BreakAndContinueInfo break_info(stmt);
- { BreakAndContinueScope push(&break_info, this);
- for (int i = 0; i < clause_count; ++i) {
- CaseClause* clause = clauses->at(i);
-
- // Identify the block where normal (non-fall-through) control flow
- // goes to.
- HBasicBlock* normal_block = NULL;
- if (clause->is_default()) {
- if (last_block != NULL) {
- normal_block = last_block;
- last_block = NULL; // Cleared to indicate we've handled it.
- }
- } else if (!curr_test_block->end()->IsDeoptimize()) {
- normal_block = curr_test_block->end()->FirstSuccessor();
- curr_test_block = curr_test_block->end()->SecondSuccessor();
- }
-
- // Identify a block to emit the body into.
- if (normal_block == NULL) {
- if (fall_through_block == NULL) {
- // (a) Unreachable.
- if (clause->is_default()) {
- continue; // Might still be reachable clause bodies.
- } else {
- break;
- }
- } else {
- // (b) Reachable only as fall through.
- set_current_block(fall_through_block);
- }
- } else if (fall_through_block == NULL) {
- // (c) Reachable only normally.
- set_current_block(normal_block);
- } else {
- // (d) Reachable both ways.
- HBasicBlock* join = CreateJoin(fall_through_block,
- normal_block,
- clause->EntryId());
- set_current_block(join);
- }
-
- CHECK_BAILOUT(VisitStatements(clause->statements()));
- fall_through_block = current_block();
- }
- }
-
- // Create an up-to-3-way join. Use the break block if it exists since
- // it's already a join block.
- HBasicBlock* break_block = break_info.break_block();
- if (break_block == NULL) {
- set_current_block(CreateJoin(fall_through_block,
- last_block,
- stmt->ExitId()));
- } else {
- if (fall_through_block != NULL) fall_through_block->Goto(break_block);
- if (last_block != NULL) last_block->Goto(break_block);
- break_block->SetJoinId(stmt->ExitId());
- set_current_block(break_block);
- }
+ // Emit and glue bodies together
+ GlueSwitchClauses(stmt, &bodies);
}
« 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