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,
bytecode_analyses_(zone()),
ais_for_loading_exec_(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
// initial capacity is redundant in the normal use case (concurrent
// compilation enabled, standard objects to be serialized), as the map
......@@ -4202,6 +4203,20 @@ PropertyAccessInfo const& JSHeapBroker::CreateAccessInfoForLoadingExec(
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 {
CHECK_EQ(kElementAccess, kind());
return static_cast<ElementAccessFeedback const*>(this);
......
......@@ -61,6 +61,24 @@ struct FeedbackSource {
broker->Trace() << __FUNCTION__ << ": missing " << x << '\n'; \
} 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 {
public:
JSHeapBroker(Isolate* isolate, Zone* broker_zone, bool tracing_enabled);
......@@ -126,6 +144,8 @@ class V8_EXPORT_PRIVATE JSHeapBroker {
MapRef map, CompilationDependencies* dependencies);
void CreateAccessInfoForLoadingThen(MapRef map,
CompilationDependencies* dependencies);
void StorePropertyAccessInfoForLoad(MapRef map, NameRef name,
PropertyAccessInfo const& access_info);
std::ostream& Trace();
void IncrementTracingIndentation();
......@@ -162,6 +182,9 @@ class V8_EXPORT_PRIVATE JSHeapBroker {
MapToAccessInfos ais_for_loading_exec_;
MapToAccessInfos ais_for_loading_has_instance_;
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 kInitialRefsBucketCount = 1024; // must be power of 2
......
......@@ -151,14 +151,6 @@ MachineRepresentation PropertyAccessBuilder::ConvertRepresentation(
Node* PropertyAccessBuilder::TryBuildLoadConstantDataField(
NameRef const& name, PropertyAccessInfo const& access_info,
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;
// First, determine if we have a constant holder to load from.
......@@ -174,17 +166,21 @@ Node* PropertyAccessBuilder::TryBuildLoadConstantDataField(
MapRef receiver_map = m.Ref(broker()).map();
if (std::find_if(access_info.receiver_maps().begin(),
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()) {
// The map of the receiver is not in the feedback, let us bail out.
return nullptr;
}
holder = Handle<JSObject>::cast(m.Value());
holder = m.Ref(broker()).AsJSObject().object();
}
Handle<Object> value = JSObject::FastPropertyAt(
holder, access_info.field_representation(), access_info.field_index());
return jsgraph()->Constant(value);
JSObjectRef holder_ref(broker(), holder);
base::Optional<ObjectRef> value = holder_ref.GetOwnDataProperty(
access_info.field_representation(), access_info.field_index());
if (!value.has_value()) {
return nullptr;
}
return jsgraph()->Constant(*value);
}
Node* PropertyAccessBuilder::BuildLoadDataField(
......
......@@ -402,7 +402,9 @@ class SerializerForBackgroundCompilation {
KeyedAccessMode const& keyed_mode);
void ProcessFeedbackForPropertyAccess(FeedbackSlot slot, AccessMode mode,
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();
enum ContextProcessingMode {
......@@ -2140,11 +2142,8 @@ SerializerForBackgroundCompilation::ProcessFeedbackMapsForNamedAccess(
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());
PropertyAccessInfo info(access_info_factory.ComputePropertyAccessInfo(
map, name.object(), mode));
PropertyAccessInfo info =
ProcessMapForNamedPropertyAccess(map_ref, name, mode);
access_infos.push_back(info);
// TODO(turbofan): We want to take receiver hints into account as well,
......@@ -2231,7 +2230,6 @@ void SerializerForBackgroundCompilation::ProcessKeyedPropertyAccess(
Hints const& receiver, Hints const& key, FeedbackSlot slot,
AccessMode mode) {
if (BailoutOnUninitialized(slot)) return;
ProcessFeedbackForPropertyAccess(slot, mode, base::nullopt);
for (Handle<Object> hint : receiver.constants()) {
ObjectRef receiver_ref(broker(), hint);
......@@ -2261,17 +2259,73 @@ void SerializerForBackgroundCompilation::ProcessKeyedPropertyAccess(
}
environment()->accumulator_hints().Clear();
ProcessFeedbackForPropertyAccess(slot, mode, base::nullopt);
}
void SerializerForBackgroundCompilation::ProcessMapForNamedPropertyAccess(
MapRef const& map, NameRef const& name) {
PropertyAccessInfo
SerializerForBackgroundCompilation::ProcessMapForNamedPropertyAccess(
MapRef const& receiver_map, NameRef const& name, AccessMode mode,
base::Optional<JSObjectRef> receiver) {
// For JSNativeContextSpecialization::ReduceNamedAccess.
if (map.IsMapOfCurrentGlobalProxy()) {
if (receiver_map.IsMapOfCurrentGlobalProxy()) {
broker()->native_context().global_proxy_object().GetPropertyCell(name,
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(
......@@ -2287,18 +2341,16 @@ void SerializerForBackgroundCompilation::ProcessNamedPropertyAccess(
Hints const& receiver, NameRef const& name, FeedbackSlot slot,
AccessMode mode) {
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 =
broker()->native_context().global_proxy_object();
for (Handle<Object> hint : receiver.constants()) {
ObjectRef object(broker(), hint);
if (mode == AccessMode::kLoad && object.IsJSObject()) {
ProcessMapForNamedPropertyAccess(object.AsJSObject().map(), name, mode,
object.AsJSObject());
}
// For JSNativeContextSpecialization::ReduceNamedAccessFromNexus.
if (object.equals(global_proxy)) {
global_proxy.GetPropertyCell(name, true);
......@@ -2311,7 +2363,15 @@ void SerializerForBackgroundCompilation::ProcessNamedPropertyAccess(
}
}
DCHECK_NE(&environment()->accumulator_hints(), &receiver);
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(
......
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