Chromium Code Reviews| Index: src/hydrogen.cc |
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
| index 741b8c53ada0e4d19399e4e72830b1b9f18446b0..f2842ffc5fc72908896d9be96a42c2b59085c304 100644 |
| --- a/src/hydrogen.cc |
| +++ b/src/hydrogen.cc |
| @@ -5784,6 +5784,52 @@ bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic( |
| } |
| +void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedFieldHelper( |
| + HValue* object, |
| + Handle<String> name, |
| + HValue* value, |
| + SmallMapList* types, |
| + int current_type, |
| + int stored_count, |
| + int position) { |
| + HInstruction* instr = NULL; |
| + if (stored_count == kMaxStorePolymorphism || |
| + (current_type == types->length() - 1)) { |
|
Toon Verwaest
2013/07/08 16:49:00
remove the - 1
|
| + if (FLAG_deoptimize_uncommon_cases) { |
| + AddSoftDeoptimize(MUST_EMIT_SOFT_DEOPT); |
|
Toon Verwaest
2013/07/08 16:49:00
Soft deopts aren't counted towards MaxDeopt to sto
|
| + } else { |
| + instr = BuildStoreNamedGeneric(object, name, value); |
| + instr->set_position(position); |
| + AddInstruction(instr); |
| + } |
| + return; |
| + } |
| + |
| + Handle<Map> map = types->at(current_type); |
| + LookupResult lookup(isolate()); |
| + if (!ComputeLoadStoreField(map, name, &lookup, true)) { |
| + HandlePolymorphicStoreNamedFieldHelper(object, name, value, types, |
| + current_type + 1, stored_count, |
| + position); |
| + return; |
| + } |
| + |
| + IfBuilder builder(this); |
| + builder.If<HCompareMap>(object, map); |
| + |
| + builder.Then(); |
| + CHECK_ALIVE(instr = BuildStoreNamedField(object, name, value, map, &lookup)); |
| + instr->set_position(position); |
| + AddInstruction(instr); |
| + |
| + builder.Else(); |
| + HandlePolymorphicStoreNamedFieldHelper(object, name, value, types, |
| + current_type + 1, stored_count + 1, |
| + position); |
| + builder.End(); |
| +} |
| + |
| + |
| void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( |
| BailoutId id, |
| int position, |
| @@ -5797,74 +5843,20 @@ void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( |
| return; |
| } |
| - // TODO(ager): We should recognize when the prototype chains for different |
| - // maps are identical. In that case we can avoid repeatedly generating the |
| - // same prototype map checks. |
| - int count = 0; |
| - HBasicBlock* join = NULL; |
| - for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { |
| - Handle<Map> map = types->at(i); |
| - LookupResult lookup(isolate()); |
| - if (ComputeLoadStoreField(map, name, &lookup, true)) { |
| - if (count == 0) { |
| - BuildCheckHeapObject(object); |
| - join = graph()->CreateBasicBlock(); |
| - } |
| - ++count; |
| - HBasicBlock* if_true = graph()->CreateBasicBlock(); |
| - HBasicBlock* if_false = graph()->CreateBasicBlock(); |
| - HCompareMap* compare = |
| - new(zone()) HCompareMap(object, map, if_true, if_false); |
| - current_block()->Finish(compare); |
| - |
| - set_current_block(if_true); |
| - HInstruction* instr; |
| - CHECK_ALIVE( |
| - instr = BuildStoreNamedField(object, name, value, map, &lookup)); |
| - instr->set_position(position); |
| - // Goto will add the HSimulate for the store. |
| - AddInstruction(instr); |
| - if (!ast_context()->IsEffect()) Push(value); |
| - current_block()->Goto(join); |
| - |
| - set_current_block(if_false); |
| - } |
| + { |
| + Add<HCheckHeapObject>(object); |
| + NoObservableSideEffectsScope no_effects(this); |
| + HandlePolymorphicStoreNamedFieldHelper(object, name, value, types, |
| + 0, 0, position); |
| } |
| - // Finish up. Unconditionally deoptimize if we've handled all the maps we |
| - // know about and do not want to handle ones we've never seen. Otherwise |
| - // use a generic IC. |
| - if (count == types->length() && FLAG_deoptimize_uncommon_cases) { |
| - current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); |
| + if (ast_context()->IsEffect()) { |
| + AddSimulate(id, REMOVABLE_SIMULATE); |
| } else { |
| - HInstruction* instr = BuildStoreNamedGeneric(object, name, value); |
| - instr->set_position(position); |
| - AddInstruction(instr); |
| - |
| - if (join != NULL) { |
| - if (!ast_context()->IsEffect()) Push(value); |
| - current_block()->Goto(join); |
| - } else { |
| - // The HSimulate for the store should not see the stored value in |
| - // effect contexts (it is not materialized at expr->id() in the |
| - // unoptimized code). |
| - if (instr->HasObservableSideEffects()) { |
| - if (ast_context()->IsEffect()) { |
| - AddSimulate(id, REMOVABLE_SIMULATE); |
| - } else { |
| - Push(value); |
| - AddSimulate(id, REMOVABLE_SIMULATE); |
| - Drop(1); |
| - } |
| - } |
| - return ast_context()->ReturnValue(value); |
| - } |
| + Push(value); |
| + AddSimulate(id, REMOVABLE_SIMULATE); |
| + ast_context()->ReturnValue(Pop()); |
| } |
| - |
| - ASSERT(join != NULL); |
| - join->SetJoinId(id); |
| - set_current_block(join); |
| - if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
| } |