Chromium Code Reviews| Index: src/hydrogen.cc |
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
| index e7fbabae1d51e489709c29a9e13f03f51dcd9024..59d28af04e96ef67bfdbacf3f1d78f4251474ea4 100644 |
| --- a/src/hydrogen.cc |
| +++ b/src/hydrogen.cc |
| @@ -3794,6 +3794,13 @@ void TestContext::BuildBranch(HValue* value) { |
| } while (false) |
| +#define CHECK_ALIVE_OR_RETURN(call, value) \ |
| + do { \ |
| + call; \ |
| + if (HasStackOverflow() || current_block() == NULL) return value; \ |
| + } while (false) |
| + |
| + |
| void HOptimizedGraphBuilder::Bailout(const char* reason) { |
| current_info()->set_bailout_reason(reason); |
| SetStackOverflow(); |
| @@ -6296,13 +6303,13 @@ HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic( |
| Handle<String> name) { |
| // Use monomorphic load if property lookup results in the same field index |
| // for all maps. Requires special map check on the set of all handled maps. |
| + if (types->length() > kMaxLoadPolymorphism) return NULL; |
| + |
| LookupResult lookup(isolate()); |
| int count; |
| Representation representation = Representation::None(); |
| HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. |
| - for (count = 0; |
| - count < types->length() && count < kMaxLoadPolymorphism; |
| - ++count) { |
| + for (count = 0; count < types->length(); ++count) { |
| Handle<Map> map = types->at(count); |
| if (!ComputeLoadStoreField(map, name, &lookup, false)) break; |
| @@ -6355,12 +6362,73 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( |
| } |
| +bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic( |
|
Jakob Kummerow
2013/06/14 13:08:05
This method looks very similar to TryLoadPolymorph
|
| + Assignment* expr, |
| + HValue* object, |
| + HValue* value, |
| + SmallMapList* types, |
| + Handle<String> name) { |
| + // Use monomorphic store if property lookup results in the same field index |
| + // for all maps. Requires special map check on the set of all handled maps. |
| + if (types->length() > kMaxStorePolymorphism) return false; |
| + |
| + LookupResult lookup(isolate()); |
| + int count; |
| + Representation representation = Representation::None(); |
| + HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. |
| + for (count = 0; count < types->length(); ++count) { |
| + Handle<Map> map = types->at(count); |
| + // Pass false to ignore transitions. |
| + if (!ComputeLoadStoreField(map, name, &lookup, false)) break; |
| + |
| + HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name); |
| + Representation new_representation = |
| + ComputeLoadStoreRepresentation(map, &lookup); |
| + |
| + if (count == 0) { |
| + // First time through the loop; set access and representation. |
| + access = new_access; |
| + representation = new_representation; |
| + } else if (!representation.IsCompatibleForStore(new_representation)) { |
| + // Representations did not match. |
| + break; |
| + } else if (access.offset() != new_access.offset()) { |
| + // Offsets did not match. |
| + break; |
| + } else if (access.IsInobject() != new_access.IsInobject()) { |
| + // In-objectness did not match. |
| + break; |
| + } |
| + } |
| + |
| + if (count != types->length()) return false; |
| + |
| + // Everything matched; can use monomorphic store. |
| + BuildCheckNonSmi(object); |
| + AddInstruction(HCheckMaps::New(object, types, zone())); |
| + HInstruction* store; |
| + CHECK_ALIVE_OR_RETURN( |
| + store = BuildStoreNamedField(object, name, value, types->at(0), &lookup), |
| + true); |
| + Push(value); |
| + store->set_position(expr->position()); |
| + AddInstruction(store); |
| + AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); |
|
Jakob Kummerow
2013/06/14 13:08:05
For the record, I think it's pointless (but safe)
|
| + ast_context()->ReturnValue(Pop()); |
| + return true; |
| +} |
| + |
| + |
| void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( |
| Assignment* expr, |
| HValue* object, |
| HValue* value, |
| SmallMapList* types, |
| Handle<String> name) { |
| + if (TryStorePolymorphicAsMonomorphic(expr, object, value, types, name)) { |
| + 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. |
| @@ -6383,8 +6451,8 @@ void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( |
| set_current_block(if_true); |
| HInstruction* instr; |
| - CHECK_ALIVE(instr = |
| - BuildStoreNamedField(object, name, value, map, &lookup)); |
| + CHECK_ALIVE( |
| + instr = BuildStoreNamedField(object, name, value, map, &lookup)); |
| instr->set_position(expr->position()); |
| // Goto will add the HSimulate for the store. |
| AddInstruction(instr); |
| @@ -6428,7 +6496,7 @@ void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( |
| ASSERT(join != NULL); |
| join->SetJoinId(expr->id()); |
| set_current_block(join); |
| - if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); |
| + if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
| } |