| OLD | NEW | 
|      1 // Copyright 2013 the V8 project authors. All rights reserved. |      1 // Copyright 2013 the V8 project authors. All rights reserved. | 
|      2 // Redistribution and use in source and binary forms, with or without |      2 // Redistribution and use in source and binary forms, with or without | 
|      3 // modification, are permitted provided that the following conditions are |      3 // modification, are permitted provided that the following conditions are | 
|      4 // met: |      4 // met: | 
|      5 // |      5 // | 
|      6 //     * Redistributions of source code must retain the above copyright |      6 //     * Redistributions of source code must retain the above copyright | 
|      7 //       notice, this list of conditions and the following disclaimer. |      7 //       notice, this list of conditions and the following disclaimer. | 
|      8 //     * Redistributions in binary form must reproduce the above |      8 //     * Redistributions in binary form must reproduce the above | 
|      9 //       copyright notice, this list of conditions and the following |      9 //       copyright notice, this list of conditions and the following | 
|     10 //       disclaimer in the documentation and/or other materials provided |     10 //       disclaimer in the documentation and/or other materials provided | 
| (...skipping 4123 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   4134 void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { |   4134 void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { | 
|   4135   ASSERT(!HasStackOverflow()); |   4135   ASSERT(!HasStackOverflow()); | 
|   4136   ASSERT(current_block() != NULL); |   4136   ASSERT(current_block() != NULL); | 
|   4137   ASSERT(current_block()->HasPredecessor()); |   4137   ASSERT(current_block()->HasPredecessor()); | 
|   4138  |   4138  | 
|   4139   // We only optimize switch statements with smi-literal smi comparisons, |   4139   // We only optimize switch statements with smi-literal smi comparisons, | 
|   4140   // with a bounded number of clauses. |   4140   // with a bounded number of clauses. | 
|   4141   const int kCaseClauseLimit = 128; |   4141   const int kCaseClauseLimit = 128; | 
|   4142   ZoneList<CaseClause*>* clauses = stmt->cases(); |   4142   ZoneList<CaseClause*>* clauses = stmt->cases(); | 
|   4143   int clause_count = clauses->length(); |   4143   int clause_count = clauses->length(); | 
 |   4144   ZoneList<HBasicBlock*> body_blocks(clause_count, zone()); | 
|   4144   if (clause_count > kCaseClauseLimit) { |   4145   if (clause_count > kCaseClauseLimit) { | 
|   4145     return Bailout(kSwitchStatementTooManyClauses); |   4146     return Bailout(kSwitchStatementTooManyClauses); | 
|   4146   } |   4147   } | 
|   4147  |   4148  | 
|   4148   ASSERT(stmt->switch_type() != SwitchStatement::UNKNOWN_SWITCH); |   4149   ASSERT(stmt->switch_type() != SwitchStatement::UNKNOWN_SWITCH); | 
|   4149   if (stmt->switch_type() == SwitchStatement::GENERIC_SWITCH) { |  | 
|   4150     return Bailout(kSwitchStatementMixedOrNonLiteralSwitchLabels); |  | 
|   4151   } |  | 
|   4152  |   4150  | 
|   4153   CHECK_ALIVE(VisitForValue(stmt->tag())); |   4151   CHECK_ALIVE(VisitForValue(stmt->tag())); | 
|   4154   Add<HSimulate>(stmt->EntryId()); |   4152   Add<HSimulate>(stmt->EntryId()); | 
|   4155   HValue* tag_value = Pop(); |   4153   HValue* tag_value = Top(); | 
|   4156   HBasicBlock* first_test_block = current_block(); |  | 
|   4157  |   4154  | 
|   4158   HUnaryControlInstruction* string_check = NULL; |   4155   HUnaryControlInstruction* string_check = NULL; | 
|   4159   HBasicBlock* not_string_block = NULL; |   4156   HBasicBlock* not_string_block = NULL; | 
|   4160  |   4157  | 
|   4161   // Test switch's tag value if all clauses are string literals |   4158   // Test switch's tag value if all clauses are string literals | 
|   4162   if (stmt->switch_type() == SwitchStatement::STRING_SWITCH) { |   4159   if (stmt->switch_type() == SwitchStatement::STRING_SWITCH) { | 
|   4163     first_test_block = graph()->CreateBasicBlock(); |   4160     HBasicBlock* first_test_block = graph()->CreateBasicBlock(); | 
|   4164     not_string_block = graph()->CreateBasicBlock(); |   4161     not_string_block = graph()->CreateBasicBlock(); | 
|   4165     string_check = New<HIsStringAndBranch>( |   4162     string_check = New<HIsStringAndBranch>( | 
|   4166         tag_value, first_test_block, not_string_block); |   4163         tag_value, first_test_block, not_string_block); | 
|   4167     FinishCurrentBlock(string_check); |   4164     FinishCurrentBlock(string_check); | 
|   4168  |   4165  | 
 |   4166     set_current_block(not_string_block); | 
 |   4167     Drop(1);  // tag_value | 
 |   4168  | 
|   4169     set_current_block(first_test_block); |   4169     set_current_block(first_test_block); | 
|   4170   } |   4170   } | 
|   4171  |   4171  | 
|   4172   // 1. Build all the tests, with dangling true branches |   4172   // 1. Build all the tests, with dangling true branches | 
|   4173   BailoutId default_id = BailoutId::None(); |   4173   BailoutId default_id = BailoutId::None(); | 
|   4174   for (int i = 0; i < clause_count; ++i) { |   4174   for (int i = 0; i < clause_count; ++i) { | 
|   4175     CaseClause* clause = clauses->at(i); |   4175     CaseClause* clause = clauses->at(i); | 
|   4176     if (clause->is_default()) { |   4176     if (clause->is_default()) { | 
|   4177       default_id = clause->EntryId(); |   4177       body_blocks.Add(NULL, zone()); | 
 |   4178       if (default_id.IsNone()) default_id = clause->EntryId(); | 
|   4178       continue; |   4179       continue; | 
|   4179     } |   4180     } | 
|   4180  |   4181  | 
|   4181     // Generate a compare and branch. |   4182     // Generate a compare and branch. | 
|   4182     CHECK_ALIVE(VisitForValue(clause->label())); |   4183     CHECK_ALIVE(VisitForValue(clause->label())); | 
|   4183     HValue* label_value = Pop(); |   4184     HValue* label_value = Pop(); | 
|   4184  |   4185  | 
|   4185     HBasicBlock* next_test_block = graph()->CreateBasicBlock(); |  | 
|   4186     HBasicBlock* body_block = graph()->CreateBasicBlock(); |  | 
|   4187  |  | 
|   4188     HControlInstruction* compare; |   4186     HControlInstruction* compare; | 
|   4189  |   4187  | 
|   4190     if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) { |   4188     if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) { | 
|   4191       if (!clause->compare_type()->Is(Type::Smi())) { |   4189       if (!clause->compare_type()->Is(Type::Smi())) { | 
|   4192         Add<HDeoptimize>("Non-smi switch type", Deoptimizer::SOFT); |   4190         Add<HDeoptimize>("Non-smi switch type", Deoptimizer::SOFT); | 
|   4193       } |   4191       } | 
|   4194  |   4192  | 
|   4195       HCompareNumericAndBranch* compare_ = |   4193       HCompareNumericAndBranch* compare_ = | 
|   4196           New<HCompareNumericAndBranch>(tag_value, |   4194           New<HCompareNumericAndBranch>(tag_value, | 
|   4197                                         label_value, |   4195                                         label_value, | 
|   4198                                         Token::EQ_STRICT); |   4196                                         Token::EQ_STRICT); | 
|   4199       compare_->set_observed_input_representation( |   4197       compare_->set_observed_input_representation( | 
|   4200           Representation::Smi(), Representation::Smi()); |   4198           Representation::Smi(), Representation::Smi()); | 
|   4201       compare = compare_; |   4199       compare = compare_; | 
|   4202     } else { |   4200     } else if (stmt->switch_type() == SwitchStatement::STRING_SWITCH) { | 
|   4203       compare = New<HStringCompareAndBranch>(tag_value, |   4201       compare = New<HStringCompareAndBranch>(tag_value, | 
|   4204                                              label_value, |   4202                                              label_value, | 
|   4205                                              Token::EQ_STRICT); |   4203                                              Token::EQ_STRICT); | 
 |   4204     } else { | 
 |   4205       HValue* test = Add<HCompareGeneric>(tag_value, | 
 |   4206                                           label_value, | 
 |   4207                                           Token::EQ_STRICT); | 
 |   4208       if (test->HasObservableSideEffects()) { | 
 |   4209         Push(test); | 
 |   4210         Add<HSimulate>(clause->id(), REMOVABLE_SIMULATE); | 
 |   4211         Drop(1); | 
 |   4212       } | 
 |   4213       compare = New<HBranch>(test); | 
|   4206     } |   4214     } | 
|   4207  |   4215  | 
 |   4216     HBasicBlock* next_test_block = graph()->CreateBasicBlock(); | 
 |   4217     HBasicBlock* body_block = graph()->CreateBasicBlock(); | 
 |   4218     body_blocks.Add(body_block, zone()); | 
|   4208     compare->SetSuccessorAt(0, body_block); |   4219     compare->SetSuccessorAt(0, body_block); | 
|   4209     compare->SetSuccessorAt(1, next_test_block); |   4220     compare->SetSuccessorAt(1, next_test_block); | 
|   4210     FinishCurrentBlock(compare); |   4221     FinishCurrentBlock(compare); | 
|   4211  |   4222  | 
 |   4223     set_current_block(body_block); | 
 |   4224     Drop(1);  // tag_value | 
 |   4225  | 
|   4212     set_current_block(next_test_block); |   4226     set_current_block(next_test_block); | 
|   4213   } |   4227   } | 
|   4214  |   4228  | 
|   4215   // Save the current block to use for the default or to join with the |   4229   // Save the current block to use for the default or to join with the | 
|   4216   // exit. |   4230   // exit. | 
|   4217   HBasicBlock* last_block = current_block(); |   4231   HBasicBlock* last_block = current_block(); | 
 |   4232   Drop(1);  // tag_value | 
|   4218  |   4233  | 
|   4219   if (not_string_block != NULL) { |   4234   if (not_string_block != NULL) { | 
|   4220     BailoutId join_id = !default_id.IsNone() ? default_id : stmt->ExitId(); |   4235     BailoutId join_id = !default_id.IsNone() ? default_id : stmt->ExitId(); | 
|   4221     last_block = CreateJoin(last_block, not_string_block, join_id); |   4236     last_block = CreateJoin(last_block, not_string_block, join_id); | 
|   4222   } |   4237   } | 
|   4223  |   4238  | 
|   4224   // 2. Loop over the clauses and the linked list of tests in lockstep, |   4239   // 2. Loop over the clauses and the linked list of tests in lockstep, | 
|   4225   // translating the clause bodies. |   4240   // translating the clause bodies. | 
|   4226   HBasicBlock* curr_test_block = first_test_block; |  | 
|   4227   HBasicBlock* fall_through_block = NULL; |   4241   HBasicBlock* fall_through_block = NULL; | 
|   4228  |   4242  | 
|   4229   BreakAndContinueInfo break_info(stmt); |   4243   BreakAndContinueInfo break_info(stmt); | 
|   4230   { BreakAndContinueScope push(&break_info, this); |   4244   { BreakAndContinueScope push(&break_info, this); | 
|   4231     for (int i = 0; i < clause_count; ++i) { |   4245     for (int i = 0; i < clause_count; ++i) { | 
|   4232       CaseClause* clause = clauses->at(i); |   4246       CaseClause* clause = clauses->at(i); | 
|   4233  |   4247  | 
|   4234       // Identify the block where normal (non-fall-through) control flow |   4248       // Identify the block where normal (non-fall-through) control flow | 
|   4235       // goes to. |   4249       // goes to. | 
|   4236       HBasicBlock* normal_block = NULL; |   4250       HBasicBlock* normal_block = NULL; | 
|   4237       if (clause->is_default()) { |   4251       if (clause->is_default()) { | 
|   4238         if (last_block != NULL) { |   4252         if (last_block == NULL) continue; | 
|   4239           normal_block = last_block; |   4253         normal_block = last_block; | 
|   4240           last_block = NULL;  // Cleared to indicate we've handled it. |   4254         last_block = NULL;  // Cleared to indicate we've handled it. | 
|   4241         } |  | 
|   4242       } else { |   4255       } else { | 
|   4243         // If the current test block is deoptimizing due to an unhandled clause |   4256         normal_block = body_blocks[i]; | 
|   4244         // of the switch, the test instruction is in the next block since the |  | 
|   4245         // deopt must end the current block. |  | 
|   4246         if (curr_test_block->IsDeoptimizing()) { |  | 
|   4247           ASSERT(curr_test_block->end()->SecondSuccessor() == NULL); |  | 
|   4248           curr_test_block = curr_test_block->end()->FirstSuccessor(); |  | 
|   4249         } |  | 
|   4250         normal_block = curr_test_block->end()->FirstSuccessor(); |  | 
|   4251         curr_test_block = curr_test_block->end()->SecondSuccessor(); |  | 
|   4252       } |   4257       } | 
|   4253  |   4258  | 
|   4254       // Identify a block to emit the body into. |   4259       if (fall_through_block == NULL) { | 
|   4255       if (normal_block == NULL) { |  | 
|   4256         if (fall_through_block == NULL) { |  | 
|   4257           // (a) Unreachable. |  | 
|   4258           if (clause->is_default()) { |  | 
|   4259             continue;  // Might still be reachable clause bodies. |  | 
|   4260           } else { |  | 
|   4261             break; |  | 
|   4262           } |  | 
|   4263         } else { |  | 
|   4264           // (b) Reachable only as fall through. |  | 
|   4265           set_current_block(fall_through_block); |  | 
|   4266         } |  | 
|   4267       } else if (fall_through_block == NULL) { |  | 
|   4268         // (c) Reachable only normally. |  | 
|   4269         set_current_block(normal_block); |   4260         set_current_block(normal_block); | 
|   4270       } else { |   4261       } else { | 
|   4271         // (d) Reachable both ways. |  | 
|   4272         HBasicBlock* join = CreateJoin(fall_through_block, |   4262         HBasicBlock* join = CreateJoin(fall_through_block, | 
|   4273                                        normal_block, |   4263                                        normal_block, | 
|   4274                                        clause->EntryId()); |   4264                                        clause->EntryId()); | 
|   4275         set_current_block(join); |   4265         set_current_block(join); | 
|   4276       } |   4266       } | 
|   4277  |   4267  | 
|   4278       CHECK_BAILOUT(VisitStatements(clause->statements())); |   4268       CHECK_BAILOUT(VisitStatements(clause->statements())); | 
|   4279       fall_through_block = current_block(); |   4269       fall_through_block = current_block(); | 
|   4280     } |   4270     } | 
|   4281   } |   4271   } | 
| (...skipping 6529 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  10811   if (ShouldProduceTraceOutput()) { |  10801   if (ShouldProduceTraceOutput()) { | 
|  10812     isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |  10802     isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 
|  10813   } |  10803   } | 
|  10814  |  10804  | 
|  10815 #ifdef DEBUG |  10805 #ifdef DEBUG | 
|  10816   graph_->Verify(false);  // No full verify. |  10806   graph_->Verify(false);  // No full verify. | 
|  10817 #endif |  10807 #endif | 
|  10818 } |  10808 } | 
|  10819  |  10809  | 
|  10820 } }  // namespace v8::internal |  10810 } }  // namespace v8::internal | 
| OLD | NEW |