Commit 5a45eab1 authored by Maya Lekova's avatar Maya Lekova Committed by Commit Bot

[turbofan] Remove remaining FastPropertyAt call

Now PropertyAccessBuilder::TryBuildLoadConstantDataField is
heap-access free.

Bug: v8:7790
Change-Id: Ibcc644270325d25da01af7f66e8a26fb57614718
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1725614
Commit-Queue: Maya Lekova <mslekova@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#63024}
parent 7677b2ef
...@@ -2157,7 +2157,8 @@ JSHeapBroker::JSHeapBroker(Isolate* isolate, Zone* broker_zone, ...@@ -2157,7 +2157,8 @@ JSHeapBroker::JSHeapBroker(Isolate* isolate, Zone* broker_zone,
bytecode_analyses_(zone()), bytecode_analyses_(zone()),
ais_for_loading_exec_(zone()), ais_for_loading_exec_(zone()),
ais_for_loading_has_instance_(zone()), ais_for_loading_has_instance_(zone()),
ais_for_loading_then_(zone()) { ais_for_loading_then_(zone()),
property_access_infos_for_load_(zone()) {
// Note that this initialization of the refs_ pointer with the minimal // Note that this initialization of the refs_ pointer with the minimal
// initial capacity is redundant in the normal use case (concurrent // initial capacity is redundant in the normal use case (concurrent
// compilation enabled, standard objects to be serialized), as the map // compilation enabled, standard objects to be serialized), as the map
...@@ -4202,6 +4203,20 @@ PropertyAccessInfo const& JSHeapBroker::CreateAccessInfoForLoadingExec( ...@@ -4202,6 +4203,20 @@ PropertyAccessInfo const& JSHeapBroker::CreateAccessInfoForLoadingExec(
return ais_for_loading_exec_.insert({map, access_info}).first->second; return ais_for_loading_exec_.insert({map, access_info}).first->second;
} }
void JSHeapBroker::StorePropertyAccessInfoForLoad(
MapRef map, NameRef name, PropertyAccessInfo const& access_info) {
MapNameRefPair pair({map, name});
auto it = property_access_infos_for_load_.find(pair);
if (it != property_access_infos_for_load_.end()) {
return;
}
auto inserted_ai =
property_access_infos_for_load_.insert(std::make_pair(pair, access_info));
DCHECK(inserted_ai.second);
USE(inserted_ai);
}
ElementAccessFeedback const* ProcessedFeedback::AsElementAccess() const { ElementAccessFeedback const* ProcessedFeedback::AsElementAccess() const {
CHECK_EQ(kElementAccess, kind()); CHECK_EQ(kElementAccess, kind());
return static_cast<ElementAccessFeedback const*>(this); return static_cast<ElementAccessFeedback const*>(this);
......
...@@ -61,6 +61,24 @@ struct FeedbackSource { ...@@ -61,6 +61,24 @@ struct FeedbackSource {
broker->Trace() << __FUNCTION__ << ": missing " << x << '\n'; \ broker->Trace() << __FUNCTION__ << ": missing " << x << '\n'; \
} while (false) } while (false)
struct MapNameRefPair {
MapRef map;
NameRef name;
struct Hash {
size_t operator()(const MapNameRefPair& pair) const {
return base::hash_combine(pair.map.object().address(),
pair.name.object().address());
}
};
struct Equal {
bool operator()(const MapNameRefPair& lhs,
const MapNameRefPair& rhs) const {
return lhs.map.equals(rhs.map) && lhs.name.equals(rhs.name);
}
};
};
class V8_EXPORT_PRIVATE JSHeapBroker { class V8_EXPORT_PRIVATE JSHeapBroker {
public: public:
JSHeapBroker(Isolate* isolate, Zone* broker_zone, bool tracing_enabled); JSHeapBroker(Isolate* isolate, Zone* broker_zone, bool tracing_enabled);
...@@ -126,6 +144,8 @@ class V8_EXPORT_PRIVATE JSHeapBroker { ...@@ -126,6 +144,8 @@ class V8_EXPORT_PRIVATE JSHeapBroker {
MapRef map, CompilationDependencies* dependencies); MapRef map, CompilationDependencies* dependencies);
void CreateAccessInfoForLoadingThen(MapRef map, void CreateAccessInfoForLoadingThen(MapRef map,
CompilationDependencies* dependencies); CompilationDependencies* dependencies);
void StorePropertyAccessInfoForLoad(MapRef map, NameRef name,
PropertyAccessInfo const& access_info);
std::ostream& Trace(); std::ostream& Trace();
void IncrementTracingIndentation(); void IncrementTracingIndentation();
...@@ -162,6 +182,9 @@ class V8_EXPORT_PRIVATE JSHeapBroker { ...@@ -162,6 +182,9 @@ class V8_EXPORT_PRIVATE JSHeapBroker {
MapToAccessInfos ais_for_loading_exec_; MapToAccessInfos ais_for_loading_exec_;
MapToAccessInfos ais_for_loading_has_instance_; MapToAccessInfos ais_for_loading_has_instance_;
MapToAccessInfos ais_for_loading_then_; MapToAccessInfos ais_for_loading_then_;
ZoneUnorderedMap<MapNameRefPair, PropertyAccessInfo, MapNameRefPair::Hash,
MapNameRefPair::Equal>
property_access_infos_for_load_;
static const size_t kMinimalRefsBucketCount = 8; // must be power of 2 static const size_t kMinimalRefsBucketCount = 8; // must be power of 2
static const size_t kInitialRefsBucketCount = 1024; // must be power of 2 static const size_t kInitialRefsBucketCount = 1024; // must be power of 2
......
...@@ -151,14 +151,6 @@ MachineRepresentation PropertyAccessBuilder::ConvertRepresentation( ...@@ -151,14 +151,6 @@ MachineRepresentation PropertyAccessBuilder::ConvertRepresentation(
Node* PropertyAccessBuilder::TryBuildLoadConstantDataField( Node* PropertyAccessBuilder::TryBuildLoadConstantDataField(
NameRef const& name, PropertyAccessInfo const& access_info, NameRef const& name, PropertyAccessInfo const& access_info,
Node* receiver) { Node* receiver) {
// TODO(neis): Eliminate FastPropertyAt call below by doing the lookup during
// acccess info computation. Requires extra care in the case where the
// receiver is the holder.
AllowCodeDependencyChange dependency_change_;
AllowHandleAllocation handle_allocation_;
AllowHandleDereference handle_dereference_;
AllowHeapAllocation heap_allocation_;
if (!access_info.IsDataConstant()) return nullptr; if (!access_info.IsDataConstant()) return nullptr;
// First, determine if we have a constant holder to load from. // First, determine if we have a constant holder to load from.
...@@ -174,17 +166,21 @@ Node* PropertyAccessBuilder::TryBuildLoadConstantDataField( ...@@ -174,17 +166,21 @@ Node* PropertyAccessBuilder::TryBuildLoadConstantDataField(
MapRef receiver_map = m.Ref(broker()).map(); MapRef receiver_map = m.Ref(broker()).map();
if (std::find_if(access_info.receiver_maps().begin(), if (std::find_if(access_info.receiver_maps().begin(),
access_info.receiver_maps().end(), [&](Handle<Map> map) { access_info.receiver_maps().end(), [&](Handle<Map> map) {
return map.equals(receiver_map.object()); return MapRef(broker(), map).equals(receiver_map);
}) == access_info.receiver_maps().end()) { }) == access_info.receiver_maps().end()) {
// The map of the receiver is not in the feedback, let us bail out. // The map of the receiver is not in the feedback, let us bail out.
return nullptr; return nullptr;
} }
holder = Handle<JSObject>::cast(m.Value()); holder = m.Ref(broker()).AsJSObject().object();
} }
Handle<Object> value = JSObject::FastPropertyAt( JSObjectRef holder_ref(broker(), holder);
holder, access_info.field_representation(), access_info.field_index()); base::Optional<ObjectRef> value = holder_ref.GetOwnDataProperty(
return jsgraph()->Constant(value); access_info.field_representation(), access_info.field_index());
if (!value.has_value()) {
return nullptr;
}
return jsgraph()->Constant(*value);
} }
Node* PropertyAccessBuilder::BuildLoadDataField( Node* PropertyAccessBuilder::BuildLoadDataField(
......
...@@ -402,7 +402,9 @@ class SerializerForBackgroundCompilation { ...@@ -402,7 +402,9 @@ class SerializerForBackgroundCompilation {
KeyedAccessMode const& keyed_mode); KeyedAccessMode const& keyed_mode);
void ProcessFeedbackForPropertyAccess(FeedbackSlot slot, AccessMode mode, void ProcessFeedbackForPropertyAccess(FeedbackSlot slot, AccessMode mode,
base::Optional<NameRef> static_name); base::Optional<NameRef> static_name);
void ProcessMapForNamedPropertyAccess(MapRef const& map, NameRef const& name); PropertyAccessInfo ProcessMapForNamedPropertyAccess(
MapRef const& receiver_map, NameRef const& name, AccessMode mode,
base::Optional<JSObjectRef> receiver = base::nullopt);
void ProcessCreateContext(); void ProcessCreateContext();
enum ContextProcessingMode { enum ContextProcessingMode {
...@@ -2140,11 +2142,8 @@ SerializerForBackgroundCompilation::ProcessFeedbackMapsForNamedAccess( ...@@ -2140,11 +2142,8 @@ SerializerForBackgroundCompilation::ProcessFeedbackMapsForNamedAccess(
ZoneVector<PropertyAccessInfo> access_infos(broker()->zone()); ZoneVector<PropertyAccessInfo> access_infos(broker()->zone());
for (Handle<Map> map : maps) { for (Handle<Map> map : maps) {
MapRef map_ref(broker(), map); MapRef map_ref(broker(), map);
ProcessMapForNamedPropertyAccess(map_ref, name); PropertyAccessInfo info =
AccessInfoFactory access_info_factory(broker(), dependencies(), ProcessMapForNamedPropertyAccess(map_ref, name, mode);
broker()->zone());
PropertyAccessInfo info(access_info_factory.ComputePropertyAccessInfo(
map, name.object(), mode));
access_infos.push_back(info); access_infos.push_back(info);
// TODO(turbofan): We want to take receiver hints into account as well, // TODO(turbofan): We want to take receiver hints into account as well,
...@@ -2231,7 +2230,6 @@ void SerializerForBackgroundCompilation::ProcessKeyedPropertyAccess( ...@@ -2231,7 +2230,6 @@ void SerializerForBackgroundCompilation::ProcessKeyedPropertyAccess(
Hints const& receiver, Hints const& key, FeedbackSlot slot, Hints const& receiver, Hints const& key, FeedbackSlot slot,
AccessMode mode) { AccessMode mode) {
if (BailoutOnUninitialized(slot)) return; if (BailoutOnUninitialized(slot)) return;
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);
...@@ -2261,17 +2259,73 @@ void SerializerForBackgroundCompilation::ProcessKeyedPropertyAccess( ...@@ -2261,17 +2259,73 @@ void SerializerForBackgroundCompilation::ProcessKeyedPropertyAccess(
} }
environment()->accumulator_hints().Clear(); environment()->accumulator_hints().Clear();
ProcessFeedbackForPropertyAccess(slot, mode, base::nullopt);
} }
void SerializerForBackgroundCompilation::ProcessMapForNamedPropertyAccess( PropertyAccessInfo
MapRef const& map, NameRef const& name) { SerializerForBackgroundCompilation::ProcessMapForNamedPropertyAccess(
MapRef const& receiver_map, NameRef const& name, AccessMode mode,
base::Optional<JSObjectRef> receiver) {
// For JSNativeContextSpecialization::ReduceNamedAccess. // For JSNativeContextSpecialization::ReduceNamedAccess.
if (map.IsMapOfCurrentGlobalProxy()) { if (receiver_map.IsMapOfCurrentGlobalProxy()) {
broker()->native_context().global_proxy_object().GetPropertyCell(name, broker()->native_context().global_proxy_object().GetPropertyCell(name,
true); true);
} }
// TODO(mslekova): Compute the property access infos as we do for feedback
// maps, store them somewhere. Add constants to the accumulator. AccessInfoFactory access_info_factory(broker(), dependencies(),
broker()->zone());
PropertyAccessInfo access_info(access_info_factory.ComputePropertyAccessInfo(
receiver_map.object(), name.object(), mode));
// For JSNativeContextSpecialization::InlinePropertySetterCall
// and InlinePropertyGetterCall.
if (access_info.IsAccessorConstant() && !access_info.constant().is_null()) {
if (access_info.constant()->IsJSFunction()) {
// For JSCallReducer::ReduceCallApiFunction.
Handle<SharedFunctionInfo> sfi(
handle(Handle<JSFunction>::cast(access_info.constant())->shared(),
broker()->isolate()));
if (sfi->IsApiFunction()) {
FunctionTemplateInfoRef fti_ref(
broker(), handle(sfi->get_api_func_data(), broker()->isolate()));
if (fti_ref.has_call_code()) fti_ref.SerializeCallCode();
ProcessReceiverMapForApiCall(fti_ref, receiver_map.object());
}
} else {
FunctionTemplateInfoRef fti_ref(
broker(), Handle<FunctionTemplateInfo>::cast(access_info.constant()));
if (fti_ref.has_call_code()) fti_ref.SerializeCallCode();
}
}
// For PropertyAccessBuilder::TryBuildLoadConstantDataField
if (mode == AccessMode::kLoad) {
broker()->StorePropertyAccessInfoForLoad(receiver_map, name, access_info);
if (access_info.IsDataConstant()) {
base::Optional<JSObjectRef> holder;
Handle<JSObject> prototype;
if (access_info.holder().ToHandle(&prototype)) {
holder = JSObjectRef(broker(), prototype);
} else {
CHECK_IMPLIES(receiver.has_value(),
receiver->map().equals(receiver_map));
holder = receiver;
}
if (holder.has_value()) {
base::Optional<ObjectRef> constant(
holder->GetOwnDataProperty(access_info.field_representation(),
access_info.field_index(), true));
if (constant.has_value()) {
environment()->accumulator_hints().AddConstant(constant->object());
}
}
}
}
return access_info;
} }
void SerializerForBackgroundCompilation::VisitLdaKeyedProperty( void SerializerForBackgroundCompilation::VisitLdaKeyedProperty(
...@@ -2287,18 +2341,16 @@ void SerializerForBackgroundCompilation::ProcessNamedPropertyAccess( ...@@ -2287,18 +2341,16 @@ void SerializerForBackgroundCompilation::ProcessNamedPropertyAccess(
Hints const& receiver, NameRef const& name, FeedbackSlot slot, Hints const& receiver, NameRef const& name, FeedbackSlot slot,
AccessMode mode) { AccessMode mode) {
if (BailoutOnUninitialized(slot)) return; if (BailoutOnUninitialized(slot)) return;
ProcessFeedbackForPropertyAccess(slot, mode, name);
for (Handle<Map> map :
GetRelevantReceiverMaps(broker()->isolate(), receiver.maps())) {
ProcessMapForNamedPropertyAccess(MapRef(broker(), map), name);
}
JSGlobalProxyRef global_proxy = JSGlobalProxyRef global_proxy =
broker()->native_context().global_proxy_object(); broker()->native_context().global_proxy_object();
for (Handle<Object> hint : receiver.constants()) { for (Handle<Object> hint : receiver.constants()) {
ObjectRef object(broker(), hint); ObjectRef object(broker(), hint);
if (mode == AccessMode::kLoad && object.IsJSObject()) {
ProcessMapForNamedPropertyAccess(object.AsJSObject().map(), name, mode,
object.AsJSObject());
}
// For JSNativeContextSpecialization::ReduceNamedAccessFromNexus. // For JSNativeContextSpecialization::ReduceNamedAccessFromNexus.
if (object.equals(global_proxy)) { if (object.equals(global_proxy)) {
global_proxy.GetPropertyCell(name, true); global_proxy.GetPropertyCell(name, true);
...@@ -2311,7 +2363,15 @@ void SerializerForBackgroundCompilation::ProcessNamedPropertyAccess( ...@@ -2311,7 +2363,15 @@ void SerializerForBackgroundCompilation::ProcessNamedPropertyAccess(
} }
} }
DCHECK_NE(&environment()->accumulator_hints(), &receiver);
environment()->accumulator_hints().Clear(); environment()->accumulator_hints().Clear();
ProcessFeedbackForPropertyAccess(slot, mode, name);
for (Handle<Map> map :
GetRelevantReceiverMaps(broker()->isolate(), receiver.maps())) {
ProcessMapForNamedPropertyAccess(MapRef(broker(), map), name, mode);
}
} }
void SerializerForBackgroundCompilation::ProcessNamedPropertyAccess( void SerializerForBackgroundCompilation::ProcessNamedPropertyAccess(
......
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