[turbofan] Fully brokerize ReducePropertyAccess
Bug: v8:7790 Change-Id: I6f493d994f49d84020966322d60061567b54c854 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1760808 Commit-Queue: Maya Lekova <mslekova@chromium.org> Reviewed-by: Georg Neis <neis@chromium.org> Cr-Commit-Position: refs/heads/master@{#63265}
This commit is contained in:
parent
d3e6e0466d
commit
69a7e86a5e
@ -592,6 +592,7 @@ class V8_EXPORT_PRIVATE MapRef : public HeapObjectRef {
|
||||
bool supports_fast_array_iteration() const;
|
||||
bool supports_fast_array_resize() const;
|
||||
bool IsMapOfCurrentGlobalProxy() const;
|
||||
bool is_abandoned_prototype_map() const;
|
||||
|
||||
OddballType oddball_type() const;
|
||||
|
||||
@ -624,6 +625,9 @@ class V8_EXPORT_PRIVATE MapRef : public HeapObjectRef {
|
||||
bool IsUnboxedDoubleField(int descriptor_index) const;
|
||||
ObjectRef GetStrongValue(int descriptor_number) const;
|
||||
|
||||
void SerializeRootMap();
|
||||
base::Optional<MapRef> FindRootMap() const;
|
||||
|
||||
// Available after calling JSFunctionRef::Serialize on a function that has
|
||||
// this map as initial map.
|
||||
ObjectRef GetConstructor() const;
|
||||
|
@ -974,6 +974,9 @@ class MapData : public HeapObjectData {
|
||||
bool IsMapOfCurrentGlobalProxy() const {
|
||||
return is_map_of_current_global_proxy_;
|
||||
}
|
||||
bool is_abandoned_prototype_map() const {
|
||||
return is_abandoned_prototype_map_;
|
||||
}
|
||||
|
||||
// Extra information.
|
||||
|
||||
@ -992,6 +995,9 @@ class MapData : public HeapObjectData {
|
||||
return instance_descriptors_;
|
||||
}
|
||||
|
||||
void SerializeRootMap(JSHeapBroker* broker);
|
||||
MapData* FindRootMap() const;
|
||||
|
||||
void SerializeConstructor(JSHeapBroker* broker);
|
||||
ObjectData* GetConstructor() const {
|
||||
CHECK(serialized_constructor_);
|
||||
@ -1031,6 +1037,7 @@ class MapData : public HeapObjectData {
|
||||
bool const supports_fast_array_iteration_;
|
||||
bool const supports_fast_array_resize_;
|
||||
bool const is_map_of_current_global_proxy_;
|
||||
bool const is_abandoned_prototype_map_;
|
||||
|
||||
bool serialized_elements_kind_generalizations_ = false;
|
||||
ZoneVector<MapData*> elements_kind_generalizations_;
|
||||
@ -1047,6 +1054,9 @@ class MapData : public HeapObjectData {
|
||||
bool serialized_prototype_ = false;
|
||||
ObjectData* prototype_ = nullptr;
|
||||
|
||||
bool serialized_root_map_ = false;
|
||||
MapData* root_map_ = nullptr;
|
||||
|
||||
bool serialized_for_element_load_ = false;
|
||||
|
||||
bool serialized_for_element_store_ = false;
|
||||
@ -1155,6 +1165,7 @@ MapData::MapData(JSHeapBroker* broker, ObjectData** storage, Handle<Map> object)
|
||||
SupportsFastArrayResize(broker->isolate(), object)),
|
||||
is_map_of_current_global_proxy_(
|
||||
object->IsMapOfGlobalProxy(broker->isolate()->native_context())),
|
||||
is_abandoned_prototype_map_(object->is_abandoned_prototype_map()),
|
||||
elements_kind_generalizations_(broker->zone()) {}
|
||||
|
||||
JSFunctionData::JSFunctionData(JSHeapBroker* broker, ObjectData** storage,
|
||||
@ -2009,6 +2020,19 @@ void MapData::SerializeOwnDescriptor(JSHeapBroker* broker,
|
||||
<< contents.size() << " total)");
|
||||
}
|
||||
|
||||
void MapData::SerializeRootMap(JSHeapBroker* broker) {
|
||||
if (serialized_root_map_) return;
|
||||
serialized_root_map_ = true;
|
||||
|
||||
TraceScope tracer(broker, this, "MapData::SerializeRootMap");
|
||||
Handle<Map> map = Handle<Map>::cast(object());
|
||||
DCHECK_NULL(root_map_);
|
||||
root_map_ =
|
||||
broker->GetOrCreateData(map->FindRootMap(broker->isolate()))->AsMap();
|
||||
}
|
||||
|
||||
MapData* MapData::FindRootMap() const { return root_map_; }
|
||||
|
||||
void JSObjectData::SerializeRecursiveAsBoilerplate(JSHeapBroker* broker,
|
||||
int depth) {
|
||||
if (serialized_as_boilerplate_) return;
|
||||
@ -3091,6 +3115,7 @@ BIMODAL_ACCESSOR(Map, HeapObject, prototype)
|
||||
BIMODAL_ACCESSOR_C(Map, InstanceType, instance_type)
|
||||
BIMODAL_ACCESSOR(Map, Object, GetConstructor)
|
||||
BIMODAL_ACCESSOR(Map, HeapObject, GetBackPointer)
|
||||
BIMODAL_ACCESSOR_C(Map, bool, is_abandoned_prototype_map)
|
||||
|
||||
#define DEF_NATIVE_CONTEXT_ACCESSOR(type, name) \
|
||||
BIMODAL_ACCESSOR(NativeContext, type, name)
|
||||
@ -3228,6 +3253,26 @@ ObjectRef MapRef::GetStrongValue(int descriptor_index) const {
|
||||
return ObjectRef(broker(), data()->AsMap()->GetStrongValue(descriptor_index));
|
||||
}
|
||||
|
||||
void MapRef::SerializeRootMap() {
|
||||
if (broker()->mode() == JSHeapBroker::kDisabled) return;
|
||||
CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
|
||||
data()->AsMap()->SerializeRootMap(broker());
|
||||
}
|
||||
|
||||
base::Optional<MapRef> MapRef::FindRootMap() const {
|
||||
if (broker()->mode() == JSHeapBroker::kDisabled) {
|
||||
AllowHandleDereference allow_handle_dereference;
|
||||
return MapRef(broker(), handle(object()->FindRootMap(broker()->isolate()),
|
||||
broker()->isolate()));
|
||||
}
|
||||
MapData* map_data = data()->AsMap()->FindRootMap();
|
||||
if (map_data) {
|
||||
return MapRef(broker(), map_data);
|
||||
}
|
||||
TRACE_BROKER_MISSING(broker(), "root map for object " << object());
|
||||
return base::nullopt;
|
||||
}
|
||||
|
||||
void* JSTypedArrayRef::external_pointer() const {
|
||||
if (broker()->mode() == JSHeapBroker::kDisabled) {
|
||||
AllowHandleDereference allow_handle_dereference;
|
||||
@ -4401,7 +4446,10 @@ ElementAccessFeedback const& JSHeapBroker::ProcessFeedbackMapsForElementAccess(
|
||||
MapHandles possible_transition_targets;
|
||||
possible_transition_targets.reserve(maps.size());
|
||||
for (Handle<Map> map : maps) {
|
||||
if (CanInlineElementAccess(MapRef(this, map)) &&
|
||||
MapRef map_ref(this, map);
|
||||
map_ref.SerializeRootMap();
|
||||
|
||||
if (CanInlineElementAccess(map_ref) &&
|
||||
IsFastElementsKind(map->elements_kind()) &&
|
||||
GetInitialFastElementsKind() != map->elements_kind()) {
|
||||
possible_transition_targets.push_back(map);
|
||||
|
@ -1481,18 +1481,16 @@ base::Optional<JSTypedArrayRef> GetTypedArrayConstant(JSHeapBroker* broker,
|
||||
|
||||
void JSNativeContextSpecialization::RemoveImpossibleReceiverMaps(
|
||||
Node* receiver, ZoneVector<Handle<Map>>* receiver_maps) const {
|
||||
// TODO(neis): Decide what to do about this for concurrent inlining.
|
||||
AllowHandleAllocation allow_handle_allocation;
|
||||
AllowHandleDereference allow_handle_dereference;
|
||||
Handle<Map> root_map;
|
||||
if (InferReceiverRootMap(receiver).ToHandle(&root_map)) {
|
||||
base::Optional<MapRef> root_map = InferReceiverRootMap(receiver);
|
||||
if (root_map.has_value()) {
|
||||
DCHECK(!root_map->is_abandoned_prototype_map());
|
||||
Isolate* isolate = this->isolate();
|
||||
receiver_maps->erase(
|
||||
std::remove_if(receiver_maps->begin(), receiver_maps->end(),
|
||||
[root_map, isolate](Handle<Map> map) {
|
||||
return map->is_abandoned_prototype_map() ||
|
||||
map->FindRootMap(isolate) != *root_map;
|
||||
[root_map, this](Handle<Map> map) {
|
||||
MapRef map_ref(broker(), map);
|
||||
return map_ref.is_abandoned_prototype_map() ||
|
||||
(map_ref.FindRootMap().has_value() &&
|
||||
!map_ref.FindRootMap()->equals(*root_map));
|
||||
}),
|
||||
receiver_maps->end());
|
||||
}
|
||||
@ -1826,6 +1824,8 @@ Reduction JSNativeContextSpecialization::ReduceElementLoadFromHeapConstant(
|
||||
Reduction JSNativeContextSpecialization::ReducePropertyAccess(
|
||||
Node* node, Node* key, base::Optional<NameRef> static_name, Node* value,
|
||||
FeedbackSource const& source, AccessMode access_mode) {
|
||||
DisallowHeapAccessIf disallow_heap_access(FLAG_concurrent_inlining);
|
||||
|
||||
DCHECK_EQ(key == nullptr, static_name.has_value());
|
||||
DCHECK(node->opcode() == IrOpcode::kJSLoadProperty ||
|
||||
node->opcode() == IrOpcode::kJSStoreProperty ||
|
||||
@ -3230,21 +3230,24 @@ bool JSNativeContextSpecialization::InferReceiverMaps(
|
||||
return false;
|
||||
}
|
||||
|
||||
MaybeHandle<Map> JSNativeContextSpecialization::InferReceiverRootMap(
|
||||
base::Optional<MapRef> JSNativeContextSpecialization::InferReceiverRootMap(
|
||||
Node* receiver) const {
|
||||
HeapObjectMatcher m(receiver);
|
||||
if (m.HasValue()) {
|
||||
return handle(m.Value()->map().FindRootMap(isolate()), isolate());
|
||||
MapRef map = m.Ref(broker()).map();
|
||||
return map.FindRootMap();
|
||||
} else if (m.IsJSCreate()) {
|
||||
base::Optional<MapRef> initial_map =
|
||||
NodeProperties::GetJSCreateMap(broker(), receiver);
|
||||
if (initial_map.has_value()) {
|
||||
DCHECK_EQ(*initial_map->object(),
|
||||
initial_map->object()->FindRootMap(isolate()));
|
||||
return initial_map->object();
|
||||
if (!initial_map->FindRootMap().has_value()) {
|
||||
return base::nullopt;
|
||||
}
|
||||
DCHECK(initial_map->equals(*initial_map->FindRootMap()));
|
||||
return *initial_map;
|
||||
}
|
||||
}
|
||||
return MaybeHandle<Map>();
|
||||
return base::nullopt;
|
||||
}
|
||||
|
||||
Graph* JSNativeContextSpecialization::graph() const {
|
||||
|
@ -231,7 +231,7 @@ class V8_EXPORT_PRIVATE JSNativeContextSpecialization final
|
||||
|
||||
// Try to infer a root map for the {receiver} independent of the current
|
||||
// program location.
|
||||
MaybeHandle<Map> InferReceiverRootMap(Node* receiver) const;
|
||||
base::Optional<MapRef> InferReceiverRootMap(Node* receiver) const;
|
||||
|
||||
// Checks if we know at compile time that the {receiver} either definitely
|
||||
// has the {prototype} in it's prototype chain, or the {receiver} definitely
|
||||
|
@ -424,7 +424,7 @@ class SerializerForBackgroundCompilation {
|
||||
bool honor_bailout_on_uninitialized);
|
||||
|
||||
PropertyAccessInfo ProcessMapForNamedPropertyAccess(
|
||||
MapRef const& receiver_map, NameRef const& name, AccessMode access_mode,
|
||||
MapRef receiver_map, NameRef const& name, AccessMode access_mode,
|
||||
base::Optional<JSObjectRef> receiver, Hints* new_accumulator_hints);
|
||||
|
||||
void ProcessCreateContext(interpreter::BytecodeArrayIterator* iterator,
|
||||
@ -2245,8 +2245,11 @@ void SerializerForBackgroundCompilation::ProcessUnaryOrBinaryOperation(
|
||||
|
||||
PropertyAccessInfo
|
||||
SerializerForBackgroundCompilation::ProcessMapForNamedPropertyAccess(
|
||||
MapRef const& receiver_map, NameRef const& name, AccessMode access_mode,
|
||||
MapRef receiver_map, NameRef const& name, AccessMode access_mode,
|
||||
base::Optional<JSObjectRef> receiver, Hints* new_accumulator_hints) {
|
||||
// For JSNativeContextSpecialization::InferReceiverRootMap
|
||||
receiver_map.SerializeRootMap();
|
||||
|
||||
// For JSNativeContextSpecialization::ReduceNamedAccess.
|
||||
if (receiver_map.IsMapOfCurrentGlobalProxy()) {
|
||||
broker()->native_context().global_proxy_object().GetPropertyCell(
|
||||
@ -2391,16 +2394,16 @@ void SerializerForBackgroundCompilation::ProcessNamedAccess(
|
||||
Hints receiver, NamedAccessFeedback const& feedback, AccessMode access_mode,
|
||||
Hints* new_accumulator_hints) {
|
||||
for (Handle<Map> map : feedback.AsNamedAccess().maps()) {
|
||||
ProcessMapForNamedPropertyAccess(MapRef(broker(), map), feedback.name(),
|
||||
access_mode, base::nullopt,
|
||||
new_accumulator_hints);
|
||||
MapRef map_ref(broker(), map);
|
||||
ProcessMapForNamedPropertyAccess(map_ref, feedback.name(), access_mode,
|
||||
base::nullopt, new_accumulator_hints);
|
||||
}
|
||||
|
||||
for (Handle<Map> map :
|
||||
GetRelevantReceiverMaps(broker()->isolate(), receiver.maps())) {
|
||||
ProcessMapForNamedPropertyAccess(MapRef(broker(), map), feedback.name(),
|
||||
access_mode, base::nullopt,
|
||||
new_accumulator_hints);
|
||||
MapRef map_ref(broker(), map);
|
||||
ProcessMapForNamedPropertyAccess(map_ref, feedback.name(), access_mode,
|
||||
base::nullopt, new_accumulator_hints);
|
||||
}
|
||||
|
||||
JSGlobalProxyRef global_proxy =
|
||||
@ -2408,9 +2411,10 @@ void SerializerForBackgroundCompilation::ProcessNamedAccess(
|
||||
for (Handle<Object> hint : receiver.constants()) {
|
||||
ObjectRef object(broker(), hint);
|
||||
if (access_mode == AccessMode::kLoad && object.IsJSObject()) {
|
||||
ProcessMapForNamedPropertyAccess(
|
||||
object.AsJSObject().map(), feedback.name(), access_mode,
|
||||
object.AsJSObject(), new_accumulator_hints);
|
||||
MapRef map_ref = object.AsJSObject().map();
|
||||
ProcessMapForNamedPropertyAccess(map_ref, feedback.name(), access_mode,
|
||||
object.AsJSObject(),
|
||||
new_accumulator_hints);
|
||||
}
|
||||
// For JSNativeContextSpecialization::ReduceNamedAccessFromNexus.
|
||||
// TODO(neis): This should be done even if megamorphic.
|
||||
@ -2451,6 +2455,11 @@ void SerializerForBackgroundCompilation::ProcessElementAccess(
|
||||
for (Handle<Object> hint : receiver.constants()) {
|
||||
ObjectRef receiver_ref(broker(), hint);
|
||||
|
||||
// For JSNativeContextSpecialization::InferReceiverRootMap
|
||||
if (receiver_ref.IsHeapObject()) {
|
||||
receiver_ref.AsHeapObject().map().SerializeRootMap();
|
||||
}
|
||||
|
||||
// For JSNativeContextSpecialization::ReduceElementAccess.
|
||||
if (receiver_ref.IsJSTypedArray()) {
|
||||
receiver_ref.AsJSTypedArray().Serialize();
|
||||
@ -2476,6 +2485,12 @@ void SerializerForBackgroundCompilation::ProcessElementAccess(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For JSNativeContextSpecialization::InferReceiverRootMap
|
||||
for (Handle<Map> map : receiver.maps()) {
|
||||
MapRef map_ref(broker(), map);
|
||||
map_ref.SerializeRootMap();
|
||||
}
|
||||
}
|
||||
|
||||
void SerializerForBackgroundCompilation::VisitLdaNamedProperty(
|
||||
|
Loading…
Reference in New Issue
Block a user