diff options
Diffstat (limited to 'deps/v8/src/compiler/access-info.cc')
-rw-r--r-- | deps/v8/src/compiler/access-info.cc | 436 |
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 |