Commit 268dd1e6 authored by Georg Neis's avatar Georg Neis Committed by Commit Bot

[turbofan] Brokerize and serialize for keyed accesses

Bug: v8:7790
Change-Id: Ib3c67e4f038b3eac3f85cd2f3c38501a4b2073f7
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1609792
Commit-Queue: Georg Neis <neis@chromium.org>
Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61577}
parent 1e53bb96
...@@ -279,40 +279,29 @@ base::Optional<ElementAccessInfo> AccessInfoFactory::ComputeElementAccessInfo( ...@@ -279,40 +279,29 @@ base::Optional<ElementAccessInfo> AccessInfoFactory::ComputeElementAccessInfo(
} }
bool AccessInfoFactory::ComputeElementAccessInfos( bool AccessInfoFactory::ComputeElementAccessInfos(
FeedbackNexus nexus, MapHandles const& maps, AccessMode access_mode, ElementAccessFeedback const& processed, AccessMode access_mode,
ZoneVector<ElementAccessInfo>* access_infos) const { ZoneVector<ElementAccessInfo>* access_infos) const {
DCHECK(access_infos->empty());
ProcessedFeedback const* processed =
FLAG_concurrent_inlining
? broker()->GetFeedback(FeedbackSource(nexus))
: broker()->ProcessFeedbackMapsForElementAccess(maps);
if (processed == nullptr) return false;
if (processed->kind() == ProcessedFeedback::kInsufficient) return true;
CHECK_EQ(processed->kind(), ProcessedFeedback::kElementAccess);
ElementAccessFeedback const* feedback =
static_cast<ElementAccessFeedback const*>(processed);
if (access_mode == AccessMode::kLoad || access_mode == AccessMode::kHas) { if (access_mode == AccessMode::kLoad || access_mode == AccessMode::kHas) {
// For polymorphic loads of similar elements kinds (i.e. all tagged or all // 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 // double), always use the "worst case" code without a transition. This is
// much faster than transitioning the elements to the worst case, trading a // much faster than transitioning the elements to the worst case, trading a
// TransitionElementsKind for a CheckMaps, avoiding mutation of the array. // TransitionElementsKind for a CheckMaps, avoiding mutation of the array.
base::Optional<ElementAccessInfo> access_info = base::Optional<ElementAccessInfo> access_info =
ConsolidateElementLoad(*feedback); ConsolidateElementLoad(processed);
if (access_info.has_value()) { if (access_info.has_value()) {
access_infos->push_back(*access_info); access_infos->push_back(*access_info);
return true; return true;
} }
} }
for (Handle<Map> receiver_map : feedback->receiver_maps) { for (Handle<Map> receiver_map : processed.receiver_maps) {
// Compute the element access information. // Compute the element access information.
base::Optional<ElementAccessInfo> access_info = base::Optional<ElementAccessInfo> access_info =
ComputeElementAccessInfo(receiver_map, access_mode); ComputeElementAccessInfo(receiver_map, access_mode);
if (!access_info.has_value()) return false; if (!access_info.has_value()) return false;
// Collect the possible transitions for the {receiver_map}. // Collect the possible transitions for the {receiver_map}.
for (auto transition : feedback->transitions) { for (auto transition : processed.transitions) {
if (transition.second.equals(receiver_map)) { if (transition.second.equals(receiver_map)) {
access_info->AddTransitionSource(transition.first); access_info->AddTransitionSource(transition.first);
} }
......
...@@ -168,7 +168,7 @@ class AccessInfoFactory final { ...@@ -168,7 +168,7 @@ class AccessInfoFactory final {
base::Optional<ElementAccessInfo> ComputeElementAccessInfo( base::Optional<ElementAccessInfo> ComputeElementAccessInfo(
Handle<Map> map, AccessMode access_mode) const; Handle<Map> map, AccessMode access_mode) const;
bool ComputeElementAccessInfos( bool ComputeElementAccessInfos(
FeedbackNexus nexus, MapHandles const& maps, AccessMode access_mode, ElementAccessFeedback const& processed, AccessMode access_mode,
ZoneVector<ElementAccessInfo>* access_infos) const; ZoneVector<ElementAccessInfo>* access_infos) const;
PropertyAccessInfo ComputePropertyAccessInfo(Handle<Map> map, PropertyAccessInfo ComputePropertyAccessInfo(Handle<Map> map,
......
...@@ -3380,14 +3380,6 @@ ProcessedFeedback const* JSHeapBroker::GetFeedback( ...@@ -3380,14 +3380,6 @@ ProcessedFeedback const* JSHeapBroker::GetFeedback(
return it->second; return it->second;
} }
ElementAccessFeedback const* JSHeapBroker::GetElementAccessFeedback(
FeedbackSource const& source) const {
ProcessedFeedback const* feedback = GetFeedback(source);
if (feedback == nullptr) return nullptr;
CHECK_EQ(feedback->kind(), ProcessedFeedback::kElementAccess);
return static_cast<ElementAccessFeedback const*>(feedback);
}
GlobalAccessFeedback const* JSHeapBroker::GetGlobalAccessFeedback( GlobalAccessFeedback const* JSHeapBroker::GetGlobalAccessFeedback(
FeedbackSource const& source) const { FeedbackSource const& source) const {
ProcessedFeedback const* feedback = GetFeedback(source); ProcessedFeedback const* feedback = GetFeedback(source);
...@@ -3496,6 +3488,23 @@ std::ostream& operator<<(std::ostream& os, const ObjectRef& ref) { ...@@ -3496,6 +3488,23 @@ std::ostream& operator<<(std::ostream& os, const ObjectRef& ref) {
return os << ref.data(); return os << ref.data();
} }
base::Optional<NameRef> JSHeapBroker::GetNameFeedback(
FeedbackNexus const& nexus) {
Name raw_name = nexus.GetName();
if (raw_name.is_null()) return base::nullopt;
return NameRef(this, handle(raw_name, isolate()));
}
ElementAccessFeedback const* ProcessedFeedback::AsElementAccess() const {
CHECK_EQ(kElementAccess, kind());
return static_cast<ElementAccessFeedback const*>(this);
}
NamedAccessFeedback const* ProcessedFeedback::AsNamedAccess() const {
CHECK_EQ(kNamedAccess, kind());
return static_cast<NamedAccessFeedback const*>(this);
}
#undef BIMODAL_ACCESSOR #undef BIMODAL_ACCESSOR
#undef BIMODAL_ACCESSOR_B #undef BIMODAL_ACCESSOR_B
#undef BIMODAL_ACCESSOR_C #undef BIMODAL_ACCESSOR_C
......
...@@ -708,11 +708,17 @@ class InternalizedStringRef : public StringRef { ...@@ -708,11 +708,17 @@ class InternalizedStringRef : public StringRef {
Handle<InternalizedString> object() const; Handle<InternalizedString> object() const;
}; };
class ElementAccessFeedback;
class NamedAccessFeedback;
class ProcessedFeedback : public ZoneObject { class ProcessedFeedback : public ZoneObject {
public: public:
enum Kind { kInsufficient, kGlobalAccess, kNamedAccess, kElementAccess }; enum Kind { kInsufficient, kGlobalAccess, kNamedAccess, kElementAccess };
Kind kind() const { return kind_; } Kind kind() const { return kind_; }
ElementAccessFeedback const* AsElementAccess() const;
NamedAccessFeedback const* AsNamedAccess() const;
protected: protected:
explicit ProcessedFeedback(Kind kind) : kind_(kind) {} explicit ProcessedFeedback(Kind kind) : kind_(kind) {}
...@@ -852,8 +858,6 @@ class V8_EXPORT_PRIVATE JSHeapBroker { ...@@ -852,8 +858,6 @@ class V8_EXPORT_PRIVATE JSHeapBroker {
ProcessedFeedback const* GetFeedback(FeedbackSource const& source) const; ProcessedFeedback const* GetFeedback(FeedbackSource const& source) const;
// Convenience wrappers around GetFeedback. // Convenience wrappers around GetFeedback.
ElementAccessFeedback const* GetElementAccessFeedback(
FeedbackSource const& source) const;
GlobalAccessFeedback const* GetGlobalAccessFeedback( GlobalAccessFeedback const* GetGlobalAccessFeedback(
FeedbackSource const& source) const; FeedbackSource const& source) const;
...@@ -863,6 +867,8 @@ class V8_EXPORT_PRIVATE JSHeapBroker { ...@@ -863,6 +867,8 @@ class V8_EXPORT_PRIVATE JSHeapBroker {
GlobalAccessFeedback const* ProcessFeedbackForGlobalAccess( GlobalAccessFeedback const* ProcessFeedbackForGlobalAccess(
FeedbackSource const& source); FeedbackSource const& source);
base::Optional<NameRef> GetNameFeedback(FeedbackNexus const& nexus);
std::ostream& Trace(); std::ostream& Trace();
void IncrementTracingIndentation(); void IncrementTracingIndentation();
void DecrementTracingIndentation(); void DecrementTracingIndentation();
......
...@@ -93,11 +93,17 @@ class V8_EXPORT_PRIVATE JSNativeContextSpecialization final ...@@ -93,11 +93,17 @@ class V8_EXPORT_PRIVATE JSNativeContextSpecialization final
Reduction ReduceJSToObject(Node* node); Reduction ReduceJSToObject(Node* node);
Reduction ReduceElementAccess(Node* node, Node* index, Node* value, Reduction ReduceElementAccess(Node* node, Node* index, Node* value,
FeedbackNexus const& nexus, ElementAccessFeedback const& processed,
MapHandles const& receiver_maps,
AccessMode access_mode, AccessMode access_mode,
KeyedAccessLoadMode load_mode, KeyedAccessLoadMode load_mode,
KeyedAccessStoreMode store_mode); KeyedAccessStoreMode store_mode);
// In the case of non-keyed (named) accesses, pass the name as {static_name}
// and use {nullptr} for {key} (load/store modes are irrelevant).
Reduction ReducePropertyAccessUsingProcessedFeedback(
Node* node, Node* key, base::Optional<NameRef> static_name, Node* value,
FeedbackNexus const& nexus, AccessMode access_mode,
KeyedAccessLoadMode load_mode = STANDARD_LOAD,
KeyedAccessStoreMode store_mode = STANDARD_STORE);
Reduction ReduceKeyedAccess(Node* node, Node* key, Node* value, Reduction ReduceKeyedAccess(Node* node, Node* key, Node* value,
FeedbackNexus const& nexus, FeedbackNexus const& nexus,
AccessMode access_mode, AccessMode access_mode,
...@@ -110,12 +116,6 @@ class V8_EXPORT_PRIVATE JSNativeContextSpecialization final ...@@ -110,12 +116,6 @@ class V8_EXPORT_PRIVATE JSNativeContextSpecialization final
Reduction ReduceNamedAccess(Node* node, Node* value, Reduction ReduceNamedAccess(Node* node, Node* value,
NamedAccessFeedback const& processed, NamedAccessFeedback const& processed,
AccessMode access_mode, Node* key = nullptr); 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,
MapHandles const& receiver_maps,
NameRef const& name, AccessMode access_mode,
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);
......
...@@ -815,9 +815,24 @@ SerializerForBackgroundCompilation::ProcessFeedbackMapsForElementAccess( ...@@ -815,9 +815,24 @@ SerializerForBackgroundCompilation::ProcessFeedbackMapsForElementAccess(
return result; return result;
} }
// Note: We never use the same feedback slot for multiple access modes. NamedAccessFeedback const*
void SerializerForBackgroundCompilation::ProcessFeedbackForKeyedPropertyAccess( SerializerForBackgroundCompilation::ProcessFeedbackMapsForNamedAccess(
FeedbackSlot slot, AccessMode mode) { const MapHandles& maps, AccessMode mode, NameRef const& name) {
ZoneVector<PropertyAccessInfo> access_infos(broker()->zone());
for (Handle<Map> map : 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));
}
DCHECK(!access_infos.empty());
return new (broker()->zone()) NamedAccessFeedback(name, access_infos);
}
void SerializerForBackgroundCompilation::ProcessFeedbackForPropertyAccess(
FeedbackSlot slot, AccessMode mode, base::Optional<NameRef> static_name) {
if (slot.IsInvalid()) return; if (slot.IsInvalid()) return;
if (environment()->function().feedback_vector.is_null()) return; if (environment()->function().feedback_vector.is_null()) return;
...@@ -825,26 +840,32 @@ void SerializerForBackgroundCompilation::ProcessFeedbackForKeyedPropertyAccess( ...@@ -825,26 +840,32 @@ void SerializerForBackgroundCompilation::ProcessFeedbackForKeyedPropertyAccess(
FeedbackSource source(nexus); FeedbackSource source(nexus);
if (broker()->HasFeedback(source)) return; if (broker()->HasFeedback(source)) return;
ProcessedFeedback const* processed = nullptr;
if (nexus.ic_state() == UNINITIALIZED) { if (nexus.ic_state() == UNINITIALIZED) {
processed = new (broker()->zone()) InsufficientFeedback(); broker()->SetFeedback(source,
} else { new (broker()->zone()) InsufficientFeedback());
if (nexus.GetKeyType() == PROPERTY) { return;
CHECK_NE(mode, AccessMode::kStoreInLiteral); }
// TODO(neis): Support named access.
} else { MapHandles maps;
DCHECK_EQ(nexus.GetKeyType(), ELEMENT); if (nexus.ExtractMaps(&maps) == 0) { // Megamorphic.
DCHECK(nexus.GetName().is_null()); broker()->SetFeedback(source, nullptr);
MapHandles maps; return;
if (nexus.ExtractMaps(&maps) != 0) { }
maps = GetRelevantReceiverMaps(broker()->isolate(), maps);
if (maps.empty()) { maps = GetRelevantReceiverMaps(broker()->isolate(), maps);
processed = new (broker()->zone()) InsufficientFeedback(); if (maps.empty()) {
} else { broker()->SetFeedback(source,
processed = ProcessFeedbackMapsForElementAccess(maps, mode); new (broker()->zone()) InsufficientFeedback());
} return;
} }
}
ProcessedFeedback const* processed = nullptr;
base::Optional<NameRef> name =
static_name.has_value() ? static_name : broker()->GetNameFeedback(nexus);
if (name.has_value()) {
processed = ProcessFeedbackMapsForNamedAccess(maps, mode, *name);
} else if (nexus.GetKeyType() == ELEMENT && nexus.ic_state() != MEGAMORPHIC) {
processed = ProcessFeedbackMapsForElementAccess(maps, mode);
} }
broker()->SetFeedback(source, processed); broker()->SetFeedback(source, processed);
} }
...@@ -852,7 +873,7 @@ void SerializerForBackgroundCompilation::ProcessFeedbackForKeyedPropertyAccess( ...@@ -852,7 +873,7 @@ void SerializerForBackgroundCompilation::ProcessFeedbackForKeyedPropertyAccess(
void SerializerForBackgroundCompilation::ProcessKeyedPropertyAccess( void SerializerForBackgroundCompilation::ProcessKeyedPropertyAccess(
Hints const& receiver, Hints const& key, FeedbackSlot slot, Hints const& receiver, Hints const& key, FeedbackSlot slot,
AccessMode mode) { AccessMode mode) {
ProcessFeedbackForKeyedPropertyAccess(slot, mode); ProcessFeedbackForPropertyAccess(slot, mode, base::nullopt);
for (Handle<Object> hint : receiver.constants()) { for (Handle<Object> hint : receiver.constants()) {
ObjectRef receiver_ref(broker(), hint); ObjectRef receiver_ref(broker(), hint);
...@@ -893,43 +914,6 @@ void SerializerForBackgroundCompilation::ProcessMapForNamedPropertyAccess( ...@@ -893,43 +914,6 @@ void SerializerForBackgroundCompilation::ProcessMapForNamedPropertyAccess(
} }
} }
// Note: We never use the same feedback slot for multiple names.
void SerializerForBackgroundCompilation::ProcessFeedbackForNamedPropertyAccess(
FeedbackSlot slot, NameRef const& name, 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 {
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);
}
void SerializerForBackgroundCompilation::VisitLdaKeyedProperty( void SerializerForBackgroundCompilation::VisitLdaKeyedProperty(
BytecodeArrayIterator* iterator) { BytecodeArrayIterator* iterator) {
Hints const& key = environment()->accumulator_hints(); Hints const& key = environment()->accumulator_hints();
...@@ -942,7 +926,7 @@ void SerializerForBackgroundCompilation::VisitLdaKeyedProperty( ...@@ -942,7 +926,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) {
ProcessFeedbackForNamedPropertyAccess(slot, name, mode); ProcessFeedbackForPropertyAccess(slot, mode, name);
for (Handle<Map> map : for (Handle<Map> map :
GetRelevantReceiverMaps(broker()->isolate(), receiver.maps())) { GetRelevantReceiverMaps(broker()->isolate(), receiver.maps())) {
......
...@@ -312,13 +312,12 @@ class SerializerForBackgroundCompilation { ...@@ -312,13 +312,12 @@ class SerializerForBackgroundCompilation {
FeedbackSlot slot, AccessMode mode); FeedbackSlot slot, AccessMode mode);
GlobalAccessFeedback const* ProcessFeedbackForGlobalAccess(FeedbackSlot slot); GlobalAccessFeedback const* ProcessFeedbackForGlobalAccess(FeedbackSlot slot);
void ProcessFeedbackForKeyedPropertyAccess(FeedbackSlot slot, NamedAccessFeedback const* ProcessFeedbackMapsForNamedAccess(
AccessMode mode); const MapHandles& maps, AccessMode mode, NameRef const& name);
ElementAccessFeedback const* ProcessFeedbackMapsForElementAccess( ElementAccessFeedback const* ProcessFeedbackMapsForElementAccess(
const MapHandles& maps, AccessMode mode); const MapHandles& maps, AccessMode mode);
void ProcessFeedbackForNamedPropertyAccess(FeedbackSlot slot, void ProcessFeedbackForPropertyAccess(FeedbackSlot slot, AccessMode mode,
NameRef const& name, base::Optional<NameRef> static_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,
......
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