Index: src/compiler/access-info.cc |
diff --git a/src/compiler/access-info.cc b/src/compiler/access-info.cc |
index 768b98502e871de5985755d70bb8b412ecdcfe7f..ecb9482c113698a2dd26e9cbec06164147208dc4 100644 |
--- a/src/compiler/access-info.cc |
+++ b/src/compiler/access-info.cc |
@@ -56,59 +56,51 @@ std::ostream& operator<<(std::ostream& os, AccessMode access_mode) { |
return os; |
} |
+ElementAccessInfo::ElementAccessInfo() {} |
+ |
+ElementAccessInfo::ElementAccessInfo(MapList const& receiver_maps, |
+ ElementsKind elements_kind, |
+ MaybeHandle<JSObject> holder) |
+ : elements_kind_(elements_kind), |
+ holder_(holder), |
+ receiver_maps_(receiver_maps) {} |
// static |
-PropertyAccessInfo PropertyAccessInfo::NotFound(Type* receiver_type, |
+PropertyAccessInfo PropertyAccessInfo::NotFound(MapList const& receiver_maps, |
MaybeHandle<JSObject> holder) { |
- return PropertyAccessInfo(holder, receiver_type); |
+ return PropertyAccessInfo(holder, receiver_maps); |
} |
- |
// static |
PropertyAccessInfo PropertyAccessInfo::DataConstant( |
- Type* receiver_type, Handle<Object> constant, |
+ MapList const& receiver_maps, Handle<Object> constant, |
MaybeHandle<JSObject> holder) { |
- return PropertyAccessInfo(holder, constant, receiver_type); |
+ return PropertyAccessInfo(holder, constant, receiver_maps); |
} |
- |
// static |
PropertyAccessInfo PropertyAccessInfo::DataField( |
- Type* receiver_type, FieldIndex field_index, Type* field_type, |
+ MapList const& receiver_maps, FieldIndex field_index, Type* field_type, |
MaybeHandle<JSObject> holder, MaybeHandle<Map> transition_map) { |
return PropertyAccessInfo(holder, transition_map, field_index, field_type, |
- receiver_type); |
+ receiver_maps); |
} |
- |
-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()) {} |
- |
+ : kind_(kInvalid), field_type_(Type::Any()) {} |
PropertyAccessInfo::PropertyAccessInfo(MaybeHandle<JSObject> holder, |
- Type* receiver_type) |
+ MapList const& receiver_maps) |
: kind_(kNotFound), |
- receiver_type_(receiver_type), |
+ receiver_maps_(receiver_maps), |
holder_(holder), |
field_type_(Type::Any()) {} |
- |
PropertyAccessInfo::PropertyAccessInfo(MaybeHandle<JSObject> holder, |
Handle<Object> constant, |
- Type* receiver_type) |
+ MapList const& receiver_maps) |
: kind_(kDataConstant), |
- receiver_type_(receiver_type), |
+ receiver_maps_(receiver_maps), |
constant_(constant), |
holder_(holder), |
field_type_(Type::Any()) {} |
@@ -116,14 +108,55 @@ PropertyAccessInfo::PropertyAccessInfo(MaybeHandle<JSObject> holder, |
PropertyAccessInfo::PropertyAccessInfo(MaybeHandle<JSObject> holder, |
MaybeHandle<Map> transition_map, |
FieldIndex field_index, Type* field_type, |
- Type* receiver_type) |
+ MapList const& receiver_maps) |
: kind_(kDataField), |
- receiver_type_(receiver_type), |
+ receiver_maps_(receiver_maps), |
transition_map_(transition_map), |
holder_(holder), |
field_index_(field_index), |
field_type_(field_type) {} |
+bool PropertyAccessInfo::Merge(PropertyAccessInfo const* that) { |
+ if (this->kind_ != that->kind_) return false; |
+ if (this->holder_.address() != that->holder_.address()) return false; |
+ |
+ switch (this->kind_) { |
+ case kInvalid: |
+ break; |
+ |
+ case kNotFound: |
+ return true; |
+ |
+ case kDataField: { |
+ // Check if we actually access the same field. |
+ if (this->transition_map_.address() == that->transition_map_.address() && |
+ this->field_index_ == that->field_index_ && |
+ this->field_type_->Is(that->field_type_) && |
+ that->field_type_->Is(this->field_type_)) { |
+ this->receiver_maps_.insert(this->receiver_maps_.end(), |
+ that->receiver_maps_.begin(), |
+ that->receiver_maps_.end()); |
+ return true; |
+ } |
+ return false; |
+ } |
+ |
+ case kDataConstant: { |
+ // Check if we actually access the same constant. |
+ if (this->constant_.address() == that->constant_.address()) { |
+ this->receiver_maps_.insert(this->receiver_maps_.end(), |
+ that->receiver_maps_.begin(), |
+ that->receiver_maps_.end()); |
+ return true; |
+ } |
+ return false; |
+ } |
+ } |
+ |
+ UNREACHABLE(); |
+ return false; |
+} |
+ |
AccessInfoFactory::AccessInfoFactory(CompilationDependencies* dependencies, |
Handle<Context> native_context, Zone* zone) |
: dependencies_(dependencies), |
@@ -161,8 +194,7 @@ bool AccessInfoFactory::ComputeElementAccessInfo( |
} |
} |
- *access_info = |
- ElementAccessInfo(Type::Class(map, zone()), elements_kind, holder); |
+ *access_info = ElementAccessInfo(MapList{map}, elements_kind, holder); |
return true; |
} |
@@ -258,7 +290,7 @@ bool AccessInfoFactory::ComputePropertyAccessInfo( |
} |
if (details.type() == DATA_CONSTANT) { |
*access_info = PropertyAccessInfo::DataConstant( |
- Type::Class(receiver_map, zone()), |
+ MapList{receiver_map}, |
handle(descriptors->GetValue(number), isolate()), holder); |
return true; |
} else if (details.type() == DATA) { |
@@ -294,7 +326,7 @@ bool AccessInfoFactory::ComputePropertyAccessInfo( |
DCHECK(field_type->Is(Type::TaggedPointer())); |
} |
*access_info = PropertyAccessInfo::DataField( |
- Type::Class(receiver_map, zone()), field_index, field_type, holder); |
+ MapList{receiver_map}, field_index, field_type, holder); |
return true; |
} else { |
// TODO(bmeurer): Add support for accessors. |
@@ -331,8 +363,8 @@ bool AccessInfoFactory::ComputePropertyAccessInfo( |
// The property was not found, return undefined or throw depending |
// on the language mode of the load operation. |
// Implemented according to ES6 section 9.1.8 [[Get]] (P, Receiver) |
- *access_info = PropertyAccessInfo::NotFound( |
- Type::Class(receiver_map, zone()), holder); |
+ *access_info = |
+ PropertyAccessInfo::NotFound(MapList{receiver_map}, holder); |
return true; |
} else { |
return false; |
@@ -350,7 +382,6 @@ bool AccessInfoFactory::ComputePropertyAccessInfo( |
return false; |
} |
- |
bool AccessInfoFactory::ComputePropertyAccessInfos( |
MapHandleList const& maps, Handle<Name> name, AccessMode access_mode, |
ZoneVector<PropertyAccessInfo>* access_infos) { |
@@ -360,7 +391,15 @@ bool AccessInfoFactory::ComputePropertyAccessInfos( |
if (!ComputePropertyAccessInfo(map, name, access_mode, &access_info)) { |
return false; |
} |
- access_infos->push_back(access_info); |
+ // Try to merge the {access_info} with an existing one. |
+ bool merged = false; |
+ for (PropertyAccessInfo& other_info : *access_infos) { |
+ if (other_info.Merge(&access_info)) { |
+ merged = true; |
+ break; |
+ } |
+ } |
+ if (!merged) access_infos->push_back(access_info); |
} |
} |
return true; |
@@ -394,8 +433,8 @@ bool AccessInfoFactory::LookupSpecialFieldAccessor( |
field_type = type_cache_.kJSArrayLengthType; |
} |
} |
- *access_info = PropertyAccessInfo::DataField(Type::Class(map, zone()), |
- field_index, field_type); |
+ *access_info = |
+ PropertyAccessInfo::DataField(MapList{map}, field_index, field_type); |
return true; |
} |
return false; |
@@ -445,9 +484,8 @@ bool AccessInfoFactory::LookupTransition(Handle<Map> map, Handle<Name> name, |
DCHECK(field_type->Is(Type::TaggedPointer())); |
} |
dependencies()->AssumeMapNotDeprecated(transition_map); |
- *access_info = |
- PropertyAccessInfo::DataField(Type::Class(map, zone()), field_index, |
- field_type, holder, transition_map); |
+ *access_info = PropertyAccessInfo::DataField( |
+ MapList{map}, field_index, field_type, holder, transition_map); |
return true; |
} |
return false; |