Commit eea2cc65 authored by Jakob Gruber's avatar Jakob Gruber Committed by V8 LUCI CQ

[compiler] Refactor PropertyAccessInfo to contain refs

.. instead of handles and update all uses. Likewise with
ElementAccessInfo. Essentially, this creates the needed refs up-front
and removes useless MakeRef calls from PAI users.

Bug: v8:7790, v8:11671
Change-Id: I175e77dcca27760101606587de615e3497e68c68
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3030701
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarMichael Stanton <mvstanton@chromium.org>
Cr-Commit-Position: refs/heads/master@{#75805}
parent d430856d
This diff is collapsed.
...@@ -37,26 +37,26 @@ std::ostream& operator<<(std::ostream&, AccessMode); ...@@ -37,26 +37,26 @@ std::ostream& operator<<(std::ostream&, AccessMode);
// This class encapsulates all information required to access a certain element. // This class encapsulates all information required to access a certain element.
class ElementAccessInfo final { class ElementAccessInfo final {
public: public:
ElementAccessInfo(ZoneVector<Handle<Map>>&& lookup_start_object_maps, ElementAccessInfo(ZoneVector<MapRef>&& lookup_start_object_maps,
ElementsKind elements_kind, Zone* zone); ElementsKind elements_kind, Zone* zone);
ElementsKind elements_kind() const { return elements_kind_; } ElementsKind elements_kind() const { return elements_kind_; }
ZoneVector<Handle<Map>> const& lookup_start_object_maps() const { ZoneVector<MapRef> const& lookup_start_object_maps() const {
return lookup_start_object_maps_; return lookup_start_object_maps_;
} }
ZoneVector<Handle<Map>> const& transition_sources() const { ZoneVector<MapRef> const& transition_sources() const {
return transition_sources_; return transition_sources_;
} }
void AddTransitionSource(Handle<Map> map) { void AddTransitionSource(MapRef map) {
CHECK_EQ(lookup_start_object_maps_.size(), 1); CHECK_EQ(lookup_start_object_maps_.size(), 1);
transition_sources_.push_back(map); transition_sources_.push_back(map);
} }
private: private:
ElementsKind elements_kind_; ElementsKind elements_kind_;
ZoneVector<Handle<Map>> lookup_start_object_maps_; ZoneVector<MapRef> lookup_start_object_maps_;
ZoneVector<Handle<Map>> transition_sources_; ZoneVector<MapRef> transition_sources_;
}; };
// This class encapsulates all information required to access a certain // This class encapsulates all information required to access a certain
...@@ -75,37 +75,35 @@ class PropertyAccessInfo final { ...@@ -75,37 +75,35 @@ class PropertyAccessInfo final {
kStringLength kStringLength
}; };
static PropertyAccessInfo NotFound(Zone* zone, Handle<Map> receiver_map, static PropertyAccessInfo NotFound(Zone* zone, MapRef receiver_map,
MaybeHandle<JSObject> holder); base::Optional<JSObjectRef> holder);
static PropertyAccessInfo DataField( static PropertyAccessInfo DataField(
Zone* zone, Handle<Map> receiver_map, Zone* zone, MapRef receiver_map,
ZoneVector<CompilationDependency const*>&& unrecorded_dependencies, ZoneVector<CompilationDependency const*>&& unrecorded_dependencies,
FieldIndex field_index, Representation field_representation, FieldIndex field_index, Representation field_representation,
Type field_type, Handle<Map> field_owner_map, Type field_type, MapRef field_owner_map, base::Optional<MapRef> field_map,
MaybeHandle<Map> field_map = MaybeHandle<Map>(), base::Optional<JSObjectRef> holder,
MaybeHandle<JSObject> holder = MaybeHandle<JSObject>(), base::Optional<MapRef> transition_map);
MaybeHandle<Map> transition_map = MaybeHandle<Map>());
static PropertyAccessInfo FastDataConstant( static PropertyAccessInfo FastDataConstant(
Zone* zone, Handle<Map> receiver_map, Zone* zone, MapRef receiver_map,
ZoneVector<CompilationDependency const*>&& unrecorded_dependencies, ZoneVector<CompilationDependency const*>&& unrecorded_dependencies,
FieldIndex field_index, Representation field_representation, FieldIndex field_index, Representation field_representation,
Type field_type, Handle<Map> field_owner_map, MaybeHandle<Map> field_map, Type field_type, MapRef field_owner_map, base::Optional<MapRef> field_map,
MaybeHandle<JSObject> holder, base::Optional<JSObjectRef> holder,
MaybeHandle<Map> transition_map = MaybeHandle<Map>()); base::Optional<MapRef> transition_map);
static PropertyAccessInfo FastAccessorConstant(Zone* zone, static PropertyAccessInfo FastAccessorConstant(
Handle<Map> receiver_map, Zone* zone, MapRef receiver_map, base::Optional<ObjectRef> constant,
Handle<Object> constant, base::Optional<JSObjectRef> holder);
MaybeHandle<JSObject> holder); static PropertyAccessInfo ModuleExport(Zone* zone, MapRef receiver_map,
static PropertyAccessInfo ModuleExport(Zone* zone, Handle<Map> receiver_map, CellRef cell);
Handle<Cell> cell); static PropertyAccessInfo StringLength(Zone* zone, MapRef receiver_map);
static PropertyAccessInfo StringLength(Zone* zone, Handle<Map> receiver_map);
static PropertyAccessInfo Invalid(Zone* zone); static PropertyAccessInfo Invalid(Zone* zone);
static PropertyAccessInfo DictionaryProtoDataConstant( static PropertyAccessInfo DictionaryProtoDataConstant(
Zone* zone, Handle<Map> receiver_map, Handle<JSObject> holder, Zone* zone, MapRef receiver_map, JSObjectRef holder,
InternalIndex dict_index, Handle<Name> name); InternalIndex dict_index, NameRef name);
static PropertyAccessInfo DictionaryProtoAccessorConstant( static PropertyAccessInfo DictionaryProtoAccessorConstant(
Zone* zone, Handle<Map> receiver_map, MaybeHandle<JSObject> holder, Zone* zone, MapRef receiver_map, base::Optional<JSObjectRef> holder,
Handle<Object> constant, Handle<Name> name); ObjectRef constant, NameRef name);
bool Merge(PropertyAccessInfo const* that, AccessMode access_mode, bool Merge(PropertyAccessInfo const* that, AccessMode access_mode,
Zone* zone) V8_WARN_UNUSED_RESULT; Zone* zone) V8_WARN_UNUSED_RESULT;
...@@ -128,7 +126,7 @@ class PropertyAccessInfo final { ...@@ -128,7 +126,7 @@ class PropertyAccessInfo final {
return kind() == kDictionaryProtoAccessorConstant; return kind() == kDictionaryProtoAccessorConstant;
} }
bool HasTransitionMap() const { return !transition_map().is_null(); } bool HasTransitionMap() const { return transition_map().has_value(); }
bool HasDictionaryHolder() const { bool HasDictionaryHolder() const {
return kind_ == kDictionaryProtoDataConstant || return kind_ == kDictionaryProtoDataConstant ||
kind_ == kDictionaryProtoAccessorConstant; kind_ == kDictionaryProtoAccessorConstant;
...@@ -136,17 +134,17 @@ class PropertyAccessInfo final { ...@@ -136,17 +134,17 @@ class PropertyAccessInfo final {
ConstFieldInfo GetConstFieldInfo() const; ConstFieldInfo GetConstFieldInfo() const;
Kind kind() const { return kind_; } Kind kind() const { return kind_; }
MaybeHandle<JSObject> holder() const { base::Optional<JSObjectRef> holder() const {
// TODO(neis): There was a CHECK here that tries to protect against // TODO(neis): There was a CHECK here that tries to protect against
// using the access info without recording its dependencies first. // using the access info without recording its dependencies first.
// Find a more suitable place for it. // Find a more suitable place for it.
return holder_; return holder_;
} }
MaybeHandle<Map> transition_map() const { base::Optional<MapRef> transition_map() const {
DCHECK(!HasDictionaryHolder()); DCHECK(!HasDictionaryHolder());
return transition_map_; return transition_map_;
} }
Handle<Object> constant() const { return constant_; } base::Optional<ObjectRef> constant() const { return constant_; }
FieldIndex field_index() const { FieldIndex field_index() const {
DCHECK(!HasDictionaryHolder()); DCHECK(!HasDictionaryHolder());
return field_index_; return field_index_;
...@@ -160,11 +158,11 @@ class PropertyAccessInfo final { ...@@ -160,11 +158,11 @@ class PropertyAccessInfo final {
DCHECK(!HasDictionaryHolder()); DCHECK(!HasDictionaryHolder());
return field_representation_; return field_representation_;
} }
MaybeHandle<Map> field_map() const { base::Optional<MapRef> field_map() const {
DCHECK(!HasDictionaryHolder()); DCHECK(!HasDictionaryHolder());
return field_map_; return field_map_;
} }
ZoneVector<Handle<Map>> const& lookup_start_object_maps() const { ZoneVector<MapRef> const& lookup_start_object_maps() const {
return lookup_start_object_maps_; return lookup_start_object_maps_;
} }
...@@ -173,46 +171,48 @@ class PropertyAccessInfo final { ...@@ -173,46 +171,48 @@ class PropertyAccessInfo final {
return dictionary_index_; return dictionary_index_;
} }
Handle<Name> name() const { NameRef name() const {
DCHECK(HasDictionaryHolder()); DCHECK(HasDictionaryHolder());
return name_.ToHandleChecked(); return name_.value();
} }
private: private:
explicit PropertyAccessInfo(Zone* zone); explicit PropertyAccessInfo(Zone* zone);
PropertyAccessInfo(Zone* zone, Kind kind, MaybeHandle<JSObject> holder, PropertyAccessInfo(Zone* zone, Kind kind, base::Optional<JSObjectRef> holder,
ZoneVector<Handle<Map>>&& lookup_start_object_maps); ZoneVector<MapRef>&& lookup_start_object_maps);
PropertyAccessInfo(Zone* zone, Kind kind, MaybeHandle<JSObject> holder, PropertyAccessInfo(Zone* zone, Kind kind, base::Optional<JSObjectRef> holder,
Handle<Object> constant, MaybeHandle<Name> name, base::Optional<ObjectRef> constant,
ZoneVector<Handle<Map>>&& lookup_start_object_maps); base::Optional<NameRef> name,
PropertyAccessInfo(Kind kind, MaybeHandle<JSObject> holder, ZoneVector<MapRef>&& lookup_start_object_maps);
MaybeHandle<Map> transition_map, FieldIndex field_index, PropertyAccessInfo(Kind kind, base::Optional<JSObjectRef> holder,
base::Optional<MapRef> transition_map,
FieldIndex field_index,
Representation field_representation, Type field_type, Representation field_representation, Type field_type,
Handle<Map> field_owner_map, MaybeHandle<Map> field_map, MapRef field_owner_map, base::Optional<MapRef> field_map,
ZoneVector<Handle<Map>>&& lookup_start_object_maps, ZoneVector<MapRef>&& lookup_start_object_maps,
ZoneVector<CompilationDependency const*>&& dependencies); ZoneVector<CompilationDependency const*>&& dependencies);
PropertyAccessInfo(Zone* zone, Kind kind, MaybeHandle<JSObject> holder, PropertyAccessInfo(Zone* zone, Kind kind, base::Optional<JSObjectRef> holder,
ZoneVector<Handle<Map>>&& lookup_start_object_maps, ZoneVector<MapRef>&& lookup_start_object_maps,
InternalIndex dictionary_index, Handle<Name> name); InternalIndex dictionary_index, NameRef name);
// Members used for fast and dictionary mode holders: // Members used for fast and dictionary mode holders:
Kind kind_; Kind kind_;
ZoneVector<Handle<Map>> lookup_start_object_maps_; ZoneVector<MapRef> lookup_start_object_maps_;
Handle<Object> constant_; base::Optional<ObjectRef> constant_;
MaybeHandle<JSObject> holder_; base::Optional<JSObjectRef> holder_;
// Members only used for fast mode holders: // Members only used for fast mode holders:
ZoneVector<CompilationDependency const*> unrecorded_dependencies_; ZoneVector<CompilationDependency const*> unrecorded_dependencies_;
MaybeHandle<Map> transition_map_; base::Optional<MapRef> transition_map_;
FieldIndex field_index_; FieldIndex field_index_;
Representation field_representation_; Representation field_representation_;
Type field_type_; Type field_type_;
MaybeHandle<Map> field_owner_map_; base::Optional<MapRef> field_owner_map_;
MaybeHandle<Map> field_map_; base::Optional<MapRef> field_map_;
// Members only used for dictionary mode holders: // Members only used for dictionary mode holders:
InternalIndex dictionary_index_; InternalIndex dictionary_index_;
MaybeHandle<Name> name_; base::Optional<NameRef> name_;
}; };
// This class encapsulates information required to generate load properties // This class encapsulates information required to generate load properties
......
...@@ -881,12 +881,10 @@ void DependOnStablePrototypeChain(CompilationDependencies* deps, MapRef map, ...@@ -881,12 +881,10 @@ void DependOnStablePrototypeChain(CompilationDependencies* deps, MapRef map,
} }
} // namespace } // namespace
template <class MapContainer>
void CompilationDependencies::DependOnStablePrototypeChains( void CompilationDependencies::DependOnStablePrototypeChains(
MapContainer const& receiver_maps, WhereToStart start, ZoneVector<MapRef> const& receiver_maps, WhereToStart start,
base::Optional<JSObjectRef> last_prototype) { base::Optional<JSObjectRef> last_prototype) {
for (auto map : receiver_maps) { for (MapRef receiver_map : receiver_maps) {
MapRef receiver_map = MakeRef(broker_, map);
if (start == kStartAtReceiver) DependOnStableMap(receiver_map); if (start == kStartAtReceiver) DependOnStableMap(receiver_map);
if (receiver_map.IsPrimitiveMap()) { if (receiver_map.IsPrimitiveMap()) {
// Perform the implicit ToObject for primitives here. // Perform the implicit ToObject for primitives here.
...@@ -900,12 +898,6 @@ void CompilationDependencies::DependOnStablePrototypeChains( ...@@ -900,12 +898,6 @@ void CompilationDependencies::DependOnStablePrototypeChains(
DependOnStablePrototypeChain(this, receiver_map, last_prototype); DependOnStablePrototypeChain(this, receiver_map, last_prototype);
} }
} }
template void CompilationDependencies::DependOnStablePrototypeChains(
ZoneVector<Handle<Map>> const& receiver_maps, WhereToStart start,
base::Optional<JSObjectRef> last_prototype);
template void CompilationDependencies::DependOnStablePrototypeChains(
ZoneHandleSet<Map> const& receiver_maps, WhereToStart start,
base::Optional<JSObjectRef> last_prototype);
void CompilationDependencies::DependOnElementsKinds( void CompilationDependencies::DependOnElementsKinds(
const AllocationSiteRef& site) { const AllocationSiteRef& site) {
......
...@@ -116,9 +116,8 @@ class V8_EXPORT_PRIVATE CompilationDependencies : public ZoneObject { ...@@ -116,9 +116,8 @@ class V8_EXPORT_PRIVATE CompilationDependencies : public ZoneObject {
// For each given map, depend on the stability of (the maps of) all prototypes // For each given map, depend on the stability of (the maps of) all prototypes
// up to (and including) the {last_prototype}. // up to (and including) the {last_prototype}.
template <class MapContainer>
void DependOnStablePrototypeChains( void DependOnStablePrototypeChains(
MapContainer const& receiver_maps, WhereToStart start, ZoneVector<MapRef> const& receiver_maps, WhereToStart start,
base::Optional<JSObjectRef> last_prototype = base::Optional<JSObjectRef> last_prototype =
base::Optional<JSObjectRef>()); base::Optional<JSObjectRef>());
......
...@@ -8002,14 +8002,12 @@ Reduction JSCallReducer::ReduceRegExpPrototypeTest(Node* node) { ...@@ -8002,14 +8002,12 @@ Reduction JSCallReducer::ReduceRegExpPrototypeTest(Node* node) {
// If "exec" has been modified on {regexp}, we can't do anything. // If "exec" has been modified on {regexp}, we can't do anything.
if (ai_exec.IsFastDataConstant()) { if (ai_exec.IsFastDataConstant()) {
Handle<JSObject> holder; base::Optional<JSObjectRef> holder = ai_exec.holder();
// Do not reduce if the exec method is not on the prototype chain. // Do not reduce if the exec method is not on the prototype chain.
if (!ai_exec.holder().ToHandle(&holder)) return inference.NoChange(); if (!holder.has_value()) return inference.NoChange();
JSObjectRef holder_ref = MakeRef(broker(), holder);
// Bail out if the exec method is not the original one. // Bail out if the exec method is not the original one.
base::Optional<ObjectRef> constant = holder_ref.GetOwnFastDataProperty( base::Optional<ObjectRef> constant = holder->GetOwnFastDataProperty(
ai_exec.field_representation(), ai_exec.field_index(), dependencies()); ai_exec.field_representation(), ai_exec.field_index(), dependencies());
if (!constant.has_value() || if (!constant.has_value() ||
!constant->equals(native_context().regexp_exec_function())) { !constant->equals(native_context().regexp_exec_function())) {
...@@ -8018,8 +8016,7 @@ Reduction JSCallReducer::ReduceRegExpPrototypeTest(Node* node) { ...@@ -8018,8 +8016,7 @@ Reduction JSCallReducer::ReduceRegExpPrototypeTest(Node* node) {
// Add proper dependencies on the {regexp}s [[Prototype]]s. // Add proper dependencies on the {regexp}s [[Prototype]]s.
dependencies()->DependOnStablePrototypeChains( dependencies()->DependOnStablePrototypeChains(
ai_exec.lookup_start_object_maps(), kStartAtPrototype, ai_exec.lookup_start_object_maps(), kStartAtPrototype, holder.value());
MakeRef(broker(), holder));
} else { } else {
// TODO(v8:11457) Support dictionary mode protoypes here. // TODO(v8:11457) Support dictionary mode protoypes here.
return inference.NoChange(); return inference.NoChange();
......
...@@ -210,7 +210,7 @@ class V8_EXPORT_PRIVATE JSNativeContextSpecialization final ...@@ -210,7 +210,7 @@ class V8_EXPORT_PRIVATE JSNativeContextSpecialization final
// Checks if we can turn the hole into undefined when loading an element // Checks if we can turn the hole into undefined when loading an element
// from an object with one of the {receiver_maps}; sets up appropriate // from an object with one of the {receiver_maps}; sets up appropriate
// code dependencies and might use the array protector cell. // code dependencies and might use the array protector cell.
bool CanTreatHoleAsUndefined(ZoneVector<Handle<Map>> const& receiver_maps); bool CanTreatHoleAsUndefined(ZoneVector<MapRef> const& receiver_maps);
void RemoveImpossibleMaps(Node* object, ZoneVector<Handle<Map>>* maps) const; void RemoveImpossibleMaps(Node* object, ZoneVector<Handle<Map>>* maps) const;
......
...@@ -34,31 +34,28 @@ SimplifiedOperatorBuilder* PropertyAccessBuilder::simplified() const { ...@@ -34,31 +34,28 @@ SimplifiedOperatorBuilder* PropertyAccessBuilder::simplified() const {
return jsgraph()->simplified(); return jsgraph()->simplified();
} }
bool HasOnlyStringMaps(JSHeapBroker* broker, bool HasOnlyStringMaps(JSHeapBroker* broker, ZoneVector<MapRef> const& maps) {
ZoneVector<Handle<Map>> const& maps) { for (MapRef map : maps) {
for (auto map : maps) { if (!map.IsStringMap()) return false;
MapRef map_ref = MakeRef(broker, map);
if (!map_ref.IsStringMap()) return false;
} }
return true; return true;
} }
namespace { namespace {
bool HasOnlyNumberMaps(JSHeapBroker* broker, bool HasOnlyNumberMaps(JSHeapBroker* broker, ZoneVector<MapRef> const& maps) {
ZoneVector<Handle<Map>> const& maps) { for (MapRef map : maps) {
for (auto map : maps) { if (map.instance_type() != HEAP_NUMBER_TYPE) return false;
MapRef map_ref = MakeRef(broker, map);
if (map_ref.instance_type() != HEAP_NUMBER_TYPE) return false;
} }
return true; return true;
} }
} // namespace } // namespace
bool PropertyAccessBuilder::TryBuildStringCheck( bool PropertyAccessBuilder::TryBuildStringCheck(JSHeapBroker* broker,
JSHeapBroker* broker, ZoneVector<Handle<Map>> const& maps, Node** receiver, ZoneVector<MapRef> const& maps,
Node** effect, Node* control) { Node** receiver, Effect* effect,
Control control) {
if (HasOnlyStringMaps(broker, maps)) { if (HasOnlyStringMaps(broker, maps)) {
// Monormorphic string access (ignoring the fact that there are multiple // Monormorphic string access (ignoring the fact that there are multiple
// String maps). // String maps).
...@@ -70,9 +67,10 @@ bool PropertyAccessBuilder::TryBuildStringCheck( ...@@ -70,9 +67,10 @@ bool PropertyAccessBuilder::TryBuildStringCheck(
return false; return false;
} }
bool PropertyAccessBuilder::TryBuildNumberCheck( bool PropertyAccessBuilder::TryBuildNumberCheck(JSHeapBroker* broker,
JSHeapBroker* broker, ZoneVector<Handle<Map>> const& maps, Node** receiver, ZoneVector<MapRef> const& maps,
Node** effect, Node* control) { Node** receiver, Effect* effect,
Control control) {
if (HasOnlyNumberMaps(broker, maps)) { if (HasOnlyNumberMaps(broker, maps)) {
// Monomorphic number access (we also deal with Smis here). // Monomorphic number access (we also deal with Smis here).
*receiver = *effect = *receiver = *effect =
...@@ -83,15 +81,15 @@ bool PropertyAccessBuilder::TryBuildNumberCheck( ...@@ -83,15 +81,15 @@ bool PropertyAccessBuilder::TryBuildNumberCheck(
return false; return false;
} }
void PropertyAccessBuilder::BuildCheckMaps( void PropertyAccessBuilder::BuildCheckMaps(Node* object, Effect* effect,
Node* object, Node** effect, Node* control, Control control,
ZoneVector<Handle<Map>> const& maps) { ZoneVector<MapRef> const& maps) {
HeapObjectMatcher m(object); HeapObjectMatcher m(object);
if (m.HasResolvedValue()) { if (m.HasResolvedValue()) {
MapRef object_map = m.Ref(broker()).map(); MapRef object_map = m.Ref(broker()).map();
if (object_map.is_stable()) { if (object_map.is_stable()) {
for (Handle<Map> map : maps) { for (MapRef map : maps) {
if (MakeRef(broker(), map).equals(object_map)) { if (map.equals(object_map)) {
dependencies()->DependOnStableMap(object_map); dependencies()->DependOnStableMap(object_map);
return; return;
} }
...@@ -100,10 +98,9 @@ void PropertyAccessBuilder::BuildCheckMaps( ...@@ -100,10 +98,9 @@ void PropertyAccessBuilder::BuildCheckMaps(
} }
ZoneHandleSet<Map> map_set; ZoneHandleSet<Map> map_set;
CheckMapsFlags flags = CheckMapsFlag::kNone; CheckMapsFlags flags = CheckMapsFlag::kNone;
for (Handle<Map> map : maps) { for (MapRef map : maps) {
MapRef object_map = MakeRef(broker(), map); map_set.insert(map.object(), graph()->zone());
map_set.insert(object_map.object(), graph()->zone()); if (map.is_migration_target()) {
if (object_map.is_migration_target()) {
flags |= CheckMapsFlag::kTryMigrateInstance; flags |= CheckMapsFlag::kTryMigrateInstance;
} }
} }
...@@ -127,9 +124,9 @@ Node* PropertyAccessBuilder::BuildCheckValue(Node* receiver, Effect* effect, ...@@ -127,9 +124,9 @@ Node* PropertyAccessBuilder::BuildCheckValue(Node* receiver, Effect* effect,
Node* PropertyAccessBuilder::ResolveHolder( Node* PropertyAccessBuilder::ResolveHolder(
PropertyAccessInfo const& access_info, Node* lookup_start_object) { PropertyAccessInfo const& access_info, Node* lookup_start_object) {
Handle<JSObject> holder; base::Optional<JSObjectRef> holder = access_info.holder();
if (access_info.holder().ToHandle(&holder)) { if (holder.has_value()) {
return jsgraph()->Constant(MakeRef(broker(), holder)); return jsgraph()->Constant(holder.value());
} }
return lookup_start_object; return lookup_start_object;
} }
...@@ -155,29 +152,27 @@ base::Optional<Node*> PropertyAccessBuilder::FoldLoadDictPrototypeConstant( ...@@ -155,29 +152,27 @@ base::Optional<Node*> PropertyAccessBuilder::FoldLoadDictPrototypeConstant(
DCHECK(V8_DICT_PROPERTY_CONST_TRACKING_BOOL); DCHECK(V8_DICT_PROPERTY_CONST_TRACKING_BOOL);
DCHECK(access_info.IsDictionaryProtoDataConstant()); DCHECK(access_info.IsDictionaryProtoDataConstant());
JSObjectRef holder =
MakeRef(broker(), access_info.holder().ToHandleChecked());
InternalIndex index = access_info.dictionary_index(); InternalIndex index = access_info.dictionary_index();
base::Optional<ObjectRef> value = base::Optional<ObjectRef> value =
holder.GetOwnDictionaryProperty(index, dependencies()); access_info.holder()->GetOwnDictionaryProperty(index, dependencies());
if (!value) return {}; if (!value) return {};
for (Handle<Map> map : access_info.lookup_start_object_maps()) { for (MapRef map : access_info.lookup_start_object_maps()) {
Handle<Map> map_handle = map.object();
// Non-JSReceivers that passed AccessInfoFactory::ComputePropertyAccessInfo // Non-JSReceivers that passed AccessInfoFactory::ComputePropertyAccessInfo
// must have different lookup start map. // must have different lookup start map.
if (!map->IsJSReceiverMap()) { if (!map_handle->IsJSReceiverMap()) {
// Perform the implicit ToObject for primitives here. // Perform the implicit ToObject for primitives here.
// Implemented according to ES6 section 7.3.2 GetV (V, P). // Implemented according to ES6 section 7.3.2 GetV (V, P).
JSFunction constructor = JSFunction constructor =
Map::GetConstructorFunction( Map::GetConstructorFunction(
*map, *broker()->target_native_context().object()) *map_handle, *broker()->target_native_context().object())
.value(); .value();
map = MakeRef(broker(), constructor.initial_map()).object(); map = MakeRef(broker(), constructor.initial_map());
DCHECK(map->IsJSObjectMap()); DCHECK(map.object()->IsJSObjectMap());
} }
dependencies()->DependOnConstantInDictionaryPrototypeChain( dependencies()->DependOnConstantInDictionaryPrototypeChain(
MakeRef(broker(), map), MakeRef(broker(), access_info.name()), map, access_info.name(), value.value(), PropertyKind::kData);
value.value(), PropertyKind::kData);
} }
return jsgraph()->Constant(value.value()); return jsgraph()->Constant(value.value());
...@@ -189,9 +184,10 @@ Node* PropertyAccessBuilder::TryFoldLoadConstantDataField( ...@@ -189,9 +184,10 @@ Node* PropertyAccessBuilder::TryFoldLoadConstantDataField(
if (!access_info.IsFastDataConstant()) return nullptr; if (!access_info.IsFastDataConstant()) return nullptr;
// First, determine if we have a constant holder to load from. // First, determine if we have a constant holder to load from.
Handle<JSObject> holder; base::Optional<JSObjectRef> holder = access_info.holder();
// If {access_info} has a holder, just use it. // If {access_info} has a holder, just use it.
if (!access_info.holder().ToHandle(&holder)) { if (!holder.has_value()) {
// Otherwise, try to match the {lookup_start_object} as a constant. // Otherwise, try to match the {lookup_start_object} as a constant.
HeapObjectMatcher m(lookup_start_object); HeapObjectMatcher m(lookup_start_object);
if (!m.HasResolvedValue() || !m.Ref(broker()).IsJSObject()) return nullptr; if (!m.HasResolvedValue() || !m.Ref(broker()).IsJSObject()) return nullptr;
...@@ -199,26 +195,22 @@ Node* PropertyAccessBuilder::TryFoldLoadConstantDataField( ...@@ -199,26 +195,22 @@ Node* PropertyAccessBuilder::TryFoldLoadConstantDataField(
// Let us make sure the actual map of the constant lookup_start_object is // Let us make sure the actual map of the constant lookup_start_object is
// among the maps in {access_info}. // among the maps in {access_info}.
MapRef lookup_start_object_map = m.Ref(broker()).map(); MapRef lookup_start_object_map = m.Ref(broker()).map();
if (std::find_if( if (std::find_if(access_info.lookup_start_object_maps().begin(),
access_info.lookup_start_object_maps().begin(), access_info.lookup_start_object_maps().end(),
access_info.lookup_start_object_maps().end(), [&](Handle<Map> map) { [&](MapRef map) {
return MakeRef(broker(), map).equals(lookup_start_object_map); return map.equals(lookup_start_object_map);
}) == access_info.lookup_start_object_maps().end()) { }) == access_info.lookup_start_object_maps().end()) {
// The map of the lookup_start_object is not in the feedback, let us bail // The map of the lookup_start_object is not in the feedback, let us bail
// out. // out.
return nullptr; return nullptr;
} }
holder = m.Ref(broker()).AsJSObject().object(); holder = m.Ref(broker()).AsJSObject();
} }
JSObjectRef holder_ref = MakeRef(broker(), holder); base::Optional<ObjectRef> value =
base::Optional<ObjectRef> value = holder_ref.GetOwnFastDataProperty( holder->GetOwnFastDataProperty(access_info.field_representation(),
access_info.field_representation(), access_info.field_index(), access_info.field_index(), dependencies());
dependencies()); return value.has_value() ? jsgraph()->Constant(*value) : nullptr;
if (!value.has_value()) {
return nullptr;
}
return jsgraph()->Constant(*value);
} }
Node* PropertyAccessBuilder::BuildLoadDataField(NameRef const& name, Node* PropertyAccessBuilder::BuildLoadDataField(NameRef const& name,
...@@ -333,12 +325,11 @@ Node* PropertyAccessBuilder::BuildLoadDataField( ...@@ -333,12 +325,11 @@ Node* PropertyAccessBuilder::BuildLoadDataField(
field_representation == MachineRepresentation::kCompressedPointer) { field_representation == MachineRepresentation::kCompressedPointer) {
// Remember the map of the field value, if its map is stable. This is // Remember the map of the field value, if its map is stable. This is
// used by the LoadElimination to eliminate map checks on the result. // used by the LoadElimination to eliminate map checks on the result.
Handle<Map> field_map; base::Optional<MapRef> field_map = access_info.field_map();
if (access_info.field_map().ToHandle(&field_map)) { if (field_map.has_value()) {
MapRef field_map_ref = MakeRef(broker(), field_map); if (field_map->is_stable()) {
if (field_map_ref.is_stable()) { dependencies()->DependOnStableMap(field_map.value());
dependencies()->DependOnStableMap(field_map_ref); field_access.map = field_map->object();
field_access.map = field_map;
} }
} }
} }
......
...@@ -36,25 +36,15 @@ class PropertyAccessBuilder { ...@@ -36,25 +36,15 @@ class PropertyAccessBuilder {
// Builds the appropriate string check if the maps are only string // Builds the appropriate string check if the maps are only string
// maps. // maps.
bool TryBuildStringCheck(JSHeapBroker* broker, bool TryBuildStringCheck(JSHeapBroker* broker, ZoneVector<MapRef> const& maps,
ZoneVector<Handle<Map>> const& maps, Node** receiver, Node** receiver, Effect* effect, Control control);
Node** effect, Node* control);
// Builds a number check if all maps are number maps. // Builds a number check if all maps are number maps.
bool TryBuildNumberCheck(JSHeapBroker* broker, bool TryBuildNumberCheck(JSHeapBroker* broker, ZoneVector<MapRef> const& maps,
ZoneVector<Handle<Map>> const& maps, Node** receiver, Node** receiver, Effect* effect, Control control);
Node** effect, Node* control);
// TODO(jgruber): Remove the untyped version once all uses are
// updated.
void BuildCheckMaps(Node* object, Node** effect, Node* control,
ZoneVector<Handle<Map>> const& maps);
void BuildCheckMaps(Node* object, Effect* effect, Control control, void BuildCheckMaps(Node* object, Effect* effect, Control control,
ZoneVector<Handle<Map>> const& maps) { ZoneVector<MapRef> const& maps);
Node* e = *effect;
Node* c = control;
BuildCheckMaps(object, &e, c, maps);
*effect = e;
}
Node* BuildCheckValue(Node* receiver, Effect* effect, Control control, Node* BuildCheckValue(Node* receiver, Effect* effect, Control control,
Handle<HeapObject> value); Handle<HeapObject> value);
...@@ -106,8 +96,7 @@ class PropertyAccessBuilder { ...@@ -106,8 +96,7 @@ class PropertyAccessBuilder {
CompilationDependencies* dependencies_; CompilationDependencies* dependencies_;
}; };
bool HasOnlyStringMaps(JSHeapBroker* broker, bool HasOnlyStringMaps(JSHeapBroker* broker, ZoneVector<MapRef> const& maps);
ZoneVector<Handle<Map>> const& maps);
} // namespace compiler } // namespace compiler
} // namespace internal } // namespace internal
......
...@@ -2613,13 +2613,12 @@ PropertyAccessInfo SerializerForBackgroundCompilation::ProcessMapForRegExpTest( ...@@ -2613,13 +2613,12 @@ PropertyAccessInfo SerializerForBackgroundCompilation::ProcessMapForRegExpTest(
AccessMode::kLoad, dependencies(), AccessMode::kLoad, dependencies(),
SerializationPolicy::kSerializeIfNeeded); SerializationPolicy::kSerializeIfNeeded);
Handle<JSObject> holder; base::Optional<JSObjectRef> holder = ai_exec.holder();
if (ai_exec.IsFastDataConstant() && ai_exec.holder().ToHandle(&holder)) { if (ai_exec.IsFastDataConstant() && holder.has_value()) {
// The property is on the prototype chain. // The property is on the prototype chain.
JSObjectRef holder_ref = MakeRef(broker(), holder); holder->GetOwnFastDataProperty(ai_exec.field_representation(),
holder_ref.GetOwnFastDataProperty(ai_exec.field_representation(), ai_exec.field_index(), nullptr,
ai_exec.field_index(), nullptr, SerializationPolicy::kSerializeIfNeeded);
SerializationPolicy::kSerializeIfNeeded);
} }
return ai_exec; return ai_exec;
} }
...@@ -2632,13 +2631,12 @@ void SerializerForBackgroundCompilation::ProcessHintsForRegExpTest( ...@@ -2632,13 +2631,12 @@ void SerializerForBackgroundCompilation::ProcessHintsForRegExpTest(
Handle<Map> regexp_map(regexp->map(), broker()->isolate()); Handle<Map> regexp_map(regexp->map(), broker()->isolate());
PropertyAccessInfo ai_exec = PropertyAccessInfo ai_exec =
ProcessMapForRegExpTest(MakeRef(broker(), regexp_map)); ProcessMapForRegExpTest(MakeRef(broker(), regexp_map));
Handle<JSObject> holder; base::Optional<JSObjectRef> holder = ai_exec.holder();
if (ai_exec.IsFastDataConstant() && !ai_exec.holder().ToHandle(&holder)) { if (ai_exec.IsFastDataConstant() && holder.has_value()) {
// The property is on the object itself. // The property is on the object itself.
JSObjectRef holder_ref = MakeRef(broker(), regexp); holder->GetOwnFastDataProperty(ai_exec.field_representation(),
holder_ref.GetOwnFastDataProperty( ai_exec.field_index(), nullptr,
ai_exec.field_representation(), ai_exec.field_index(), nullptr, SerializationPolicy::kSerializeIfNeeded);
SerializationPolicy::kSerializeIfNeeded);
} }
} }
...@@ -2927,12 +2925,12 @@ void SerializerForBackgroundCompilation::ProcessMapForNamedPropertyAccess( ...@@ -2927,12 +2925,12 @@ void SerializerForBackgroundCompilation::ProcessMapForNamedPropertyAccess(
// For JSNativeContextSpecialization::InlinePropertySetterCall // For JSNativeContextSpecialization::InlinePropertySetterCall
// and InlinePropertyGetterCall. // and InlinePropertyGetterCall.
base::Optional<ObjectRef> constant = access_info.constant();
if ((access_info.IsFastAccessorConstant() || if ((access_info.IsFastAccessorConstant() ||
access_info.IsDictionaryProtoAccessorConstant()) && access_info.IsDictionaryProtoAccessorConstant()) &&
!access_info.constant().is_null()) { constant.has_value()) {
if (access_info.constant()->IsJSFunction()) { if (constant->IsJSFunction()) {
JSFunctionRef function = JSFunctionRef function = constant->AsJSFunction();
MakeRef(broker(), Handle<JSFunction>::cast(access_info.constant()));
if (receiver_map.has_value()) { if (receiver_map.has_value()) {
// For JSCallReducer and JSInlining(Heuristic). // For JSCallReducer and JSInlining(Heuristic).
...@@ -2957,16 +2955,10 @@ void SerializerForBackgroundCompilation::ProcessMapForNamedPropertyAccess( ...@@ -2957,16 +2955,10 @@ void SerializerForBackgroundCompilation::ProcessMapForNamedPropertyAccess(
} }
} }
} }
} else if (access_info.constant()->IsJSBoundFunction()) {
// For JSCallReducer::ReduceJSCall.
MakeRef(broker(), Handle<JSBoundFunction>::cast(access_info.constant()));
} else {
MakeRef(broker(), FunctionTemplateInfo::cast(*access_info.constant()));
} }
} else if (access_info.IsModuleExport()) { } else if (access_info.IsModuleExport()) {
// For JSNativeContextSpecialization::BuildPropertyLoad // For JSNativeContextSpecialization::BuildPropertyLoad
DCHECK(!access_info.constant().is_null()); DCHECK(access_info.constant()->IsCell());
MakeRef(broker(), Handle<Cell>::cast(access_info.constant()));
} }
switch (access_mode) { switch (access_mode) {
...@@ -2975,11 +2967,8 @@ void SerializerForBackgroundCompilation::ProcessMapForNamedPropertyAccess( ...@@ -2975,11 +2967,8 @@ void SerializerForBackgroundCompilation::ProcessMapForNamedPropertyAccess(
// PropertyAccessBuilder::BuildLoadDictPrototypeConstant // PropertyAccessBuilder::BuildLoadDictPrototypeConstant
if (access_info.IsFastDataConstant() || if (access_info.IsFastDataConstant() ||
access_info.IsDictionaryProtoDataConstant()) { access_info.IsDictionaryProtoDataConstant()) {
base::Optional<JSObjectRef> holder; base::Optional<JSObjectRef> holder = access_info.holder();
Handle<JSObject> prototype; if (!holder.has_value()) {
if (access_info.holder().ToHandle(&prototype)) {
holder = MakeRef(broker(), prototype);
} else {
CHECK_IMPLIES(concrete_receiver.has_value(), CHECK_IMPLIES(concrete_receiver.has_value(),
concrete_receiver->map().equals(*receiver_map)); concrete_receiver->map().equals(*receiver_map));
holder = concrete_receiver; holder = concrete_receiver;
...@@ -3004,12 +2993,12 @@ void SerializerForBackgroundCompilation::ProcessMapForNamedPropertyAccess( ...@@ -3004,12 +2993,12 @@ void SerializerForBackgroundCompilation::ProcessMapForNamedPropertyAccess(
case AccessMode::kStoreInLiteral: case AccessMode::kStoreInLiteral:
// For MapInference (StoreField case). // For MapInference (StoreField case).
if (access_info.IsDataField() || access_info.IsFastDataConstant()) { if (access_info.IsDataField() || access_info.IsFastDataConstant()) {
Handle<Map> transition_map; base::Optional<MapRef> transition_map = access_info.transition_map();
if (access_info.transition_map().ToHandle(&transition_map)) { if (transition_map.has_value()) {
MapRef map_ref = MakeRef(broker(), transition_map);
TRACE_BROKER(broker(), "Propagating transition map " TRACE_BROKER(broker(), "Propagating transition map "
<< map_ref << " to receiver hints."); << transition_map.value()
receiver->AddMap(transition_map, zone(), broker_, false); << " to receiver hints.");
receiver->AddMap(transition_map->object(), zone(), broker_, false);
} }
} }
break; break;
...@@ -3323,10 +3312,10 @@ void SerializerForBackgroundCompilation::ProcessConstantForInstanceOf( ...@@ -3323,10 +3312,10 @@ void SerializerForBackgroundCompilation::ProcessConstantForInstanceOf(
ProcessConstantForOrdinaryHasInstance(constructor_heap_object, ProcessConstantForOrdinaryHasInstance(constructor_heap_object,
walk_prototypes); walk_prototypes);
} else if (access_info.IsFastDataConstant()) { } else if (access_info.IsFastDataConstant()) {
Handle<JSObject> holder; base::Optional<JSObjectRef> holder = access_info.holder();
bool found_on_proto = access_info.holder().ToHandle(&holder); bool found_on_proto = holder.has_value();
JSObjectRef holder_ref = JSObjectRef holder_ref =
found_on_proto ? MakeRef(broker(), holder) : constructor.AsJSObject(); found_on_proto ? holder.value() : constructor.AsJSObject();
base::Optional<ObjectRef> constant = holder_ref.GetOwnFastDataProperty( base::Optional<ObjectRef> constant = holder_ref.GetOwnFastDataProperty(
access_info.field_representation(), access_info.field_index(), nullptr, access_info.field_representation(), access_info.field_index(), nullptr,
SerializationPolicy::kSerializeIfNeeded); SerializationPolicy::kSerializeIfNeeded);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment