Index: src/compiler/access-info.cc |
diff --git a/src/compiler/access-info.cc b/src/compiler/access-info.cc |
index 436181b1750d277e82cdcc7f3b3b47f4d17d708a..9173811da5f512d7f1f2b4fcda083143ef1aabc6 100644 |
--- a/src/compiler/access-info.cc |
+++ b/src/compiler/access-info.cc |
@@ -81,6 +81,14 @@ PropertyAccessInfo PropertyAccessInfo::DataField( |
ElementAccessInfo::ElementAccessInfo() : receiver_type_(Type::None()) {} |
+ElementAccessInfo::ElementAccessInfo(Type* receiver_type, |
+ ElementsKind elements_kind, |
+ MaybeHandle<JSObject> holder) |
+ : elements_kind_(elements_kind), |
+ holder_(holder), |
+ receiver_type_(receiver_type) {} |
+ |
+ |
PropertyAccessInfo::PropertyAccessInfo() |
: kind_(kInvalid), receiver_type_(Type::None()), field_type_(Type::Any()) {} |
@@ -153,15 +161,50 @@ bool AccessInfoFactory::ComputeElementAccessInfo( |
bool AccessInfoFactory::ComputeElementAccessInfos( |
MapHandleList const& maps, AccessMode access_mode, |
ZoneVector<ElementAccessInfo>* access_infos) { |
+ // Collect possible transition targets. |
+ MapHandleList possible_transition_targets(maps.length()); |
for (Handle<Map> map : maps) { |
if (Map::TryUpdate(map).ToHandle(&map)) { |
- ElementAccessInfo access_info; |
- if (!ComputeElementAccessInfo(map, access_mode, &access_info)) { |
- return false; |
+ if (CanInlineElementAccess(map) && |
+ IsFastElementsKind(map->elements_kind()) && |
+ GetInitialFastElementsKind() != map->elements_kind()) { |
+ possible_transition_targets.Add(map); |
} |
- access_infos->push_back(access_info); |
} |
} |
+ |
+ // Separate the actual receiver maps and the possible transition sources. |
+ MapHandleList receiver_maps(maps.length()); |
+ MapTransitionList transitions(maps.length()); |
+ for (Handle<Map> map : maps) { |
+ if (Map::TryUpdate(map).ToHandle(&map)) { |
+ Handle<Map> transition_target = |
+ Map::FindTransitionedMap(map, &possible_transition_targets); |
+ if (transition_target.is_null()) { |
+ receiver_maps.Add(map); |
+ } else { |
+ transitions.push_back(std::make_pair(map, transition_target)); |
+ } |
+ } |
+ } |
+ |
+ for (Handle<Map> receiver_map : receiver_maps) { |
+ // Compute the element access information. |
+ ElementAccessInfo access_info; |
+ if (!ComputeElementAccessInfo(receiver_map, access_mode, &access_info)) { |
+ return false; |
+ } |
+ |
+ // Collect the possible transitions for the {receiver_map}. |
+ for (auto transition : transitions) { |
+ if (transition.second.is_identical_to(receiver_map)) { |
+ access_info.transitions().push_back(transition); |
+ } |
+ } |
+ |
+ // Schedule the access information. |
+ access_infos->push_back(access_info); |
+ } |
return true; |
} |