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 enumerable = environment()->ExpressionStackAt(4); | |
mvstanton
2015/04/10 11:40:07
nit: why do you need to get enumerable again? Add
| |
5089 HValue* index = environment()->ExpressionStackAt(0); | 5110 HValue* index = environment()->ExpressionStackAt(0); |
5090 HValue* limit = environment()->ExpressionStackAt(1); | 5111 HValue* limit = environment()->ExpressionStackAt(1); |
5091 | 5112 |
5092 // Check that we still have more keys. | 5113 // Check that we still have more keys. |
5093 HCompareNumericAndBranch* compare_index = | 5114 HCompareNumericAndBranch* compare_index = |
5094 New<HCompareNumericAndBranch>(index, limit, Token::LT); | 5115 New<HCompareNumericAndBranch>(index, limit, Token::LT); |
5095 compare_index->set_observed_input_representation( | 5116 compare_index->set_observed_input_representation( |
5096 Representation::Smi(), Representation::Smi()); | 5117 Representation::Smi(), Representation::Smi()); |
5097 | 5118 |
5098 HBasicBlock* loop_body = graph()->CreateBasicBlock(); | 5119 HBasicBlock* loop_body = graph()->CreateBasicBlock(); |
5099 HBasicBlock* loop_successor = graph()->CreateBasicBlock(); | 5120 HBasicBlock* loop_successor = graph()->CreateBasicBlock(); |
5100 | 5121 |
5101 compare_index->SetSuccessorAt(0, loop_body); | 5122 compare_index->SetSuccessorAt(0, loop_body); |
5102 compare_index->SetSuccessorAt(1, loop_successor); | 5123 compare_index->SetSuccessorAt(1, loop_successor); |
5103 FinishCurrentBlock(compare_index); | 5124 FinishCurrentBlock(compare_index); |
5104 | 5125 |
5105 set_current_block(loop_successor); | 5126 set_current_block(loop_successor); |
5106 Drop(5); | 5127 Drop(5); |
5107 | 5128 |
5108 set_current_block(loop_body); | 5129 set_current_block(loop_body); |
5109 | 5130 |
5110 HValue* key = Add<HLoadKeyed>( | 5131 HValue* key = |
5111 environment()->ExpressionStackAt(2), // Enum cache. | 5132 Add<HLoadKeyed>(environment()->ExpressionStackAt(2), // Enum cache. |
5112 environment()->ExpressionStackAt(0), // Iteration index. | 5133 index, index, FAST_ELEMENTS); |
5113 environment()->ExpressionStackAt(0), | |
5114 FAST_ELEMENTS); | |
5115 | 5134 |
5116 // Check if the expected map still matches that of the enumerable. | 5135 if (fast) { |
5117 // If not just deoptimize. | 5136 // Check if the expected map still matches that of the enumerable. |
5118 Add<HCheckMapValue>(environment()->ExpressionStackAt(4), | 5137 // If not just deoptimize. |
5119 environment()->ExpressionStackAt(3)); | 5138 Add<HCheckMapValue>(enumerable, environment()->ExpressionStackAt(3)); |
5120 | 5139 Bind(each_var, key); |
5121 Bind(each_var, key); | 5140 } else { |
5141 HValue* function = AddLoadJSBuiltin(Builtins::FILTER_KEY); | |
5142 Add<HPushArguments>(enumerable, key); | |
5143 key = Add<HInvokeFunction>(function, 2); | |
5144 Bind(each_var, key); | |
5145 Add<HSimulate>(stmt->AssignmentId()); | |
5146 Add<HCheckHeapObject>(key); | |
5147 } | |
5122 | 5148 |
5123 BreakAndContinueInfo break_info(stmt, scope(), 5); | 5149 BreakAndContinueInfo break_info(stmt, scope(), 5); |
5124 { | 5150 { |
5125 BreakAndContinueScope push(&break_info, this); | 5151 BreakAndContinueScope push(&break_info, this); |
5126 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry)); | 5152 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry)); |
5127 } | 5153 } |
5128 | 5154 |
5129 HBasicBlock* body_exit = | 5155 HBasicBlock* body_exit = |
5130 JoinContinue(stmt, current_block(), break_info.continue_block()); | 5156 JoinContinue(stmt, current_block(), break_info.continue_block()); |
5131 | 5157 |
(...skipping 7790 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
12922 if (ShouldProduceTraceOutput()) { | 12948 if (ShouldProduceTraceOutput()) { |
12923 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 12949 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
12924 } | 12950 } |
12925 | 12951 |
12926 #ifdef DEBUG | 12952 #ifdef DEBUG |
12927 graph_->Verify(false); // No full verify. | 12953 graph_->Verify(false); // No full verify. |
12928 #endif | 12954 #endif |
12929 } | 12955 } |
12930 | 12956 |
12931 } } // namespace v8::internal | 12957 } } // namespace v8::internal |
OLD | NEW |