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; |