| 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);
|
| }
|
|
|
|
|
|
|