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(
}
bool AccessInfoFactory::ComputeElementAccessInfos(
FeedbackNexus nexus, MapHandles const& maps, AccessMode access_mode,
ElementAccessFeedback const& processed, AccessMode access_mode,
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) {
// For polymorphic loads of similar elements kinds (i.e. all tagged or all
// double), always use the "worst case" code without a transition. This is
// much faster than transitioning the elements to the worst case, trading a
// TransitionElementsKind for a CheckMaps, avoiding mutation of the array.
base::Optional<ElementAccessInfo> access_info =
ConsolidateElementLoad(*feedback);
ConsolidateElementLoad(processed);
if (access_info.has_value()) {
access_infos->push_back(*access_info);
return true;
}
}
for (Handle<Map> receiver_map : feedback->receiver_maps) {
for (Handle<Map> receiver_map : processed.receiver_maps) {
// Compute the element access information.
base::Optional<ElementAccessInfo> access_info =
ComputeElementAccessInfo(receiver_map, access_mode);
if (!access_info.has_value()) return false;
// Collect the possible transitions for the {receiver_map}.
for (auto transition : feedback->transitions) {
for (auto transition : processed.transitions) {
if (transition.second.equals(receiver_map)) {
access_info->AddTransitionSource(transition.first);
}
......
......@@ -168,7 +168,7 @@ class AccessInfoFactory final {
base::Optional<ElementAccessInfo> ComputeElementAccessInfo(
Handle<Map> map, AccessMode access_mode) const;
bool ComputeElementAccessInfos(
FeedbackNexus nexus, MapHandles const& maps, AccessMode access_mode,
ElementAccessFeedback const& processed, AccessMode access_mode,
ZoneVector<ElementAccessInfo>* access_infos) const;
PropertyAccessInfo ComputePropertyAccessInfo(Handle<Map> map,
......
......@@ -3380,14 +3380,6 @@ ProcessedFeedback const* JSHeapBroker::GetFeedback(
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(
FeedbackSource const& source) const {
ProcessedFeedback const* feedback = GetFeedback(source);
......@@ -3496,6 +3488,23 @@ std::ostream& operator<<(std::ostream& os, const ObjectRef& ref) {
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_B
#undef BIMODAL_ACCESSOR_C
......
......@@ -708,11 +708,17 @@ class InternalizedStringRef : public StringRef {
Handle<InternalizedString> object() const;
};
class ElementAccessFeedback;
class NamedAccessFeedback;
class ProcessedFeedback : public ZoneObject {
public:
enum Kind { kInsufficient, kGlobalAccess, kNamedAccess, kElementAccess };
Kind kind() const { return kind_; }
ElementAccessFeedback const* AsElementAccess() const;
NamedAccessFeedback const* AsNamedAccess() const;
protected:
explicit ProcessedFeedback(Kind kind) : kind_(kind) {}
......@@ -852,8 +858,6 @@ class V8_EXPORT_PRIVATE JSHeapBroker {
ProcessedFeedback const* GetFeedback(FeedbackSource const& source) const;
// Convenience wrappers around GetFeedback.
ElementAccessFeedback const* GetElementAccessFeedback(
FeedbackSource const& source) const;
GlobalAccessFeedback const* GetGlobalAccessFeedback(
FeedbackSource const& source) const;
......@@ -863,6 +867,8 @@ class V8_EXPORT_PRIVATE JSHeapBroker {
GlobalAccessFeedback const* ProcessFeedbackForGlobalAccess(
FeedbackSource const& source);
base::Optional<NameRef> GetNameFeedback(FeedbackNexus const& nexus);
std::ostream& Trace();
void IncrementTracingIndentation();
void DecrementTracingIndentation();
......
......@@ -93,11 +93,17 @@ class V8_EXPORT_PRIVATE JSNativeContextSpecialization final
Reduction ReduceJSToObject(Node* node);
Reduction ReduceElementAccess(Node* node, Node* index, Node* value,
FeedbackNexus const& nexus,
MapHandles const& receiver_maps,
ElementAccessFeedback const& processed,
AccessMode access_mode,
KeyedAccessLoadMode load_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,
FeedbackNexus const& nexus,
AccessMode access_mode,
......@@ -110,12 +116,6 @@ class V8_EXPORT_PRIVATE JSNativeContextSpecialization final
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,
MapHandles const& receiver_maps,
NameRef const& name, AccessMode access_mode,
Node* key);
Reduction ReduceGlobalAccess(Node* node, Node* receiver, Node* value,
NameRef const& name, AccessMode access_mode,
Node* key = nullptr);
......
......@@ -815,9 +815,24 @@ SerializerForBackgroundCompilation::ProcessFeedbackMapsForElementAccess(
return result;
}
// Note: We never use the same feedback slot for multiple access modes.
void SerializerForBackgroundCompilation::ProcessFeedbackForKeyedPropertyAccess(
FeedbackSlot slot, AccessMode mode) {
NamedAccessFeedback const*
SerializerForBackgroundCompilation::ProcessFeedbackMapsForNamedAccess(
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 (environment()->function().feedback_vector.is_null()) return;
......@@ -825,26 +840,32 @@ void SerializerForBackgroundCompilation::ProcessFeedbackForKeyedPropertyAccess(
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());
broker()->SetFeedback(source,
new (broker()->zone()) InsufficientFeedback());
return;
}
MapHandles maps;
if (nexus.ExtractMaps(&maps) != 0) {
if (nexus.ExtractMaps(&maps) == 0) { // Megamorphic.
broker()->SetFeedback(source, nullptr);
return;
}
maps = GetRelevantReceiverMaps(broker()->isolate(), maps);
if (maps.empty()) {
processed = new (broker()->zone()) InsufficientFeedback();
} else {
processed = ProcessFeedbackMapsForElementAccess(maps, mode);
}
}
broker()->SetFeedback(source,
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);
}
......@@ -852,7 +873,7 @@ void SerializerForBackgroundCompilation::ProcessFeedbackForKeyedPropertyAccess(
void SerializerForBackgroundCompilation::ProcessKeyedPropertyAccess(
Hints const& receiver, Hints const& key, FeedbackSlot slot,
AccessMode mode) {
ProcessFeedbackForKeyedPropertyAccess(slot, mode);
ProcessFeedbackForPropertyAccess(slot, mode, base::nullopt);
for (Handle<Object> hint : receiver.constants()) {
ObjectRef receiver_ref(broker(), hint);
......@@ -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(
BytecodeArrayIterator* iterator) {
Hints const& key = environment()->accumulator_hints();
......@@ -942,7 +926,7 @@ void SerializerForBackgroundCompilation::VisitLdaKeyedProperty(
void SerializerForBackgroundCompilation::ProcessNamedPropertyAccess(
Hints const& receiver, NameRef const& name, FeedbackSlot slot,
AccessMode mode) {
ProcessFeedbackForNamedPropertyAccess(slot, name, mode);
ProcessFeedbackForPropertyAccess(slot, mode, name);
for (Handle<Map> map :
GetRelevantReceiverMaps(broker()->isolate(), receiver.maps())) {
......
......@@ -312,13 +312,12 @@ class SerializerForBackgroundCompilation {
FeedbackSlot slot, AccessMode mode);
GlobalAccessFeedback const* ProcessFeedbackForGlobalAccess(FeedbackSlot slot);
void ProcessFeedbackForKeyedPropertyAccess(FeedbackSlot slot,
AccessMode mode);
NamedAccessFeedback const* ProcessFeedbackMapsForNamedAccess(
const MapHandles& maps, AccessMode mode, NameRef const& name);
ElementAccessFeedback const* ProcessFeedbackMapsForElementAccess(
const MapHandles& maps, AccessMode mode);
void ProcessFeedbackForNamedPropertyAccess(FeedbackSlot slot,
NameRef const& name,
AccessMode mode);
void ProcessFeedbackForPropertyAccess(FeedbackSlot slot, AccessMode mode,
base::Optional<NameRef> static_name);
void ProcessMapForNamedPropertyAccess(MapRef const& map, NameRef const& name);
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