summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/access-info.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/compiler/access-info.cc')
-rw-r--r--deps/v8/src/compiler/access-info.cc436
1 files changed, 230 insertions, 206 deletions
diff --git a/deps/v8/src/compiler/access-info.cc b/deps/v8/src/compiler/access-info.cc
index 4e67c35cdf..ac46eeb07b 100644
--- a/deps/v8/src/compiler/access-info.cc
+++ b/deps/v8/src/compiler/access-info.cc
@@ -24,21 +24,6 @@ namespace compiler {
namespace {
-bool CanInlineElementAccess(Handle<Map> map) {
- if (!map->IsJSObjectMap()) return false;
- if (map->is_access_check_needed()) return false;
- if (map->has_indexed_interceptor()) return false;
- ElementsKind const elements_kind = map->elements_kind();
- if (IsFastElementsKind(elements_kind)) return true;
- if (IsFixedTypedArrayElementsKind(elements_kind) &&
- elements_kind != BIGUINT64_ELEMENTS &&
- elements_kind != BIGINT64_ELEMENTS) {
- return true;
- }
- return false;
-}
-
-
bool CanInlinePropertyAccess(Handle<Map> map) {
// We can inline property access to prototypes of all primitives, except
// the special Oddball ones that have no wrapper counterparts (i.e. Null,
@@ -63,6 +48,8 @@ std::ostream& operator<<(std::ostream& os, AccessMode access_mode) {
return os << "Store";
case AccessMode::kStoreInLiteral:
return os << "StoreInLiteral";
+ case AccessMode::kHas:
+ return os << "Has";
}
UNREACHABLE();
}
@@ -71,7 +58,9 @@ ElementAccessInfo::ElementAccessInfo() = default;
ElementAccessInfo::ElementAccessInfo(MapHandles const& receiver_maps,
ElementsKind elements_kind)
- : elements_kind_(elements_kind), receiver_maps_(receiver_maps) {}
+ : elements_kind_(elements_kind), receiver_maps_(receiver_maps) {
+ CHECK(!receiver_maps.empty());
+}
// static
PropertyAccessInfo PropertyAccessInfo::NotFound(MapHandles const& receiver_maps,
@@ -175,6 +164,7 @@ bool PropertyAccessInfo::Merge(PropertyAccessInfo const* that,
if (this->field_index_.GetFieldAccessStubKey() ==
that->field_index_.GetFieldAccessStubKey()) {
switch (access_mode) {
+ case AccessMode::kHas:
case AccessMode::kLoad: {
if (this->field_representation_ != that->field_representation_) {
if (!IsAnyTagged(this->field_representation_) ||
@@ -249,19 +239,15 @@ Handle<Cell> PropertyAccessInfo::export_cell() const {
AccessInfoFactory::AccessInfoFactory(JSHeapBroker* broker,
CompilationDependencies* dependencies,
- Handle<Context> native_context, Zone* zone)
+ Zone* zone)
: broker_(broker),
dependencies_(dependencies),
- native_context_(native_context),
- isolate_(native_context->GetIsolate()),
type_cache_(TypeCache::Get()),
- zone_(zone) {
- DCHECK(native_context->IsNativeContext());
-}
-
+ zone_(zone) {}
bool AccessInfoFactory::ComputeElementAccessInfo(
- Handle<Map> map, AccessMode access_mode, ElementAccessInfo* access_info) {
+ Handle<Map> map, AccessMode access_mode,
+ ElementAccessInfo* access_info) const {
// Check if it is safe to inline element access for the {map}.
if (!CanInlineElementAccess(map)) return false;
ElementsKind const elements_kind = map->elements_kind();
@@ -270,54 +256,50 @@ bool AccessInfoFactory::ComputeElementAccessInfo(
}
bool AccessInfoFactory::ComputeElementAccessInfos(
- MapHandles const& maps, AccessMode access_mode,
- ZoneVector<ElementAccessInfo>* access_infos) {
- if (access_mode == AccessMode::kLoad) {
+ FeedbackNexus nexus, MapHandles const& maps, AccessMode access_mode,
+ ZoneVector<ElementAccessInfo>* access_infos) const {
+ ProcessedFeedback processed(broker()->zone());
+ ProcessFeedbackMapsForElementAccess(isolate(), maps, &processed);
+
+ if (FLAG_concurrent_inlining) {
+ if (broker()->HasFeedback(nexus)) {
+ // We have already processed the feedback for this nexus during
+ // serialization. Use that data instead of the data computed above.
+ ProcessedFeedback const& preprocessed =
+ broker()->GetOrCreateFeedback(nexus);
+ TRACE_BROKER(broker(),
+ "ComputeElementAccessInfos: using preprocessed feedback "
+ << "(slot " << nexus.slot() << " of "
+ << Brief(*nexus.vector_handle()) << "; "
+ << preprocessed.receiver_maps.size() << "/"
+ << preprocessed.transitions.size() << " vs "
+ << processed.receiver_maps.size() << "/"
+ << processed.transitions.size() << ").\n");
+ processed.receiver_maps = preprocessed.receiver_maps;
+ processed.transitions = preprocessed.transitions;
+ } else {
+ TRACE_BROKER(broker(),
+ "ComputeElementAccessInfos: missing preprocessed feedback "
+ << "(slot " << nexus.slot() << " of "
+ << Brief(*nexus.vector_handle()) << ").\n");
+ }
+ }
+
+ if (processed.receiver_maps.empty()) return false;
+
+ if (access_mode == AccessMode::kLoad || access_mode == AccessMode::kHas) {
// For polymorphic loads of similar elements kinds (i.e. all tagged or all
// double), always use the "worst case" code without a transition. This is
// much faster than transitioning the elements to the worst case, trading a
// TransitionElementsKind for a CheckMaps, avoiding mutation of the array.
ElementAccessInfo access_info;
- if (ConsolidateElementLoad(maps, &access_info)) {
+ if (ConsolidateElementLoad(processed, &access_info)) {
access_infos->push_back(access_info);
return true;
}
}
- // Collect possible transition targets.
- MapHandles possible_transition_targets;
- possible_transition_targets.reserve(maps.size());
- for (Handle<Map> map : maps) {
- if (Map::TryUpdate(isolate(), map).ToHandle(&map)) {
- if (CanInlineElementAccess(map) &&
- IsFastElementsKind(map->elements_kind()) &&
- GetInitialFastElementsKind() != map->elements_kind()) {
- possible_transition_targets.push_back(map);
- }
- }
- }
-
- // Separate the actual receiver maps and the possible transition sources.
- MapHandles receiver_maps;
- receiver_maps.reserve(maps.size());
- MapTransitionList transitions(maps.size());
- for (Handle<Map> map : maps) {
- if (Map::TryUpdate(isolate(), map).ToHandle(&map)) {
- // Don't generate elements kind transitions from stable maps.
- Map transition_target = map->is_stable()
- ? Map()
- : map->FindElementsKindTransitionedMap(
- isolate(), possible_transition_targets);
- if (transition_target.is_null()) {
- receiver_maps.push_back(map);
- } else {
- transitions.push_back(
- std::make_pair(map, handle(transition_target, isolate())));
- }
- }
- }
-
- for (Handle<Map> receiver_map : receiver_maps) {
+ for (Handle<Map> receiver_map : processed.receiver_maps) {
// Compute the element access information.
ElementAccessInfo access_info;
if (!ComputeElementAccessInfo(receiver_map, access_mode, &access_info)) {
@@ -325,9 +307,9 @@ bool AccessInfoFactory::ComputeElementAccessInfos(
}
// Collect the possible transitions for the {receiver_map}.
- for (auto transition : transitions) {
+ for (auto transition : processed.transitions) {
if (transition.second.is_identical_to(receiver_map)) {
- access_info.transitions().push_back(transition);
+ access_info.AddTransitionSource(transition.first);
}
}
@@ -337,24 +319,139 @@ bool AccessInfoFactory::ComputeElementAccessInfos(
return true;
}
+bool AccessInfoFactory::ComputeDataFieldAccessInfo(
+ Handle<Map> receiver_map, Handle<Map> map, MaybeHandle<JSObject> holder,
+ int number, AccessMode access_mode, PropertyAccessInfo* access_info) const {
+ DCHECK_NE(number, DescriptorArray::kNotFound);
+ Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate());
+ PropertyDetails const details = descriptors->GetDetails(number);
+ int index = descriptors->GetFieldIndex(number);
+ Representation details_representation = details.representation();
+ FieldIndex field_index =
+ FieldIndex::ForPropertyIndex(*map, index, details_representation);
+ Type field_type = Type::NonInternal();
+ MachineRepresentation field_representation = MachineRepresentation::kTagged;
+ MaybeHandle<Map> field_map;
+ if (details_representation.IsSmi()) {
+ field_type = Type::SignedSmall();
+ field_representation = MachineRepresentation::kTaggedSigned;
+ } else if (details_representation.IsDouble()) {
+ field_type = type_cache_->kFloat64;
+ field_representation = MachineRepresentation::kFloat64;
+ } else if (details_representation.IsHeapObject()) {
+ // Extract the field type from the property details (make sure its
+ // representation is TaggedPointer to reflect the heap object case).
+ field_representation = MachineRepresentation::kTaggedPointer;
+ Handle<FieldType> descriptors_field_type(descriptors->GetFieldType(number),
+ isolate());
+ if (descriptors_field_type->IsNone()) {
+ // Store is not safe if the field type was cleared.
+ if (access_mode == AccessMode::kStore) return false;
+
+ // The field type was cleared by the GC, so we don't know anything
+ // about the contents now.
+ } else if (descriptors_field_type->IsClass()) {
+ MapRef map_ref(broker(), map);
+ map_ref.SerializeOwnDescriptors(); // TODO(neis): Remove later.
+ dependencies()->DependOnFieldType(map_ref, number);
+ // Remember the field map, and try to infer a useful type.
+ Handle<Map> map(descriptors_field_type->AsClass(), isolate());
+ field_type = Type::For(MapRef(broker(), map));
+ field_map = MaybeHandle<Map>(map);
+ }
+ }
+ *access_info = PropertyAccessInfo::DataField(
+ details.constness(), MapHandles{receiver_map}, field_index,
+ field_representation, field_type, field_map, holder);
+ return true;
+}
+
+bool AccessInfoFactory::ComputeAccessorDescriptorAccessInfo(
+ Handle<Map> receiver_map, Handle<Name> name, Handle<Map> map,
+ MaybeHandle<JSObject> holder, int number, AccessMode access_mode,
+ PropertyAccessInfo* access_info) const {
+ DCHECK_NE(number, DescriptorArray::kNotFound);
+ Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate());
+ SLOW_DCHECK(number == descriptors->Search(*name, *map));
+ if (map->instance_type() == JS_MODULE_NAMESPACE_TYPE) {
+ DCHECK(map->is_prototype_map());
+ Handle<PrototypeInfo> proto_info(PrototypeInfo::cast(map->prototype_info()),
+ isolate());
+ Handle<JSModuleNamespace> module_namespace(
+ JSModuleNamespace::cast(proto_info->module_namespace()), isolate());
+ Handle<Cell> cell(
+ Cell::cast(module_namespace->module()->exports()->Lookup(
+ ReadOnlyRoots(isolate()), name, Smi::ToInt(name->GetHash()))),
+ isolate());
+ if (cell->value()->IsTheHole(isolate())) {
+ // This module has not been fully initialized yet.
+ return false;
+ }
+ *access_info =
+ PropertyAccessInfo::ModuleExport(MapHandles{receiver_map}, cell);
+ return true;
+ }
+ if (access_mode == AccessMode::kHas) {
+ // HasProperty checks don't call getter/setters, existence is sufficient.
+ *access_info = PropertyAccessInfo::AccessorConstant(
+ MapHandles{receiver_map}, Handle<Object>(), holder);
+ return true;
+ }
+ Handle<Object> accessors(descriptors->GetStrongValue(number), isolate());
+ if (!accessors->IsAccessorPair()) return false;
+ Handle<Object> accessor(access_mode == AccessMode::kLoad
+ ? Handle<AccessorPair>::cast(accessors)->getter()
+ : Handle<AccessorPair>::cast(accessors)->setter(),
+ isolate());
+ if (!accessor->IsJSFunction()) {
+ CallOptimization optimization(isolate(), accessor);
+ if (!optimization.is_simple_api_call()) return false;
+ if (optimization.IsCrossContextLazyAccessorPair(
+ *broker()->native_context().object(), *map)) {
+ return false;
+ }
+
+ CallOptimization::HolderLookup lookup;
+ holder = optimization.LookupHolderOfExpectedType(receiver_map, &lookup);
+ if (lookup == CallOptimization::kHolderNotFound) return false;
+ DCHECK_IMPLIES(lookup == CallOptimization::kHolderIsReceiver,
+ holder.is_null());
+ DCHECK_IMPLIES(lookup == CallOptimization::kHolderFound, !holder.is_null());
+ if (V8_UNLIKELY(FLAG_runtime_stats)) return false;
+ }
+ if (access_mode == AccessMode::kLoad) {
+ Handle<Name> cached_property_name;
+ if (FunctionTemplateInfo::TryGetCachedPropertyName(isolate(), accessor)
+ .ToHandle(&cached_property_name)) {
+ if (ComputePropertyAccessInfo(map, cached_property_name, access_mode,
+ access_info)) {
+ return true;
+ }
+ }
+ }
+ *access_info = PropertyAccessInfo::AccessorConstant(MapHandles{receiver_map},
+ accessor, holder);
+ return true;
+}
bool AccessInfoFactory::ComputePropertyAccessInfo(
Handle<Map> map, Handle<Name> name, AccessMode access_mode,
- PropertyAccessInfo* access_info) {
+ PropertyAccessInfo* access_info) const {
CHECK(name->IsUniqueName());
+ if (access_mode == AccessMode::kHas && !map->IsJSReceiverMap()) return false;
+
// Check if it is safe to inline property access for the {map}.
if (!CanInlinePropertyAccess(map)) return false;
- // Compute the receiver type.
- Handle<Map> receiver_map = map;
-
// We support fast inline cases for certain JSObject getters.
- if (access_mode == AccessMode::kLoad &&
+ if ((access_mode == AccessMode::kLoad || access_mode == AccessMode::kHas) &&
LookupSpecialFieldAccessor(map, name, access_info)) {
return true;
}
+ // Remember the receiver map. We use {map} as loop variable.
+ Handle<Map> receiver_map = map;
MaybeHandle<JSObject> holder;
do {
// Lookup the named property on the {map}.
@@ -368,62 +465,23 @@ bool AccessInfoFactory::ComputePropertyAccessInfo(
if (details.IsReadOnly()) {
return false;
}
- // Check for store to data property on a prototype.
if (details.kind() == kData && !holder.is_null()) {
- // Store to property not found on the receiver but on a prototype, we
- // need to transition to a new data property.
- // Implemented according to ES6 section 9.1.9 [[Set]] (P, V, Receiver)
+ // This is a store to a property not found on the receiver but on a
+ // prototype. According to ES6 section 9.1.9 [[Set]], we need to
+ // create a new data property on the receiver. We can still optimize
+ // if such a transition already exists.
return LookupTransition(receiver_map, name, holder, access_info);
}
}
if (details.location() == kField) {
if (details.kind() == kData) {
- int index = descriptors->GetFieldIndex(number);
- Representation details_representation = details.representation();
- FieldIndex field_index =
- FieldIndex::ForPropertyIndex(*map, index, details_representation);
- Type field_type = Type::NonInternal();
- MachineRepresentation field_representation =
- MachineRepresentation::kTagged;
- MaybeHandle<Map> field_map;
- if (details_representation.IsSmi()) {
- field_type = Type::SignedSmall();
- field_representation = MachineRepresentation::kTaggedSigned;
- } else if (details_representation.IsDouble()) {
- field_type = type_cache_->kFloat64;
- field_representation = MachineRepresentation::kFloat64;
- } else if (details_representation.IsHeapObject()) {
- // Extract the field type from the property details (make sure its
- // representation is TaggedPointer to reflect the heap object case).
- field_representation = MachineRepresentation::kTaggedPointer;
- Handle<FieldType> descriptors_field_type(
- descriptors->GetFieldType(number), isolate());
- if (descriptors_field_type->IsNone()) {
- // Store is not safe if the field type was cleared.
- if (access_mode == AccessMode::kStore) return false;
-
- // The field type was cleared by the GC, so we don't know anything
- // about the contents now.
- } else if (descriptors_field_type->IsClass()) {
- MapRef map_ref(broker(), map);
- map_ref.SerializeOwnDescriptors(); // TODO(neis): Remove later.
- dependencies()->DependOnFieldType(map_ref, number);
- // Remember the field map, and try to infer a useful type.
- Handle<Map> map(descriptors_field_type->AsClass(), isolate());
- field_type = Type::For(MapRef(broker(), map));
- field_map = MaybeHandle<Map>(map);
- }
- }
- *access_info = PropertyAccessInfo::DataField(
- details.constness(), MapHandles{receiver_map}, field_index,
- field_representation, field_type, field_map, holder);
- return true;
+ return ComputeDataFieldAccessInfo(receiver_map, map, holder, number,
+ access_mode, access_info);
} else {
DCHECK_EQ(kAccessor, details.kind());
// TODO(turbofan): Add support for general accessors?
return false;
}
-
} else {
DCHECK_EQ(kDescriptor, details.location());
if (details.kind() == kData) {
@@ -434,71 +492,16 @@ bool AccessInfoFactory::ComputePropertyAccessInfo(
return true;
} else {
DCHECK_EQ(kAccessor, details.kind());
- if (map->instance_type() == JS_MODULE_NAMESPACE_TYPE) {
- DCHECK(map->is_prototype_map());
- Handle<PrototypeInfo> proto_info(
- PrototypeInfo::cast(map->prototype_info()), isolate());
- Handle<JSModuleNamespace> module_namespace(
- JSModuleNamespace::cast(proto_info->module_namespace()),
- isolate());
- Handle<Cell> cell(
- Cell::cast(module_namespace->module()->exports()->Lookup(
- ReadOnlyRoots(isolate()), name,
- Smi::ToInt(name->GetHash()))),
- isolate());
- if (cell->value()->IsTheHole(isolate())) {
- // This module has not been fully initialized yet.
- return false;
- }
- *access_info = PropertyAccessInfo::ModuleExport(
- MapHandles{receiver_map}, cell);
- return true;
- }
- Handle<Object> accessors(descriptors->GetStrongValue(number),
- isolate());
- if (!accessors->IsAccessorPair()) return false;
- Handle<Object> accessor(
- access_mode == AccessMode::kLoad
- ? Handle<AccessorPair>::cast(accessors)->getter()
- : Handle<AccessorPair>::cast(accessors)->setter(),
- isolate());
- if (!accessor->IsJSFunction()) {
- CallOptimization optimization(isolate(), accessor);
- if (!optimization.is_simple_api_call()) return false;
- if (optimization.IsCrossContextLazyAccessorPair(*native_context_,
- *map)) {
- return false;
- }
-
- CallOptimization::HolderLookup lookup;
- holder =
- optimization.LookupHolderOfExpectedType(receiver_map, &lookup);
- if (lookup == CallOptimization::kHolderNotFound) return false;
- DCHECK_IMPLIES(lookup == CallOptimization::kHolderIsReceiver,
- holder.is_null());
- DCHECK_IMPLIES(lookup == CallOptimization::kHolderFound,
- !holder.is_null());
- if (V8_UNLIKELY(FLAG_runtime_stats)) return false;
- }
- if (access_mode == AccessMode::kLoad) {
- Handle<Name> cached_property_name;
- if (FunctionTemplateInfo::TryGetCachedPropertyName(isolate(),
- accessor)
- .ToHandle(&cached_property_name)) {
- if (ComputePropertyAccessInfo(map, cached_property_name,
- access_mode, access_info)) {
- return true;
- }
- }
- }
- *access_info = PropertyAccessInfo::AccessorConstant(
- MapHandles{receiver_map}, accessor, holder);
- return true;
+ return ComputeAccessorDescriptorAccessInfo(receiver_map, name, map,
+ holder, number,
+ access_mode, access_info);
}
}
UNREACHABLE();
}
+ // The property wasn't found on {map}. Look on the prototype if appropriate.
+
// Don't search on the prototype chain for special indices in case of
// integer indexed exotic objects (see ES6 section 9.4.5).
if (map->IsJSTypedArrayMap() && name->IsString() &&
@@ -506,7 +509,7 @@ bool AccessInfoFactory::ComputePropertyAccessInfo(
return false;
}
- // Don't search on the prototype when storing in literals
+ // Don't search on the prototype when storing in literals.
if (access_mode == AccessMode::kStoreInLiteral) {
return LookupTransition(receiver_map, name, holder, access_info);
}
@@ -519,7 +522,7 @@ bool AccessInfoFactory::ComputePropertyAccessInfo(
// Perform the implicit ToObject for primitives here.
// Implemented according to ES6 section 7.3.2 GetV (V, P).
Handle<JSFunction> constructor;
- if (Map::GetConstructorFunction(map, native_context())
+ if (Map::GetConstructorFunction(map, broker()->native_context().object())
.ToHandle(&constructor)) {
map = handle(constructor->initial_map(), isolate());
DCHECK(map->prototype()->IsJSObject());
@@ -554,7 +557,7 @@ bool AccessInfoFactory::ComputePropertyAccessInfo(
bool AccessInfoFactory::ComputePropertyAccessInfo(
MapHandles const& maps, Handle<Name> name, AccessMode access_mode,
- PropertyAccessInfo* access_info) {
+ PropertyAccessInfo* access_info) const {
ZoneVector<PropertyAccessInfo> access_infos(zone());
if (ComputePropertyAccessInfos(maps, name, access_mode, &access_infos) &&
access_infos.size() == 1) {
@@ -566,23 +569,27 @@ bool AccessInfoFactory::ComputePropertyAccessInfo(
bool AccessInfoFactory::ComputePropertyAccessInfos(
MapHandles const& maps, Handle<Name> name, AccessMode access_mode,
- ZoneVector<PropertyAccessInfo>* access_infos) {
+ ZoneVector<PropertyAccessInfo>* access_infos) const {
+ ZoneVector<PropertyAccessInfo> infos(zone());
+ infos.reserve(maps.size());
for (Handle<Map> map : maps) {
- if (Map::TryUpdate(isolate(), map).ToHandle(&map)) {
- PropertyAccessInfo access_info;
- if (!ComputePropertyAccessInfo(map, name, access_mode, &access_info)) {
- return false;
- }
- // 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, access_mode, zone())) {
- merged = true;
- break;
- }
+ PropertyAccessInfo access_info;
+ if (!ComputePropertyAccessInfo(map, name, access_mode, &access_info)) {
+ return false;
+ }
+ infos.push_back(access_info);
+ }
+
+ // Merge as many as possible and push into {access_infos}.
+ for (auto it = infos.begin(), end = infos.end(); it != end; ++it) {
+ bool merged = false;
+ for (auto ot = it + 1; ot != end; ++ot) {
+ if (ot->Merge(&(*it), access_mode, zone())) {
+ merged = true;
+ break;
}
- if (!merged) access_infos->push_back(access_info);
}
+ if (!merged) access_infos->push_back(*it);
}
return true;
}
@@ -610,12 +617,16 @@ Maybe<ElementsKind> GeneralizeElementsKind(ElementsKind this_kind,
} // namespace
-bool AccessInfoFactory::ConsolidateElementLoad(MapHandles const& maps,
- ElementAccessInfo* access_info) {
- if (maps.empty()) return false;
- InstanceType instance_type = maps.front()->instance_type();
- ElementsKind elements_kind = maps.front()->elements_kind();
- for (Handle<Map> map : maps) {
+bool AccessInfoFactory::ConsolidateElementLoad(
+ ProcessedFeedback const& processed, ElementAccessInfo* access_info) const {
+ CHECK(!processed.receiver_maps.empty());
+
+ // We want to look at each map but the maps are split across
+ // {processed.receiver_maps} and {processed.transitions}.
+
+ InstanceType instance_type = processed.receiver_maps.front()->instance_type();
+ ElementsKind elements_kind = processed.receiver_maps.front()->elements_kind();
+ auto processMap = [&](Handle<Map> map) {
if (!CanInlineElementAccess(map) || map->instance_type() != instance_type) {
return false;
}
@@ -623,16 +634,31 @@ bool AccessInfoFactory::ConsolidateElementLoad(MapHandles const& maps,
.To(&elements_kind)) {
return false;
}
+ return true;
+ };
+
+ for (Handle<Map> map : processed.receiver_maps) {
+ if (!processMap(map)) return false;
+ }
+
+ MapHandles maps(processed.receiver_maps.begin(),
+ processed.receiver_maps.end());
+ for (auto& pair : processed.transitions) {
+ if (!processMap(pair.first) || !processMap(pair.second)) return false;
+ maps.push_back(pair.first);
+ maps.push_back(pair.second);
}
+ // {maps} may now contain duplicate entries, but that shouldn't matter.
+
*access_info = ElementAccessInfo(maps, elements_kind);
return true;
}
bool AccessInfoFactory::LookupSpecialFieldAccessor(
- Handle<Map> map, Handle<Name> name, PropertyAccessInfo* access_info) {
+ Handle<Map> map, Handle<Name> name, PropertyAccessInfo* access_info) const {
// Check for String::length field accessor.
if (map->IsStringMap()) {
- if (Name::Equals(isolate(), name, factory()->length_string())) {
+ if (Name::Equals(isolate(), name, isolate()->factory()->length_string())) {
*access_info = PropertyAccessInfo::StringLength(MapHandles{map});
return true;
}
@@ -644,7 +670,8 @@ bool AccessInfoFactory::LookupSpecialFieldAccessor(
Type field_type = Type::NonInternal();
MachineRepresentation field_representation = MachineRepresentation::kTagged;
if (map->IsJSArrayMap()) {
- DCHECK(Name::Equals(isolate(), factory()->length_string(), name));
+ DCHECK(
+ Name::Equals(isolate(), isolate()->factory()->length_string(), name));
// The JSArray::length property is a smi in the range
// [0, FixedDoubleArray::kMaxLength] in case of fast double
// elements, a smi in the range [0, FixedArray::kMaxLength]
@@ -669,10 +696,9 @@ bool AccessInfoFactory::LookupSpecialFieldAccessor(
return false;
}
-
-bool AccessInfoFactory::LookupTransition(Handle<Map> map, Handle<Name> name,
- MaybeHandle<JSObject> holder,
- PropertyAccessInfo* access_info) {
+bool AccessInfoFactory::LookupTransition(
+ Handle<Map> map, Handle<Name> name, MaybeHandle<JSObject> holder,
+ PropertyAccessInfo* access_info) const {
// Check if the {map} has a data transition with the given {name}.
Map transition =
TransitionsAccessor(isolate(), map).SearchTransition(*name, kData, NONE);
@@ -729,8 +755,6 @@ bool AccessInfoFactory::LookupTransition(Handle<Map> map, Handle<Name> name,
}
-Factory* AccessInfoFactory::factory() const { return isolate()->factory(); }
-
} // namespace compiler
} // namespace internal
} // namespace v8