OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/hydrogen.h" | 5 #include "src/hydrogen.h" |
6 | 6 |
7 #include <sstream> | 7 #include <sstream> |
8 | 8 |
9 #include "src/v8.h" | 9 #include "src/v8.h" |
10 | 10 |
(...skipping 5032 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5043 | 5043 |
5044 void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) { | 5044 void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) { |
5045 DCHECK(!HasStackOverflow()); | 5045 DCHECK(!HasStackOverflow()); |
5046 DCHECK(current_block() != NULL); | 5046 DCHECK(current_block() != NULL); |
5047 DCHECK(current_block()->HasPredecessor()); | 5047 DCHECK(current_block()->HasPredecessor()); |
5048 | 5048 |
5049 if (!FLAG_optimize_for_in) { | 5049 if (!FLAG_optimize_for_in) { |
5050 return Bailout(kForInStatementOptimizationIsDisabled); | 5050 return Bailout(kForInStatementOptimizationIsDisabled); |
5051 } | 5051 } |
5052 | 5052 |
5053 if (stmt->for_in_type() != ForInStatement::FAST_FOR_IN) { | |
5054 return Bailout(kForInStatementIsNotFastCase); | |
5055 } | |
5056 | |
5057 if (!stmt->each()->IsVariableProxy() || | 5053 if (!stmt->each()->IsVariableProxy() || |
5058 !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) { | 5054 !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) { |
5059 return Bailout(kForInStatementWithNonLocalEachVariable); | 5055 return Bailout(kForInStatementWithNonLocalEachVariable); |
5060 } | 5056 } |
5061 | 5057 |
5062 Variable* each_var = stmt->each()->AsVariableProxy()->var(); | 5058 Variable* each_var = stmt->each()->AsVariableProxy()->var(); |
5063 | 5059 |
5064 CHECK_ALIVE(VisitForValue(stmt->enumerable())); | 5060 CHECK_ALIVE(VisitForValue(stmt->enumerable())); |
5065 HValue* enumerable = Top(); // Leave enumerable at the top. | 5061 HValue* enumerable = Top(); // Leave enumerable at the top. |
5066 | 5062 |
5067 HInstruction* map = Add<HForInPrepareMap>(enumerable); | 5063 HInstruction* map; |
5068 Add<HSimulate>(stmt->PrepareId()); | 5064 HInstruction* array; |
| 5065 HInstruction* enum_length; |
| 5066 bool fast = stmt->for_in_type() == ForInStatement::FAST_FOR_IN; |
| 5067 if (fast) { |
| 5068 map = Add<HForInPrepareMap>(enumerable); |
| 5069 Add<HSimulate>(stmt->PrepareId()); |
5069 | 5070 |
5070 HInstruction* array = Add<HForInCacheArray>( | 5071 array = Add<HForInCacheArray>(enumerable, map, |
5071 enumerable, map, DescriptorArray::kEnumCacheBridgeCacheIndex); | 5072 DescriptorArray::kEnumCacheBridgeCacheIndex); |
| 5073 enum_length = Add<HMapEnumLength>(map); |
5072 | 5074 |
5073 HInstruction* enum_length = Add<HMapEnumLength>(map); | 5075 HInstruction* index_cache = Add<HForInCacheArray>( |
| 5076 enumerable, map, DescriptorArray::kEnumCacheBridgeIndicesCacheIndex); |
| 5077 HForInCacheArray::cast(array) |
| 5078 ->set_index_cache(HForInCacheArray::cast(index_cache)); |
| 5079 } else { |
| 5080 Add<HSimulate>(stmt->PrepareId()); |
| 5081 { |
| 5082 NoObservableSideEffectsScope no_effects(this); |
| 5083 BuildJSObjectCheck(enumerable, 0); |
| 5084 } |
| 5085 Add<HSimulate>(stmt->ToObjectId()); |
| 5086 |
| 5087 map = graph()->GetConstant1(); |
| 5088 Runtime::FunctionId function_id = Runtime::kGetPropertyNamesFast; |
| 5089 Add<HPushArguments>(enumerable); |
| 5090 array = Add<HCallRuntime>(isolate()->factory()->empty_string(), |
| 5091 Runtime::FunctionForId(function_id), 1); |
| 5092 Push(array); |
| 5093 Add<HSimulate>(stmt->EnumId()); |
| 5094 Drop(1); |
| 5095 Handle<Map> array_map = isolate()->factory()->fixed_array_map(); |
| 5096 HValue* check = Add<HCheckMaps>(array, array_map); |
| 5097 enum_length = AddLoadFixedArrayLength(array, check); |
| 5098 } |
5074 | 5099 |
5075 HInstruction* start_index = Add<HConstant>(0); | 5100 HInstruction* start_index = Add<HConstant>(0); |
5076 | 5101 |
5077 Push(map); | 5102 Push(map); |
5078 Push(array); | 5103 Push(array); |
5079 Push(enum_length); | 5104 Push(enum_length); |
5080 Push(start_index); | 5105 Push(start_index); |
5081 | 5106 |
5082 HInstruction* index_cache = Add<HForInCacheArray>( | |
5083 enumerable, map, DescriptorArray::kEnumCacheBridgeIndicesCacheIndex); | |
5084 HForInCacheArray::cast(array)->set_index_cache( | |
5085 HForInCacheArray::cast(index_cache)); | |
5086 | |
5087 HBasicBlock* loop_entry = BuildLoopEntry(stmt); | 5107 HBasicBlock* loop_entry = BuildLoopEntry(stmt); |
5088 | 5108 |
| 5109 // Reload the values to ensure we have up-to-date values inside of the loop. |
| 5110 // This is relevant especially for OSR where the values don't come from the |
| 5111 // computation above, but from the OSR entry block. |
| 5112 enumerable = environment()->ExpressionStackAt(4); |
5089 HValue* index = environment()->ExpressionStackAt(0); | 5113 HValue* index = environment()->ExpressionStackAt(0); |
5090 HValue* limit = environment()->ExpressionStackAt(1); | 5114 HValue* limit = environment()->ExpressionStackAt(1); |
5091 | 5115 |
5092 // Check that we still have more keys. | 5116 // Check that we still have more keys. |
5093 HCompareNumericAndBranch* compare_index = | 5117 HCompareNumericAndBranch* compare_index = |
5094 New<HCompareNumericAndBranch>(index, limit, Token::LT); | 5118 New<HCompareNumericAndBranch>(index, limit, Token::LT); |
5095 compare_index->set_observed_input_representation( | 5119 compare_index->set_observed_input_representation( |
5096 Representation::Smi(), Representation::Smi()); | 5120 Representation::Smi(), Representation::Smi()); |
5097 | 5121 |
5098 HBasicBlock* loop_body = graph()->CreateBasicBlock(); | 5122 HBasicBlock* loop_body = graph()->CreateBasicBlock(); |
5099 HBasicBlock* loop_successor = graph()->CreateBasicBlock(); | 5123 HBasicBlock* loop_successor = graph()->CreateBasicBlock(); |
5100 | 5124 |
5101 compare_index->SetSuccessorAt(0, loop_body); | 5125 compare_index->SetSuccessorAt(0, loop_body); |
5102 compare_index->SetSuccessorAt(1, loop_successor); | 5126 compare_index->SetSuccessorAt(1, loop_successor); |
5103 FinishCurrentBlock(compare_index); | 5127 FinishCurrentBlock(compare_index); |
5104 | 5128 |
5105 set_current_block(loop_successor); | 5129 set_current_block(loop_successor); |
5106 Drop(5); | 5130 Drop(5); |
5107 | 5131 |
5108 set_current_block(loop_body); | 5132 set_current_block(loop_body); |
5109 | 5133 |
5110 HValue* key = Add<HLoadKeyed>( | 5134 HValue* key = |
5111 environment()->ExpressionStackAt(2), // Enum cache. | 5135 Add<HLoadKeyed>(environment()->ExpressionStackAt(2), // Enum cache. |
5112 environment()->ExpressionStackAt(0), // Iteration index. | 5136 index, index, FAST_ELEMENTS); |
5113 environment()->ExpressionStackAt(0), | |
5114 FAST_ELEMENTS); | |
5115 | 5137 |
5116 // Check if the expected map still matches that of the enumerable. | 5138 if (fast) { |
5117 // If not just deoptimize. | 5139 // Check if the expected map still matches that of the enumerable. |
5118 Add<HCheckMapValue>(environment()->ExpressionStackAt(4), | 5140 // If not just deoptimize. |
5119 environment()->ExpressionStackAt(3)); | 5141 Add<HCheckMapValue>(enumerable, environment()->ExpressionStackAt(3)); |
5120 | 5142 Bind(each_var, key); |
5121 Bind(each_var, key); | 5143 } else { |
| 5144 HValue* function = AddLoadJSBuiltin(Builtins::FILTER_KEY); |
| 5145 Add<HPushArguments>(enumerable, key); |
| 5146 key = Add<HInvokeFunction>(function, 2); |
| 5147 Bind(each_var, key); |
| 5148 Add<HSimulate>(stmt->AssignmentId()); |
| 5149 Add<HCheckHeapObject>(key); |
| 5150 } |
5122 | 5151 |
5123 BreakAndContinueInfo break_info(stmt, scope(), 5); | 5152 BreakAndContinueInfo break_info(stmt, scope(), 5); |
5124 { | 5153 { |
5125 BreakAndContinueScope push(&break_info, this); | 5154 BreakAndContinueScope push(&break_info, this); |
5126 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry)); | 5155 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry)); |
5127 } | 5156 } |
5128 | 5157 |
5129 HBasicBlock* body_exit = | 5158 HBasicBlock* body_exit = |
5130 JoinContinue(stmt, current_block(), break_info.continue_block()); | 5159 JoinContinue(stmt, current_block(), break_info.continue_block()); |
5131 | 5160 |
(...skipping 7790 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12922 if (ShouldProduceTraceOutput()) { | 12951 if (ShouldProduceTraceOutput()) { |
12923 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 12952 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
12924 } | 12953 } |
12925 | 12954 |
12926 #ifdef DEBUG | 12955 #ifdef DEBUG |
12927 graph_->Verify(false); // No full verify. | 12956 graph_->Verify(false); // No full verify. |
12928 #endif | 12957 #endif |
12929 } | 12958 } |
12930 | 12959 |
12931 } } // namespace v8::internal | 12960 } } // namespace v8::internal |
OLD | NEW |