Index: src/hydrogen.cc |
diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
index 1593301e2ec715f7e67f0bfb17446f9941ad9fb0..ce83d901cf1387b6bdbfd5f032674c5c93bc6a58 100644 |
--- a/src/hydrogen.cc |
+++ b/src/hydrogen.cc |
@@ -5610,10 +5610,12 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreMonomorphic( |
} |
-void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( |
+void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess( |
+ PropertyAccessType access_type, |
BailoutId ast_id, |
BailoutId return_id, |
HValue* object, |
+ HValue* value, |
SmallMapList* types, |
Handle<String> name) { |
// Something did not match; must use a polymorphic load. |
@@ -5623,8 +5625,9 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( |
bool handled_string = false; |
bool handle_smi = false; |
+ STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism); |
for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { |
- PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name); |
+ PropertyAccessInfo info(this, access_type, ToType(types->at(i)), name); |
if (info.type()->Is(Type::String())) { |
if (handled_string) continue; |
handled_string = true; |
@@ -5643,7 +5646,7 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( |
handled_string = false; |
for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { |
- PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name); |
+ PropertyAccessInfo info(this, access_type, ToType(types->at(i)), name); |
if (info.type()->Is(Type::String())) { |
if (handled_string) continue; |
handled_string = true; |
@@ -5692,16 +5695,28 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( |
set_current_block(if_true); |
- HInstruction* load = BuildLoadMonomorphic( |
- &info, object, dependency, ast_id, |
- return_id, FLAG_polymorphic_inlining); |
- if (load == NULL) { |
+ HInstruction* access = NULL; |
+ HValue* result = NULL; |
+ switch (access_type) { |
+ case LOAD: |
+ access = BuildLoadMonomorphic( |
+ &info, object, dependency, ast_id, |
+ return_id, FLAG_polymorphic_inlining); |
+ result = access; |
+ break; |
+ case STORE: |
+ access = BuildStoreMonomorphic( |
+ &info, dependency, value, ast_id, return_id, |
+ FLAG_polymorphic_inlining); |
+ result = value; |
+ break; |
+ } |
+ |
+ if (access == NULL) { |
if (HasStackOverflow()) return; |
} else { |
- if (!load->IsLinked()) { |
- AddInstruction(load); |
- } |
- if (!ast_context()->IsEffect()) Push(load); |
+ if (!access->IsLinked()) AddInstruction(access); |
+ if (!ast_context()->IsEffect()) Push(result); |
} |
if (current_block() != NULL) Goto(join); |
@@ -5716,10 +5731,28 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( |
// that the environment stack matches the depth on deopt that it otherwise |
// would have had after a successful load. |
if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); |
- FinishExitWithHardDeoptimization("Unknown map in polymorphic load", join); |
+ const char* message = ""; |
+ switch (access_type) { |
+ case LOAD: |
+ message = "Unknown map in polymorphic load"; |
+ break; |
+ case STORE: |
+ message = "Unknown map in polymorphic store"; |
+ break; |
+ } |
+ FinishExitWithHardDeoptimization(message, join); |
} else { |
- HInstruction* load = Add<HLoadNamedGeneric>(object, name); |
- if (!ast_context()->IsEffect()) Push(load); |
+ HValue* result = NULL; |
+ switch (access_type) { |
+ case LOAD: |
+ result = Add<HLoadNamedGeneric>(object, name); |
+ break; |
+ case STORE: |
+ AddInstruction(BuildStoreNamedGeneric(object, name, value)); |
+ result = value; |
+ break; |
+ } |
+ if (!ast_context()->IsEffect()) Push(result); |
if (join != NULL) { |
Goto(join); |
@@ -5737,90 +5770,6 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( |
} |
-void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( |
- BailoutId assignment_id, |
- BailoutId return_id, |
- HValue* object, |
- HValue* value, |
- SmallMapList* types, |
- Handle<String> name) { |
- int count = 0; |
- HBasicBlock* join = NULL; |
- // TODO(verwaest): Unify with polymorphic load handling. |
- for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { |
- PropertyAccessInfo info(this, STORE, ToType(types->at(i)), name); |
- if (info.CanAccessMonomorphic()) { |
- if (count == 0) { |
- BuildCheckHeapObject(object); |
- join = graph()->CreateBasicBlock(); |
- } |
- ++count; |
- HBasicBlock* if_true = graph()->CreateBasicBlock(); |
- HBasicBlock* if_false = graph()->CreateBasicBlock(); |
- HCompareMap* compare = New<HCompareMap>( |
- object, info.map(), if_true, if_false); |
- FinishCurrentBlock(compare); |
- |
- set_current_block(if_true); |
- |
- HInstruction* store; |
- store = BuildStoreMonomorphic( |
- &info, compare, value, assignment_id, return_id, |
- FLAG_polymorphic_inlining); |
- |
- if (store == NULL) { |
- if (HasStackOverflow()) return; |
- } else { |
- ASSERT(!store->IsLinked()); |
- AddInstruction(store); |
- if (!ast_context()->IsEffect()) Push(value); |
- } |
- |
- if (current_block() != NULL) Goto(join); |
- set_current_block(if_false); |
- } |
- } |
- |
- // 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) { |
- FinishExitWithHardDeoptimization("Unknown map in polymorphic store", join); |
- } else { |
- HInstruction* instr = BuildStoreNamedGeneric(object, name, value); |
- AddInstruction(instr); |
- |
- if (join != NULL) { |
- if (!ast_context()->IsEffect()) { |
- Push(value); |
- } |
- 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()) { |
- Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE); |
- } else { |
- Push(value); |
- Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE); |
- Drop(1); |
- } |
- } |
- return ast_context()->ReturnValue(value); |
- } |
- } |
- |
- ASSERT(join != NULL); |
- join->SetJoinId(assignment_id); |
- set_current_block(join); |
- if (!ast_context()->IsEffect()) { |
- ast_context()->ReturnValue(Pop()); |
- } |
-} |
- |
- |
static bool ComputeReceiverTypes(Expression* expr, |
HValue* receiver, |
SmallMapList** t, |
@@ -5882,8 +5831,8 @@ void HOptimizedGraphBuilder::BuildStore(Expression* expr, |
if (types->length() > 0) { |
PropertyAccessInfo info(this, STORE, ToType(types->first()), name); |
if (!info.CanAccessAsMonomorphic(types)) { |
- return HandlePolymorphicStoreNamedField( |
- ast_id, return_id, object, value, types, name); |
+ return HandlePolymorphicNamedFieldAccess( |
+ STORE, ast_id, return_id, object, value, types, name); |
} |
ASSERT(!info.type()->Is(Type::Number())); |
@@ -6734,8 +6683,8 @@ void HOptimizedGraphBuilder::BuildLoad(Property* expr, |
if (types->length() > 0) { |
PropertyAccessInfo info(this, LOAD, ToType(types->first()), name); |
if (!info.CanAccessAsMonomorphic(types)) { |
- return HandlePolymorphicLoadNamedField( |
- ast_id, expr->LoadId(), object, types, name); |
+ return HandlePolymorphicNamedFieldAccess( |
+ LOAD, ast_id, expr->LoadId(), object, NULL, types, name); |
} |
HValue* checked_object; |