Chromium Code Reviews| Index: src/hydrogen.cc | 
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc | 
| index b93df482861615d499b3b4668143e2537ca9bab4..03a93c3e6550ffd86c64733a4bb6269b4b0db4f1 100644 | 
| --- a/src/hydrogen.cc | 
| +++ b/src/hydrogen.cc | 
| @@ -5370,7 +5370,7 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedField( | 
| access = HObjectAccess::ForHeapNumberValue(); | 
| } | 
| return New<HLoadNamedField>( | 
| - checked_object, static_cast<HValue*>(NULL), access, info->field_map()); | 
| + checked_object, checked_object, access, info->field_maps(), top_info()); | 
| } | 
| @@ -5414,10 +5414,15 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField( | 
| value, STORE_TO_INITIALIZED_ENTRY); | 
| } | 
| } else { | 
| - if (!info->field_map().is_null()) { | 
| + if (!info->field_maps()->is_empty()) { | 
| ASSERT(field_access.representation().IsHeapObject()); | 
| BuildCheckHeapObject(value); | 
| - value = BuildCheckMap(value, info->field_map()); | 
| + if (info->field_maps()->length() == 1) { | 
| + // TODO(bmeurer): Also apply stable maps optimization to the else case! | 
| 
 
Benedikt Meurer
2014/04/16 07:35:24
Note that this requires changes to the HCheckMaps,
 
 | 
| + value = BuildCheckMap(value, info->field_maps()->first()); | 
| + } else { | 
| + value = Add<HCheckMaps>(value, info->field_maps()); | 
| + } | 
| // TODO(bmeurer): This is a dirty hack to avoid repeating the smi check | 
| // that was already performed by the HCheckHeapObject above in the | 
| @@ -5489,11 +5494,22 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatible( | 
| } | 
| if (info->access_.offset() != access_.offset()) return false; | 
| if (info->access_.IsInobject() != access_.IsInobject()) return false; | 
| - if (!field_map_.is_identical_to(info->field_map_)) { | 
| - if (!IsLoad()) return false; | 
| - | 
| - // Throw away type information for merging polymorphic loads. | 
| - field_map_ = info->field_map_ = Handle<Map>(); | 
| + if (IsLoad()) { | 
| + if (field_maps_.is_empty() || info->field_maps_.is_empty()) { | 
| + info->field_maps_.Clear(); | 
| + } else { | 
| + for (int i = 0; i < field_maps_.length(); ++i) { | 
| + info->field_maps_.AddMapIfMissing(field_maps_.at(i), info->zone()); | 
| + } | 
| + info->field_maps_.Sort(); | 
| + } | 
| + } else { | 
| + if (field_maps_.length() != info->field_maps_.length()) return false; | 
| + for (int i = 0; i < field_maps_.length(); ++i) { | 
| + if (!field_maps_.at(i).is_identical_to(info->field_maps_.at(i))) { | 
| + return false; | 
| + } | 
| + } | 
| } | 
| info->GeneralizeRepresentation(r); | 
| return true; | 
| @@ -5518,7 +5534,7 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) { | 
| access_ = HObjectAccess::ForField(map, &lookup_, name_); | 
| // Load field map for heap objects. | 
| - if (access_.representation().IsHeapObject()) LoadFieldMap(map); | 
| + if (access_.representation().IsHeapObject()) LoadFieldMaps(map); | 
| } else if (lookup_.IsPropertyCallbacks()) { | 
| Handle<Object> callback(lookup_.GetValueFromMap(*map), isolate()); | 
| if (!callback->IsAccessorPair()) return false; | 
| @@ -5545,22 +5561,34 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) { | 
| } | 
| -void HOptimizedGraphBuilder::PropertyAccessInfo::LoadFieldMap(Handle<Map> map) { | 
| - // Figure out the field type from the accessor map. | 
| - HeapType* field_type = lookup_.GetFieldTypeFromMap(*map); | 
| - if (field_type->IsClass()) { | 
| - Handle<Map> field_map = field_type->AsClass(); | 
| - if (field_map->is_stable()) { | 
| - field_map_ = field_map; | 
| - Map::AddDependentCompilationInfo( | 
| - field_map_, DependentCode::kPrototypeCheckGroup, top_info()); | 
| +void HOptimizedGraphBuilder::PropertyAccessInfo::LoadFieldMaps( | 
| + Handle<Map> map) { | 
| + ASSERT(field_maps_.is_empty()); | 
| - // Add dependency on the map that introduced the field. | 
| - Map::AddDependentCompilationInfo( | 
| - handle(lookup_.GetFieldOwnerFromMap(*map), isolate()), | 
| - DependentCode::kFieldTypeGroup, top_info()); | 
| + // Figure out the field type from the accessor map. | 
| + Handle<HeapType> field_type(lookup_.GetFieldTypeFromMap(*map), isolate()); | 
| + | 
| + // Collect the (stable) maps from the field type. | 
| + int num_field_maps = field_type->NumClasses(); | 
| + if (num_field_maps == 0) return; | 
| + field_maps_.Reserve(num_field_maps, zone()); | 
| + HeapType::Iterator<Map> it = field_type->Classes(); | 
| + while (!it.Done()) { | 
| + Handle<Map> field_map = it.Current(); | 
| + if (!field_map->is_stable()) { | 
| + field_maps_.Clear(); | 
| + return; | 
| } | 
| + field_maps_.Add(field_map, zone()); | 
| + it.Advance(); | 
| } | 
| + field_maps_.Sort(); | 
| + ASSERT_EQ(num_field_maps, field_maps_.length()); | 
| + | 
| + // Add dependency on the map that introduced the field. | 
| + Map::AddDependentCompilationInfo( | 
| + handle(lookup_.GetFieldOwnerFromMap(*map), isolate()), | 
| + DependentCode::kFieldTypeGroup, top_info()); | 
| } | 
| @@ -5604,7 +5632,7 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() { | 
| access_ = HObjectAccess::ForField(map, &lookup_, name_); | 
| // Load field map for heap objects. | 
| - if (access_.representation().IsHeapObject()) LoadFieldMap(transition()); | 
| + if (access_.representation().IsHeapObject()) LoadFieldMaps(transition()); | 
| return true; | 
| } | 
| return false; |