Commit ff74066b authored by Georg Neis's avatar Georg Neis Committed by Commit Bot

[turbofan] Introduce NamedAccessFeedback

Brokerize parts of named property access.

Bug: v8:7790
Change-Id: I465bced5f266969040d1e966946a162b0a850c5b
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1596734Reviewed-by: 's avatarSigurd Schneider <sigurds@chromium.org>
Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Commit-Queue: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61414}
parent e5a5f5ae
This diff is collapsed.
...@@ -29,22 +29,21 @@ class ElementAccessFeedback; ...@@ -29,22 +29,21 @@ class ElementAccessFeedback;
class Type; class Type;
class TypeCache; class TypeCache;
// Whether we are loading a property or storing to a property.
// For a store during literal creation, do not walk up the prototype chain.
enum class AccessMode { kLoad, kStore, kStoreInLiteral, kHas };
std::ostream& operator<<(std::ostream&, AccessMode); 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(); ElementAccessInfo(ZoneVector<Handle<Map>>&& receiver_maps,
ElementAccessInfo(MapHandles const& receiver_maps, ElementsKind elements_kind, Zone* zone);
ElementsKind elements_kind);
ElementsKind elements_kind() const { return elements_kind_; } ElementsKind elements_kind() const { return elements_kind_; }
MapHandles const& receiver_maps() const { return receiver_maps_; } ZoneVector<Handle<Map>> const& receiver_maps() const {
MapHandles const& transition_sources() const { return transition_sources_; } return receiver_maps_;
}
ZoneVector<Handle<Map>> const& transition_sources() const {
return transition_sources_;
}
void AddTransitionSource(Handle<Map> map) { void AddTransitionSource(Handle<Map> map) {
CHECK_EQ(receiver_maps_.size(), 1); CHECK_EQ(receiver_maps_.size(), 1);
...@@ -53,8 +52,8 @@ class ElementAccessInfo final { ...@@ -53,8 +52,8 @@ class ElementAccessInfo final {
private: private:
ElementsKind elements_kind_; ElementsKind elements_kind_;
MapHandles receiver_maps_; ZoneVector<Handle<Map>> receiver_maps_;
MapHandles transition_sources_; ZoneVector<Handle<Map>> transition_sources_;
}; };
// This class encapsulates all information required to access a certain // This class encapsulates all information required to access a certain
...@@ -71,31 +70,31 @@ class PropertyAccessInfo final { ...@@ -71,31 +70,31 @@ class PropertyAccessInfo final {
kStringLength kStringLength
}; };
static PropertyAccessInfo NotFound(MapHandles const& receiver_maps, static PropertyAccessInfo NotFound(Zone* zone, Handle<Map> receiver_map,
MaybeHandle<JSObject> holder); MaybeHandle<JSObject> holder);
static PropertyAccessInfo DataField( static PropertyAccessInfo DataField(
MapHandles const& receiver_maps, Zone* zone, Handle<Map> receiver_map,
std::vector<CompilationDependencies::Dependency const*>&& ZoneVector<CompilationDependencies::Dependency const*>&&
unrecorded_dependencies, unrecorded_dependencies,
FieldIndex field_index, MachineRepresentation field_representation, FieldIndex field_index, MachineRepresentation field_representation,
Type field_type, MaybeHandle<Map> field_map = MaybeHandle<Map>(), Type field_type, MaybeHandle<Map> field_map = MaybeHandle<Map>(),
MaybeHandle<JSObject> holder = MaybeHandle<JSObject>(), MaybeHandle<JSObject> holder = MaybeHandle<JSObject>(),
MaybeHandle<Map> transition_map = MaybeHandle<Map>()); MaybeHandle<Map> transition_map = MaybeHandle<Map>());
static PropertyAccessInfo DataConstant( static PropertyAccessInfo DataConstant(
MapHandles const& receiver_maps, Zone* zone, Handle<Map> receiver_map,
std::vector<CompilationDependencies::Dependency const*>&& ZoneVector<CompilationDependencies::Dependency const*>&&
unrecorded_dependencies, unrecorded_dependencies,
FieldIndex field_index, MachineRepresentation field_representation, FieldIndex field_index, MachineRepresentation field_representation,
Type field_type, MaybeHandle<Map> field_map, Type field_type, MaybeHandle<Map> field_map,
MaybeHandle<JSObject> holder); MaybeHandle<JSObject> holder);
static PropertyAccessInfo AccessorConstant(MapHandles const& receiver_maps, static PropertyAccessInfo AccessorConstant(Zone* zone,
Handle<Map> receiver_map,
Handle<Object> constant, Handle<Object> constant,
MaybeHandle<JSObject> holder); MaybeHandle<JSObject> holder);
static PropertyAccessInfo ModuleExport(MapHandles const& receiver_maps, static PropertyAccessInfo ModuleExport(Zone* zone, Handle<Map> receiver_map,
Handle<Cell> cell); Handle<Cell> cell);
static PropertyAccessInfo StringLength(MapHandles const& receiver_maps); static PropertyAccessInfo StringLength(Zone* zone, Handle<Map> receiver_map);
static PropertyAccessInfo Invalid(Zone* zone);
PropertyAccessInfo();
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;
...@@ -127,24 +126,28 @@ class PropertyAccessInfo final { ...@@ -127,24 +126,28 @@ class PropertyAccessInfo final {
return field_representation_; return field_representation_;
} }
MaybeHandle<Map> field_map() const { return field_map_; } MaybeHandle<Map> field_map() const { return field_map_; }
MapHandles const& receiver_maps() const { return receiver_maps_; } ZoneVector<Handle<Map>> const& receiver_maps() const {
return receiver_maps_;
}
Handle<Cell> export_cell() const; Handle<Cell> export_cell() const;
private: private:
PropertyAccessInfo(Kind kind, MaybeHandle<JSObject> holder, explicit PropertyAccessInfo(Zone* zone);
MapHandles const& receiver_maps); PropertyAccessInfo(Zone* zone, Kind kind, MaybeHandle<JSObject> holder,
PropertyAccessInfo(Kind kind, MaybeHandle<JSObject> holder, ZoneVector<Handle<Map>>&& receiver_maps);
Handle<Object> constant, MapHandles const& receiver_maps); PropertyAccessInfo(Zone* zone, Kind kind, MaybeHandle<JSObject> holder,
Handle<Object> constant,
ZoneVector<Handle<Map>>&& receiver_maps);
PropertyAccessInfo( PropertyAccessInfo(
Kind kind, MaybeHandle<JSObject> holder, MaybeHandle<Map> transition_map, Kind kind, MaybeHandle<JSObject> holder, MaybeHandle<Map> transition_map,
FieldIndex field_index, MachineRepresentation field_representation, FieldIndex field_index, MachineRepresentation field_representation,
Type field_type, MaybeHandle<Map> field_map, Type field_type, MaybeHandle<Map> field_map,
MapHandles const& receiver_maps, ZoneVector<Handle<Map>>&& receiver_maps,
std::vector<CompilationDependencies::Dependency const*>&& dependencies); ZoneVector<CompilationDependencies::Dependency const*>&& dependencies);
Kind kind_; Kind kind_;
MapHandles receiver_maps_; ZoneVector<Handle<Map>> receiver_maps_;
std::vector<CompilationDependencies::Dependency const*> ZoneVector<CompilationDependencies::Dependency const*>
unrecorded_dependencies_; unrecorded_dependencies_;
Handle<Object> constant_; Handle<Object> constant_;
MaybeHandle<Map> transition_map_; MaybeHandle<Map> transition_map_;
...@@ -162,8 +165,8 @@ class AccessInfoFactory final { ...@@ -162,8 +165,8 @@ class AccessInfoFactory final {
AccessInfoFactory(JSHeapBroker* broker, CompilationDependencies* dependencies, AccessInfoFactory(JSHeapBroker* broker, CompilationDependencies* dependencies,
Zone* zone); Zone* zone);
bool ComputeElementAccessInfo(Handle<Map> map, AccessMode access_mode, base::Optional<ElementAccessInfo> ComputeElementAccessInfo(
ElementAccessInfo* access_info) const; Handle<Map> map, AccessMode access_mode) const;
bool ComputeElementAccessInfos( bool ComputeElementAccessInfos(
FeedbackNexus nexus, MapHandles const& maps, AccessMode access_mode, FeedbackNexus nexus, MapHandles const& maps, AccessMode access_mode,
ZoneVector<ElementAccessInfo>* access_infos) const; ZoneVector<ElementAccessInfo>* access_infos) const;
...@@ -192,8 +195,8 @@ class AccessInfoFactory final { ...@@ -192,8 +195,8 @@ class AccessInfoFactory final {
ZoneVector<PropertyAccessInfo> infos, AccessMode access_mode) const; ZoneVector<PropertyAccessInfo> infos, AccessMode access_mode) const;
private: private:
bool ConsolidateElementLoad(ElementAccessFeedback const& processed, base::Optional<ElementAccessInfo> ConsolidateElementLoad(
ElementAccessInfo* access_info) const; ElementAccessFeedback const& processed) const;
PropertyAccessInfo LookupSpecialFieldAccessor(Handle<Map> map, PropertyAccessInfo LookupSpecialFieldAccessor(Handle<Map> map,
Handle<Name> name) const; Handle<Name> name) const;
PropertyAccessInfo LookupTransition(Handle<Map> map, Handle<Name> name, PropertyAccessInfo LookupTransition(Handle<Map> map, Handle<Name> name,
......
...@@ -599,7 +599,7 @@ void CompilationDependencies::DependOnStablePrototypeChains( ...@@ -599,7 +599,7 @@ void CompilationDependencies::DependOnStablePrototypeChains(
} }
} }
template void CompilationDependencies::DependOnStablePrototypeChains( template void CompilationDependencies::DependOnStablePrototypeChains(
MapHandles const& receiver_maps, WhereToStart start, ZoneVector<Handle<Map>> const& receiver_maps, WhereToStart start,
base::Optional<JSObjectRef> last_prototype); base::Optional<JSObjectRef> last_prototype);
template void CompilationDependencies::DependOnStablePrototypeChains( template void CompilationDependencies::DependOnStablePrototypeChains(
ZoneHandleSet<Map> const& receiver_maps, WhereToStart start, ZoneHandleSet<Map> const& receiver_maps, WhereToStart start,
......
...@@ -6749,17 +6749,15 @@ Reduction JSCallReducer::ReduceRegExpPrototypeTest(Node* node) { ...@@ -6749,17 +6749,15 @@ Reduction JSCallReducer::ReduceRegExpPrototypeTest(Node* node) {
MapHandles const& regexp_maps = inference.GetMaps(); MapHandles const& regexp_maps = inference.GetMaps();
// Compute property access info for "exec" on {resolution}. // Compute property access info for "exec" on {resolution}.
PropertyAccessInfo ai_exec; ZoneVector<PropertyAccessInfo> access_infos(graph()->zone());
{ AccessInfoFactory access_info_factory(broker(), dependencies(),
ZoneVector<PropertyAccessInfo> access_infos(graph()->zone()); graph()->zone());
AccessInfoFactory access_info_factory(broker(), dependencies(), access_info_factory.ComputePropertyAccessInfos(
graph()->zone()); MapHandles(regexp_maps.begin(), regexp_maps.end()),
access_info_factory.ComputePropertyAccessInfos( factory()->exec_string(), AccessMode::kLoad, &access_infos);
MapHandles(regexp_maps.begin(), regexp_maps.end()), PropertyAccessInfo ai_exec =
factory()->exec_string(), AccessMode::kLoad, &access_infos); access_info_factory.FinalizePropertyAccessInfosAsOne(access_infos,
ai_exec = access_info_factory.FinalizePropertyAccessInfosAsOne( AccessMode::kLoad);
access_infos, AccessMode::kLoad);
}
if (ai_exec.IsInvalid()) return inference.NoChange(); if (ai_exec.IsInvalid()) return inference.NoChange();
// If "exec" has been modified on {regexp}, we can't do anything. // If "exec" has been modified on {regexp}, we can't do anything.
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "src/bootstrapper.h" #include "src/bootstrapper.h"
#include "src/boxed-float.h" #include "src/boxed-float.h"
#include "src/code-factory.h" #include "src/code-factory.h"
#include "src/compiler/access-info.h"
#include "src/compiler/graph-reducer.h" #include "src/compiler/graph-reducer.h"
#include "src/compiler/per-isolate-compiler-cache.h" #include "src/compiler/per-isolate-compiler-cache.h"
#include "src/objects-inl.h" #include "src/objects-inl.h"
...@@ -3256,6 +3257,9 @@ bool CanInlineElementAccess(MapRef const& map) { ...@@ -3256,6 +3257,9 @@ bool CanInlineElementAccess(MapRef const& map) {
return false; return false;
} }
InsufficientFeedback::InsufficientFeedback()
: ProcessedFeedback(kInsufficient) {}
GlobalAccessFeedback::GlobalAccessFeedback(PropertyCellRef cell) GlobalAccessFeedback::GlobalAccessFeedback(PropertyCellRef cell)
: ProcessedFeedback(kGlobalAccess), : ProcessedFeedback(kGlobalAccess),
cell_or_context_(cell), cell_or_context_(cell),
...@@ -3336,6 +3340,14 @@ ElementAccessFeedback::MapIterator ElementAccessFeedback::all_maps( ...@@ -3336,6 +3340,14 @@ ElementAccessFeedback::MapIterator ElementAccessFeedback::all_maps(
return MapIterator(*this, broker); return MapIterator(*this, broker);
} }
NamedAccessFeedback::NamedAccessFeedback(
NameRef const& name, ZoneVector<PropertyAccessInfo> const& access_infos)
: ProcessedFeedback(kNamedAccess),
name_(name),
access_infos_(access_infos) {
CHECK(!access_infos.empty());
}
FeedbackSource::FeedbackSource(FeedbackNexus const& nexus) FeedbackSource::FeedbackSource(FeedbackNexus const& nexus)
: vector(nexus.vector_handle()), slot(nexus.slot()) {} : vector(nexus.vector_handle()), slot(nexus.slot()) {}
...@@ -3377,6 +3389,8 @@ GlobalAccessFeedback const* JSHeapBroker::GetGlobalAccessFeedback( ...@@ -3377,6 +3389,8 @@ GlobalAccessFeedback const* JSHeapBroker::GetGlobalAccessFeedback(
ElementAccessFeedback const* JSHeapBroker::ProcessFeedbackMapsForElementAccess( ElementAccessFeedback const* JSHeapBroker::ProcessFeedbackMapsForElementAccess(
MapHandles const& maps) { MapHandles const& maps) {
DCHECK(!maps.empty());
// Collect possible transition targets. // Collect possible transition targets.
MapHandles possible_transition_targets; MapHandles possible_transition_targets;
possible_transition_targets.reserve(maps.size()); possible_transition_targets.reserve(maps.size());
...@@ -3388,8 +3402,6 @@ ElementAccessFeedback const* JSHeapBroker::ProcessFeedbackMapsForElementAccess( ...@@ -3388,8 +3402,6 @@ ElementAccessFeedback const* JSHeapBroker::ProcessFeedbackMapsForElementAccess(
} }
} }
if (maps.empty()) return nullptr;
ElementAccessFeedback* result = new (zone()) ElementAccessFeedback(zone()); ElementAccessFeedback* result = new (zone()) ElementAccessFeedback(zone());
// Separate the actual receiver maps and the possible transition sources. // Separate the actual receiver maps and the possible transition sources.
......
...@@ -37,6 +37,10 @@ class VectorSlotPair; ...@@ -37,6 +37,10 @@ class VectorSlotPair;
namespace compiler { namespace compiler {
// Whether we are loading a property or storing to a property.
// For a store during literal creation, do not walk up the prototype chain.
enum class AccessMode { kLoad, kStore, kStoreInLiteral, kHas };
enum class OddballType : uint8_t { enum class OddballType : uint8_t {
kNone, // Not an Oddball. kNone, // Not an Oddball.
kBoolean, // True or False. kBoolean, // True or False.
...@@ -97,6 +101,7 @@ class CompilationDependencies; ...@@ -97,6 +101,7 @@ class CompilationDependencies;
class JSHeapBroker; class JSHeapBroker;
class ObjectData; class ObjectData;
class PerIsolateCompilerCache; class PerIsolateCompilerCache;
class PropertyAccessInfo;
#define FORWARD_DECL(Name) class Name##Ref; #define FORWARD_DECL(Name) class Name##Ref;
HEAP_BROKER_OBJECT_LIST(FORWARD_DECL) HEAP_BROKER_OBJECT_LIST(FORWARD_DECL)
#undef FORWARD_DECL #undef FORWARD_DECL
...@@ -704,7 +709,7 @@ class InternalizedStringRef : public StringRef { ...@@ -704,7 +709,7 @@ class InternalizedStringRef : public StringRef {
class ProcessedFeedback : public ZoneObject { class ProcessedFeedback : public ZoneObject {
public: public:
enum Kind { kElementAccess, kGlobalAccess }; enum Kind { kInsufficient, kGlobalAccess, kNamedAccess, kElementAccess };
Kind kind() const { return kind_; } Kind kind() const { return kind_; }
protected: protected:
...@@ -714,6 +719,11 @@ class ProcessedFeedback : public ZoneObject { ...@@ -714,6 +719,11 @@ class ProcessedFeedback : public ZoneObject {
Kind const kind_; Kind const kind_;
}; };
class InsufficientFeedback final : public ProcessedFeedback {
public:
InsufficientFeedback();
};
class GlobalAccessFeedback : public ProcessedFeedback { class GlobalAccessFeedback : public ProcessedFeedback {
public: public:
explicit GlobalAccessFeedback(PropertyCellRef cell); explicit GlobalAccessFeedback(PropertyCellRef cell);
...@@ -765,6 +775,21 @@ class ElementAccessFeedback : public ProcessedFeedback { ...@@ -765,6 +775,21 @@ class ElementAccessFeedback : public ProcessedFeedback {
MapIterator all_maps(JSHeapBroker* broker) const; MapIterator all_maps(JSHeapBroker* broker) const;
}; };
class NamedAccessFeedback : public ProcessedFeedback {
public:
NamedAccessFeedback(NameRef const& name,
ZoneVector<PropertyAccessInfo> const& access_infos);
NameRef const& name() const { return name_; }
ZoneVector<PropertyAccessInfo> const& access_infos() const {
return access_infos_;
}
private:
NameRef const name_;
ZoneVector<PropertyAccessInfo> const access_infos_;
};
struct FeedbackSource { struct FeedbackSource {
FeedbackSource(Handle<FeedbackVector> vector_, FeedbackSlot slot_) FeedbackSource(Handle<FeedbackVector> vector_, FeedbackSlot slot_)
: vector(vector_), slot(slot_) {} : vector(vector_), slot(slot_) {}
......
...@@ -107,10 +107,15 @@ class V8_EXPORT_PRIVATE JSNativeContextSpecialization final ...@@ -107,10 +107,15 @@ class V8_EXPORT_PRIVATE JSNativeContextSpecialization final
FeedbackNexus const& nexus, FeedbackNexus const& nexus,
NameRef const& name, NameRef const& name,
AccessMode access_mode); AccessMode access_mode);
Reduction ReduceNamedAccess(Node* node, Node* value,
NamedAccessFeedback const& processed,
AccessMode access_mode, Node* key = nullptr);
// TODO(neis): This second version of ReduceNamedAccess is here only
// temporarily while keyed access is not fully brokerized yet.
Reduction ReduceNamedAccess(Node* node, Node* value, Reduction ReduceNamedAccess(Node* node, Node* value,
MapHandles const& receiver_maps, MapHandles const& receiver_maps,
NameRef const& name, AccessMode access_mode, NameRef const& name, AccessMode access_mode,
Node* key = nullptr); Node* key);
Reduction ReduceGlobalAccess(Node* node, Node* receiver, Node* value, Reduction ReduceGlobalAccess(Node* node, Node* receiver, Node* value,
NameRef const& name, AccessMode access_mode, NameRef const& name, AccessMode access_mode,
Node* key = nullptr); Node* key = nullptr);
...@@ -214,7 +219,7 @@ class V8_EXPORT_PRIVATE JSNativeContextSpecialization final ...@@ -214,7 +219,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(MapHandles const& receiver_maps); bool CanTreatHoleAsUndefined(ZoneVector<Handle<Map>> const& receiver_maps);
// Extract receiver maps from {nexus} and filter based on {receiver} if // Extract receiver maps from {nexus} and filter based on {receiver} if
// possible. // possible.
......
...@@ -1248,8 +1248,8 @@ struct SerializationPhase { ...@@ -1248,8 +1248,8 @@ struct SerializationPhase {
void Run(PipelineData* data, Zone* temp_zone) { void Run(PipelineData* data, Zone* temp_zone) {
SerializerForBackgroundCompilation serializer( SerializerForBackgroundCompilation serializer(
data->broker(), temp_zone, data->info()->closure(), data->broker(), data->dependencies(), temp_zone,
data->info()->is_source_positions_enabled()); data->info()->closure(), data->info()->is_source_positions_enabled());
serializer.Run(); serializer.Run();
} }
}; };
......
...@@ -32,7 +32,8 @@ SimplifiedOperatorBuilder* PropertyAccessBuilder::simplified() const { ...@@ -32,7 +32,8 @@ SimplifiedOperatorBuilder* PropertyAccessBuilder::simplified() const {
return jsgraph()->simplified(); return jsgraph()->simplified();
} }
bool HasOnlyStringMaps(JSHeapBroker* broker, MapHandles const& maps) { bool HasOnlyStringMaps(JSHeapBroker* broker,
ZoneVector<Handle<Map>> const& maps) {
for (auto map : maps) { for (auto map : maps) {
MapRef map_ref(broker, map); MapRef map_ref(broker, map);
if (!map_ref.IsStringMap()) return false; if (!map_ref.IsStringMap()) return false;
...@@ -42,7 +43,8 @@ bool HasOnlyStringMaps(JSHeapBroker* broker, MapHandles const& maps) { ...@@ -42,7 +43,8 @@ bool HasOnlyStringMaps(JSHeapBroker* broker, MapHandles const& maps) {
namespace { namespace {
bool HasOnlyNumberMaps(JSHeapBroker* broker, MapHandles const& maps) { bool HasOnlyNumberMaps(JSHeapBroker* broker,
ZoneVector<Handle<Map>> const& maps) {
for (auto map : maps) { for (auto map : maps) {
MapRef map_ref(broker, map); MapRef map_ref(broker, map);
if (map_ref.instance_type() != HEAP_NUMBER_TYPE) return false; if (map_ref.instance_type() != HEAP_NUMBER_TYPE) return false;
...@@ -52,10 +54,9 @@ bool HasOnlyNumberMaps(JSHeapBroker* broker, MapHandles const& maps) { ...@@ -52,10 +54,9 @@ bool HasOnlyNumberMaps(JSHeapBroker* broker, MapHandles const& maps) {
} // namespace } // namespace
bool PropertyAccessBuilder::TryBuildStringCheck(JSHeapBroker* broker, bool PropertyAccessBuilder::TryBuildStringCheck(
MapHandles const& maps, JSHeapBroker* broker, ZoneVector<Handle<Map>> const& maps, Node** receiver,
Node** receiver, Node** effect, Node** effect, Node* control) {
Node* 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).
...@@ -67,10 +68,9 @@ bool PropertyAccessBuilder::TryBuildStringCheck(JSHeapBroker* broker, ...@@ -67,10 +68,9 @@ bool PropertyAccessBuilder::TryBuildStringCheck(JSHeapBroker* broker,
return false; return false;
} }
bool PropertyAccessBuilder::TryBuildNumberCheck(JSHeapBroker* broker, bool PropertyAccessBuilder::TryBuildNumberCheck(
MapHandles const& maps, JSHeapBroker* broker, ZoneVector<Handle<Map>> const& maps, Node** receiver,
Node** receiver, Node** effect, Node** effect, Node* control) {
Node* 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 =
...@@ -143,9 +143,9 @@ Node* PropertyAccessBuilder::BuildCheckHeapObject(Node* receiver, Node** effect, ...@@ -143,9 +143,9 @@ Node* PropertyAccessBuilder::BuildCheckHeapObject(Node* receiver, Node** effect,
return receiver; return receiver;
} }
void PropertyAccessBuilder::BuildCheckMaps(Node* receiver, Node** effect, void PropertyAccessBuilder::BuildCheckMaps(
Node* control, Node* receiver, Node** effect, Node* control,
MapHandles const& receiver_maps) { ZoneVector<Handle<Map>> const& receiver_maps) {
HeapObjectMatcher m(receiver); HeapObjectMatcher m(receiver);
if (m.HasValue()) { if (m.HasValue()) {
MapRef receiver_map = m.Ref(broker()).map(); MapRef receiver_map = m.Ref(broker()).map();
......
...@@ -33,15 +33,17 @@ class PropertyAccessBuilder { ...@@ -33,15 +33,17 @@ 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, MapHandles const& maps, bool TryBuildStringCheck(JSHeapBroker* broker,
Node** receiver, Node** effect, Node* control); ZoneVector<Handle<Map>> const& maps, Node** receiver,
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, MapHandles const& maps, bool TryBuildNumberCheck(JSHeapBroker* broker,
Node** receiver, Node** effect, Node* control); ZoneVector<Handle<Map>> const& maps, Node** receiver,
Node** effect, Node* control);
Node* BuildCheckHeapObject(Node* receiver, Node** effect, Node* control); Node* BuildCheckHeapObject(Node* receiver, Node** effect, Node* control);
void BuildCheckMaps(Node* receiver, Node** effect, Node* control, void BuildCheckMaps(Node* receiver, Node** effect, Node* control,
std::vector<Handle<Map>> const& receiver_maps); ZoneVector<Handle<Map>> const& receiver_maps);
Node* BuildCheckValue(Node* receiver, Node** effect, Node* control, Node* BuildCheckValue(Node* receiver, Node** effect, Node* control,
Handle<HeapObject> value); Handle<HeapObject> value);
...@@ -72,7 +74,8 @@ class PropertyAccessBuilder { ...@@ -72,7 +74,8 @@ class PropertyAccessBuilder {
CompilationDependencies* dependencies_; CompilationDependencies* dependencies_;
}; };
bool HasOnlyStringMaps(JSHeapBroker* broker, MapHandles const& maps); bool HasOnlyStringMaps(JSHeapBroker* broker,
ZoneVector<Handle<Map>> const& maps);
} // namespace compiler } // namespace compiler
} // namespace internal } // namespace internal
......
...@@ -247,9 +247,10 @@ int SerializerForBackgroundCompilation::Environment::RegisterToLocalIndex( ...@@ -247,9 +247,10 @@ int SerializerForBackgroundCompilation::Environment::RegisterToLocalIndex(
} }
SerializerForBackgroundCompilation::SerializerForBackgroundCompilation( SerializerForBackgroundCompilation::SerializerForBackgroundCompilation(
JSHeapBroker* broker, Zone* zone, Handle<JSFunction> closure, JSHeapBroker* broker, CompilationDependencies* dependencies, Zone* zone,
bool collect_source_positions) Handle<JSFunction> closure, bool collect_source_positions)
: broker_(broker), : broker_(broker),
dependencies_(dependencies),
zone_(zone), zone_(zone),
collect_source_positions_(collect_source_positions), collect_source_positions_(collect_source_positions),
environment_(new (zone) Environment(zone, {closure, broker_->isolate()})), environment_(new (zone) Environment(zone, {closure, broker_->isolate()})),
...@@ -258,10 +259,11 @@ SerializerForBackgroundCompilation::SerializerForBackgroundCompilation( ...@@ -258,10 +259,11 @@ SerializerForBackgroundCompilation::SerializerForBackgroundCompilation(
} }
SerializerForBackgroundCompilation::SerializerForBackgroundCompilation( SerializerForBackgroundCompilation::SerializerForBackgroundCompilation(
JSHeapBroker* broker, Zone* zone, CompilationSubject function, JSHeapBroker* broker, CompilationDependencies* dependencies, Zone* zone,
base::Optional<Hints> new_target, const HintsVector& arguments, CompilationSubject function, base::Optional<Hints> new_target,
bool collect_source_positions) const HintsVector& arguments, bool collect_source_positions)
: broker_(broker), : broker_(broker),
dependencies_(dependencies),
zone_(zone), zone_(zone),
collect_source_positions_(collect_source_positions), collect_source_positions_(collect_source_positions),
environment_(new (zone) Environment(zone, broker_->isolate(), function, environment_(new (zone) Environment(zone, broker_->isolate(), function,
...@@ -580,7 +582,7 @@ Hints SerializerForBackgroundCompilation::RunChildSerializer( ...@@ -580,7 +582,7 @@ Hints SerializerForBackgroundCompilation::RunChildSerializer(
<< *environment()); << *environment());
SerializerForBackgroundCompilation child_serializer( SerializerForBackgroundCompilation child_serializer(
broker(), zone(), function, new_target, arguments, broker(), dependencies(), zone(), function, new_target, arguments,
collect_source_positions()); collect_source_positions());
return child_serializer.Run(); return child_serializer.Run();
} }
...@@ -790,32 +792,12 @@ MapHandles GetRelevantReceiverMaps(Isolate* isolate, MapContainer const& maps) { ...@@ -790,32 +792,12 @@ MapHandles GetRelevantReceiverMaps(Isolate* isolate, MapContainer const& maps) {
} }
} // namespace } // namespace
// Note: We never use the same feedback slot for multiple access modes. ElementAccessFeedback const*
void SerializerForBackgroundCompilation::ProcessFeedbackForKeyedPropertyAccess( SerializerForBackgroundCompilation::ProcessFeedbackMapsForElementAccess(
FeedbackSlot slot, AccessMode mode) { const MapHandles& maps, AccessMode mode) {
if (slot.IsInvalid()) return; ElementAccessFeedback const* result =
if (environment()->function().feedback_vector.is_null()) return; broker()->ProcessFeedbackMapsForElementAccess(maps);
for (ElementAccessFeedback::MapIterator it = result->all_maps(broker());
FeedbackNexus nexus(environment()->function().feedback_vector, slot);
FeedbackSource source(nexus);
if (broker()->HasFeedback(source)) return;
if (nexus.GetKeyType() == PROPERTY) {
CHECK_NE(mode, AccessMode::kStoreInLiteral);
return; // TODO(neis): Support named access.
}
DCHECK_EQ(nexus.GetKeyType(), ELEMENT);
CHECK(nexus.GetName().is_null());
MapHandles maps;
nexus.ExtractMaps(&maps);
ElementAccessFeedback const* processed =
broker()->ProcessFeedbackMapsForElementAccess(
GetRelevantReceiverMaps(broker()->isolate(), maps));
broker()->SetFeedback(source, processed);
if (processed == nullptr) return;
for (ElementAccessFeedback::MapIterator it = processed->all_maps(broker());
!it.done(); it.advance()) { !it.done(); it.advance()) {
switch (mode) { switch (mode) {
case AccessMode::kHas: case AccessMode::kHas:
...@@ -830,6 +812,41 @@ void SerializerForBackgroundCompilation::ProcessFeedbackForKeyedPropertyAccess( ...@@ -830,6 +812,41 @@ void SerializerForBackgroundCompilation::ProcessFeedbackForKeyedPropertyAccess(
break; break;
} }
} }
return result;
}
// Note: We never use the same feedback slot for multiple access modes.
void SerializerForBackgroundCompilation::ProcessFeedbackForKeyedPropertyAccess(
FeedbackSlot slot, AccessMode mode) {
if (slot.IsInvalid()) return;
if (environment()->function().feedback_vector.is_null()) return;
FeedbackNexus nexus(environment()->function().feedback_vector, slot);
FeedbackSource source(nexus);
if (broker()->HasFeedback(source)) return;
ProcessedFeedback const* processed = nullptr;
if (nexus.ic_state() == UNINITIALIZED) {
processed = new (broker()->zone()) InsufficientFeedback();
} else {
if (nexus.GetKeyType() == PROPERTY) {
CHECK_NE(mode, AccessMode::kStoreInLiteral);
// TODO(neis): Support named access.
} else {
DCHECK_EQ(nexus.GetKeyType(), ELEMENT);
DCHECK(nexus.GetName().is_null());
MapHandles maps;
if (nexus.ExtractMaps(&maps) != 0) {
maps = GetRelevantReceiverMaps(broker()->isolate(), maps);
if (maps.empty()) {
processed = new (broker()->zone()) InsufficientFeedback();
} else {
processed = ProcessFeedbackMapsForElementAccess(maps, mode);
}
}
}
}
broker()->SetFeedback(source, processed);
} }
void SerializerForBackgroundCompilation::ProcessKeyedPropertyAccess( void SerializerForBackgroundCompilation::ProcessKeyedPropertyAccess(
...@@ -878,7 +895,7 @@ void SerializerForBackgroundCompilation::ProcessMapForNamedPropertyAccess( ...@@ -878,7 +895,7 @@ void SerializerForBackgroundCompilation::ProcessMapForNamedPropertyAccess(
// Note: We never use the same feedback slot for multiple names. // Note: We never use the same feedback slot for multiple names.
void SerializerForBackgroundCompilation::ProcessFeedbackForNamedPropertyAccess( void SerializerForBackgroundCompilation::ProcessFeedbackForNamedPropertyAccess(
FeedbackSlot slot, NameRef const& name) { FeedbackSlot slot, NameRef const& name, AccessMode mode) {
if (slot.IsInvalid()) return; if (slot.IsInvalid()) return;
if (environment()->function().feedback_vector.is_null()) return; if (environment()->function().feedback_vector.is_null()) return;
...@@ -886,15 +903,31 @@ void SerializerForBackgroundCompilation::ProcessFeedbackForNamedPropertyAccess( ...@@ -886,15 +903,31 @@ void SerializerForBackgroundCompilation::ProcessFeedbackForNamedPropertyAccess(
FeedbackSource source(nexus); FeedbackSource source(nexus);
if (broker()->HasFeedback(source)) return; if (broker()->HasFeedback(source)) return;
MapHandles maps; ProcessedFeedback const* processed = nullptr;
nexus.ExtractMaps(&maps); if (nexus.ic_state() == UNINITIALIZED) {
for (Handle<Map> map : GetRelevantReceiverMaps(broker()->isolate(), maps)) { processed = new (broker()->zone()) InsufficientFeedback();
ProcessMapForNamedPropertyAccess(MapRef(broker(), map), name); } else {
MapHandles maps;
if (nexus.ExtractMaps(&maps) != 0) {
ZoneVector<PropertyAccessInfo> access_infos(broker()->zone());
for (Handle<Map> map :
GetRelevantReceiverMaps(broker()->isolate(), maps)) {
MapRef map_ref(broker(), map);
ProcessMapForNamedPropertyAccess(map_ref, name);
AccessInfoFactory access_info_factory(broker(), dependencies(),
broker()->zone());
access_infos.push_back(access_info_factory.ComputePropertyAccessInfo(
map, name.object(), mode));
}
if (access_infos.empty()) {
processed = new (broker()->zone()) InsufficientFeedback();
} else {
processed =
new (broker()->zone()) NamedAccessFeedback(name, access_infos);
}
}
} }
broker()->SetFeedback(source, processed);
// NamedProperty support is still WIP. For now we don't have any actual data
// to store, so use nullptr to at least record that we processed the feedback.
broker()->SetFeedback(source, nullptr);
} }
void SerializerForBackgroundCompilation::VisitLdaKeyedProperty( void SerializerForBackgroundCompilation::VisitLdaKeyedProperty(
...@@ -909,7 +942,7 @@ void SerializerForBackgroundCompilation::VisitLdaKeyedProperty( ...@@ -909,7 +942,7 @@ void SerializerForBackgroundCompilation::VisitLdaKeyedProperty(
void SerializerForBackgroundCompilation::ProcessNamedPropertyAccess( void SerializerForBackgroundCompilation::ProcessNamedPropertyAccess(
Hints const& receiver, NameRef const& name, FeedbackSlot slot, Hints const& receiver, NameRef const& name, FeedbackSlot slot,
AccessMode mode) { AccessMode mode) {
if (!slot.IsInvalid()) ProcessFeedbackForNamedPropertyAccess(slot, name); ProcessFeedbackForNamedPropertyAccess(slot, name, mode);
for (Handle<Map> map : for (Handle<Map> map :
GetRelevantReceiverMaps(broker()->isolate(), receiver.maps())) { GetRelevantReceiverMaps(broker()->isolate(), receiver.maps())) {
...@@ -956,6 +989,11 @@ void SerializerForBackgroundCompilation::VisitStaNamedProperty( ...@@ -956,6 +989,11 @@ void SerializerForBackgroundCompilation::VisitStaNamedProperty(
ProcessNamedPropertyAccess(iterator, AccessMode::kStore); ProcessNamedPropertyAccess(iterator, AccessMode::kStore);
} }
void SerializerForBackgroundCompilation::VisitStaNamedOwnProperty(
BytecodeArrayIterator* iterator) {
ProcessNamedPropertyAccess(iterator, AccessMode::kStoreInLiteral);
}
void SerializerForBackgroundCompilation::VisitTestIn( void SerializerForBackgroundCompilation::VisitTestIn(
BytecodeArrayIterator* iterator) { BytecodeArrayIterator* iterator) {
Hints const& receiver = environment()->accumulator_hints(); Hints const& receiver = environment()->accumulator_hints();
......
...@@ -189,6 +189,7 @@ namespace compiler { ...@@ -189,6 +189,7 @@ namespace compiler {
V(StaGlobal) \ V(StaGlobal) \
V(StaInArrayLiteral) \ V(StaInArrayLiteral) \
V(StaKeyedProperty) \ V(StaKeyedProperty) \
V(StaNamedOwnProperty) \
V(StaNamedProperty) \ V(StaNamedProperty) \
V(Star) \ V(Star) \
V(TestIn) \ V(TestIn) \
...@@ -270,16 +271,18 @@ using HintsVector = ZoneVector<Hints>; ...@@ -270,16 +271,18 @@ using HintsVector = ZoneVector<Hints>;
// optimizations in the compiler, is copied to the heap broker. // optimizations in the compiler, is copied to the heap broker.
class SerializerForBackgroundCompilation { class SerializerForBackgroundCompilation {
public: public:
SerializerForBackgroundCompilation(JSHeapBroker* broker, Zone* zone, SerializerForBackgroundCompilation(JSHeapBroker* broker,
Handle<JSFunction> closure, CompilationDependencies* dependencies,
Zone* zone, Handle<JSFunction> closure,
bool collect_source_positions); bool collect_source_positions);
Hints Run(); // NOTE: Returns empty for an already-serialized function. Hints Run(); // NOTE: Returns empty for an already-serialized function.
class Environment; class Environment;
private: private:
SerializerForBackgroundCompilation(JSHeapBroker* broker, Zone* zone, SerializerForBackgroundCompilation(JSHeapBroker* broker,
CompilationSubject function, CompilationDependencies* dependencies,
Zone* zone, CompilationSubject function,
base::Optional<Hints> new_target, base::Optional<Hints> new_target,
const HintsVector& arguments, const HintsVector& arguments,
bool collect_source_positions); bool collect_source_positions);
...@@ -311,8 +314,11 @@ class SerializerForBackgroundCompilation { ...@@ -311,8 +314,11 @@ class SerializerForBackgroundCompilation {
GlobalAccessFeedback const* ProcessFeedbackForGlobalAccess(FeedbackSlot slot); GlobalAccessFeedback const* ProcessFeedbackForGlobalAccess(FeedbackSlot slot);
void ProcessFeedbackForKeyedPropertyAccess(FeedbackSlot slot, void ProcessFeedbackForKeyedPropertyAccess(FeedbackSlot slot,
AccessMode mode); AccessMode mode);
ElementAccessFeedback const* ProcessFeedbackMapsForElementAccess(
const MapHandles& maps, AccessMode mode);
void ProcessFeedbackForNamedPropertyAccess(FeedbackSlot slot, void ProcessFeedbackForNamedPropertyAccess(FeedbackSlot slot,
NameRef const& name); NameRef const& name,
AccessMode mode);
void ProcessMapForNamedPropertyAccess(MapRef const& map, NameRef const& name); void ProcessMapForNamedPropertyAccess(MapRef const& map, NameRef const& name);
Hints RunChildSerializer(CompilationSubject function, Hints RunChildSerializer(CompilationSubject function,
...@@ -320,6 +326,7 @@ class SerializerForBackgroundCompilation { ...@@ -320,6 +326,7 @@ class SerializerForBackgroundCompilation {
const HintsVector& arguments, bool with_spread); const HintsVector& arguments, bool with_spread);
JSHeapBroker* broker() const { return broker_; } JSHeapBroker* broker() const { return broker_; }
CompilationDependencies* dependencies() const { return dependencies_; }
Zone* zone() const { return zone_; } Zone* zone() const { return zone_; }
// The following flag is initialized from OptimizedCompilationInfo's // The following flag is initialized from OptimizedCompilationInfo's
// {is_source_positions_enabled}. // {is_source_positions_enabled}.
...@@ -327,6 +334,7 @@ class SerializerForBackgroundCompilation { ...@@ -327,6 +334,7 @@ class SerializerForBackgroundCompilation {
Environment* environment() const { return environment_; } Environment* environment() const { return environment_; }
JSHeapBroker* const broker_; JSHeapBroker* const broker_;
CompilationDependencies* const dependencies_;
Zone* const zone_; Zone* const zone_;
bool const collect_source_positions_; bool const collect_source_positions_;
Environment* const environment_; Environment* const environment_;
......
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