Chromium Code Reviews| Index: src/hydrogen.cc |
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
| index d6cbc1444ad52eac67ab0f98ecd35f3a8e3943ae..cf4c87f02e70a73b57b6a0edeb72e687bb3311aa 100644 |
| --- a/src/hydrogen.cc |
| +++ b/src/hydrogen.cc |
| @@ -5050,10 +5050,6 @@ void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) { |
| return Bailout(kForInStatementOptimizationIsDisabled); |
| } |
| - if (stmt->for_in_type() != ForInStatement::FAST_FOR_IN) { |
| - return Bailout(kForInStatementIsNotFastCase); |
| - } |
| - |
| if (!stmt->each()->IsVariableProxy() || |
| !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) { |
| return Bailout(kForInStatementWithNonLocalEachVariable); |
| @@ -5064,13 +5060,42 @@ void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) { |
| CHECK_ALIVE(VisitForValue(stmt->enumerable())); |
| HValue* enumerable = Top(); // Leave enumerable at the top. |
| - HInstruction* map = Add<HForInPrepareMap>(enumerable); |
| - Add<HSimulate>(stmt->PrepareId()); |
| - |
| - HInstruction* array = Add<HForInCacheArray>( |
| - enumerable, map, DescriptorArray::kEnumCacheBridgeCacheIndex); |
| + HInstruction* map; |
| + HInstruction* array; |
| + HInstruction* enum_length; |
| + bool fast = stmt->for_in_type() == ForInStatement::FAST_FOR_IN; |
| + if (fast) { |
| + map = Add<HForInPrepareMap>(enumerable); |
| + Add<HSimulate>(stmt->PrepareId()); |
| + |
| + array = Add<HForInCacheArray>(enumerable, map, |
| + DescriptorArray::kEnumCacheBridgeCacheIndex); |
| + enum_length = Add<HMapEnumLength>(map); |
| + |
| + HInstruction* index_cache = Add<HForInCacheArray>( |
| + enumerable, map, DescriptorArray::kEnumCacheBridgeIndicesCacheIndex); |
| + HForInCacheArray::cast(array) |
| + ->set_index_cache(HForInCacheArray::cast(index_cache)); |
| + } else { |
| + Add<HSimulate>(stmt->PrepareId()); |
| + { |
| + NoObservableSideEffectsScope no_effects(this); |
| + BuildJSObjectCheck(enumerable, 0); |
| + } |
| + Add<HSimulate>(stmt->ToObjectId()); |
| - HInstruction* enum_length = Add<HMapEnumLength>(map); |
| + map = graph()->GetConstant1(); |
| + Runtime::FunctionId function_id = Runtime::kGetPropertyNamesFast; |
| + Add<HPushArguments>(enumerable); |
| + array = Add<HCallRuntime>(isolate()->factory()->empty_string(), |
| + Runtime::FunctionForId(function_id), 1); |
| + Push(array); |
| + Add<HSimulate>(stmt->EnumId()); |
| + Drop(1); |
| + Handle<Map> array_map = isolate()->factory()->fixed_array_map(); |
| + HValue* check = Add<HCheckMaps>(array, array_map); |
| + enum_length = AddLoadFixedArrayLength(array, check); |
| + } |
| HInstruction* start_index = Add<HConstant>(0); |
| @@ -5079,13 +5104,9 @@ void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) { |
| Push(enum_length); |
| Push(start_index); |
| - HInstruction* index_cache = Add<HForInCacheArray>( |
| - enumerable, map, DescriptorArray::kEnumCacheBridgeIndicesCacheIndex); |
| - HForInCacheArray::cast(array)->set_index_cache( |
| - HForInCacheArray::cast(index_cache)); |
| - |
| HBasicBlock* loop_entry = BuildLoopEntry(stmt); |
| + enumerable = environment()->ExpressionStackAt(4); |
|
mvstanton
2015/04/10 11:40:07
nit: why do you need to get enumerable again? Add
|
| HValue* index = environment()->ExpressionStackAt(0); |
| HValue* limit = environment()->ExpressionStackAt(1); |
| @@ -5107,18 +5128,23 @@ void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) { |
| set_current_block(loop_body); |
| - HValue* key = Add<HLoadKeyed>( |
| - environment()->ExpressionStackAt(2), // Enum cache. |
| - environment()->ExpressionStackAt(0), // Iteration index. |
| - environment()->ExpressionStackAt(0), |
| - FAST_ELEMENTS); |
| + HValue* key = |
| + Add<HLoadKeyed>(environment()->ExpressionStackAt(2), // Enum cache. |
| + index, index, FAST_ELEMENTS); |
| - // Check if the expected map still matches that of the enumerable. |
| - // If not just deoptimize. |
| - Add<HCheckMapValue>(environment()->ExpressionStackAt(4), |
| - environment()->ExpressionStackAt(3)); |
| - |
| - Bind(each_var, key); |
| + if (fast) { |
| + // Check if the expected map still matches that of the enumerable. |
| + // If not just deoptimize. |
| + Add<HCheckMapValue>(enumerable, environment()->ExpressionStackAt(3)); |
| + Bind(each_var, key); |
| + } else { |
| + HValue* function = AddLoadJSBuiltin(Builtins::FILTER_KEY); |
| + Add<HPushArguments>(enumerable, key); |
| + key = Add<HInvokeFunction>(function, 2); |
| + Bind(each_var, key); |
| + Add<HSimulate>(stmt->AssignmentId()); |
| + Add<HCheckHeapObject>(key); |
| + } |
| BreakAndContinueInfo break_info(stmt, scope(), 5); |
| { |