Commit 4153feb2 authored by Georg Neis's avatar Georg Neis Committed by Commit Bot

[turbofan] Make PropertyAccessInfo carry unrecorded dependencies

Instead of recording dependencies during ComputePropertyAccessInfo(s),
store off-the-record dependencies in the resulting PropertyAccessInfo(s)
and record them when the PropertyAccessInfo(s) are consumed. This will
enable us to do the ComputePropertyAccessInfo(s) during serialization.

Bug: v8:7790
Change-Id: I2a3918eb3bc2c795061ca7969c0053b68a53aea7
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1581610
Commit-Queue: Georg Neis <neis@chromium.org>
Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61051}
parent e4669a9c
This diff is collapsed.
......@@ -7,6 +7,7 @@
#include <iosfwd>
#include "src/compiler/compilation-dependencies.h"
#include "src/compiler/types.h"
#include "src/feedback-vector.h"
#include "src/field-index.h"
......@@ -24,7 +25,6 @@ class Factory;
namespace compiler {
// Forward declarations.
class CompilationDependencies;
class ElementAccessFeedback;
class Type;
class TypeCache;
......@@ -79,6 +79,8 @@ class PropertyAccessInfo final {
MaybeHandle<JSObject> holder);
static PropertyAccessInfo DataField(
PropertyConstness constness, MapHandles const& receiver_maps,
std::vector<CompilationDependencies::Dependency const*>&&
unrecorded_dependencies,
FieldIndex field_index, MachineRepresentation field_representation,
Type field_type, MaybeHandle<Map> field_map = MaybeHandle<Map>(),
MaybeHandle<JSObject> holder = MaybeHandle<JSObject>(),
......@@ -95,6 +97,8 @@ class PropertyAccessInfo final {
bool Merge(PropertyAccessInfo const* that, AccessMode access_mode,
Zone* zone) V8_WARN_UNUSED_RESULT;
void RecordDependencies(CompilationDependencies* dependencies);
bool IsInvalid() const { return kind() == kInvalid; }
bool IsNotFound() const { return kind() == kNotFound; }
bool IsDataConstant() const { return kind() == kDataConstant; }
......@@ -109,7 +113,12 @@ class PropertyAccessInfo final {
bool HasTransitionMap() const { return !transition_map().is_null(); }
Kind kind() const { return kind_; }
MaybeHandle<JSObject> holder() const { return holder_; }
MaybeHandle<JSObject> holder() const {
// This CHECK tries to protect against using the access info without
// recording its dependencies first.
CHECK(unrecorded_dependencies_.empty());
return holder_;
}
MaybeHandle<Map> transition_map() const { return transition_map_; }
Handle<Object> constant() const { return constant_; }
FieldIndex field_index() const { return field_index_; }
......@@ -126,14 +135,17 @@ class PropertyAccessInfo final {
MapHandles const& receiver_maps);
PropertyAccessInfo(Kind kind, MaybeHandle<JSObject> holder,
Handle<Object> constant, MapHandles const& receiver_maps);
PropertyAccessInfo(Kind kind, MaybeHandle<JSObject> holder,
MaybeHandle<Map> transition_map, FieldIndex field_index,
MachineRepresentation field_representation,
Type field_type, MaybeHandle<Map> field_map,
MapHandles const& receiver_maps);
PropertyAccessInfo(
Kind kind, MaybeHandle<JSObject> holder, MaybeHandle<Map> transition_map,
FieldIndex field_index, MachineRepresentation field_representation,
Type field_type, MaybeHandle<Map> field_map,
MapHandles const& receiver_maps,
std::vector<CompilationDependencies::Dependency const*>&& dependencies);
Kind kind_;
MapHandles receiver_maps_;
std::vector<CompilationDependencies::Dependency const*>
unrecorded_dependencies_;
Handle<Object> constant_;
MaybeHandle<Map> transition_map_;
MaybeHandle<JSObject> holder_;
......@@ -159,19 +171,26 @@ class AccessInfoFactory final {
PropertyAccessInfo ComputePropertyAccessInfo(Handle<Map> map,
Handle<Name> name,
AccessMode access_mode) const;
PropertyAccessInfo ComputePropertyAccessInfo(MapHandles const& maps,
Handle<Name> name,
AccessMode access_mode) const;
// Convenience wrapper around {ComputePropertyAccessInfo} for multiple maps.
void ComputePropertyAccessInfos(
MapHandles const& maps, Handle<Name> name, AccessMode access_mode,
ZoneVector<PropertyAccessInfo>* access_infos) const;
// Merge as many of the given {infos} as possible. Return false iff
// any of them was invalid.
// Merge as many of the given {infos} as possible and record any dependencies.
// Return false iff any of them was invalid, in which case no dependencies are
// recorded.
// TODO(neis): Make access_mode part of access info?
bool FinalizePropertyAccessInfos(
ZoneVector<PropertyAccessInfo> infos, AccessMode access_mode,
ZoneVector<PropertyAccessInfo>* result) const;
// Merge the given {infos} to a single one and record any dependencies. If the
// merge is not possible, the result has kind {kInvalid} and no dependencies
// are recorded.
PropertyAccessInfo FinalizePropertyAccessInfosAsOne(
ZoneVector<PropertyAccessInfo> infos, AccessMode access_mode) const;
private:
bool ConsolidateElementLoad(ElementAccessFeedback const& processed,
ElementAccessInfo* access_info) const;
......@@ -188,6 +207,10 @@ class AccessInfoFactory final {
Handle<Map> receiver_map, Handle<Name> name, Handle<Map> map,
MaybeHandle<JSObject> holder, int number, AccessMode access_mode) const;
void MergePropertyAccessInfos(ZoneVector<PropertyAccessInfo> infos,
AccessMode access_mode,
ZoneVector<PropertyAccessInfo>* result) const;
CompilationDependencies* dependencies() const { return dependencies_; }
JSHeapBroker* broker() const { return broker_; }
Isolate* isolate() const { return broker()->isolate(); }
......
This diff is collapsed.
......@@ -107,16 +107,28 @@ class V8_EXPORT_PRIVATE CompilationDependencies : public ZoneObject {
SlackTrackingPrediction DependOnInitialMapInstanceSizePrediction(
const JSFunctionRef& function);
// The methods below allow for gathering dependencies without actually
// recording them. They can be recorded at a later time (or they can be
// ignored). For example,
// DependOnTransition(map);
// is equivalent to:
// RecordDependency(TransitionDependencyOffTheRecord(map));
class Dependency;
void RecordDependency(Dependency const* dependency);
Dependency const* TransitionDependencyOffTheRecord(
const MapRef& target_map) const;
Dependency const* FieldRepresentationDependencyOffTheRecord(
const MapRef& map, int descriptor) const;
Dependency const* FieldTypeDependencyOffTheRecord(const MapRef& map,
int descriptor) const;
// Exposed only for testing purposes.
bool AreValid() const;
// Exposed only because C++.
class Dependency;
private:
Zone* const zone_;
JSHeapBroker* const broker_;
ZoneForwardList<Dependency*> dependencies_;
ZoneForwardList<Dependency const*> dependencies_;
};
} // namespace compiler
......
......@@ -6887,11 +6887,17 @@ Reduction JSCallReducer::ReduceRegExpPrototypeTest(Node* node) {
}
// Compute property access info for "exec" on {resolution}.
AccessInfoFactory access_info_factory(broker(), dependencies(),
graph()->zone());
PropertyAccessInfo ai_exec = access_info_factory.ComputePropertyAccessInfo(
MapHandles(regexp_maps.begin(), regexp_maps.end()),
factory()->exec_string(), AccessMode::kLoad);
PropertyAccessInfo ai_exec;
{
ZoneVector<PropertyAccessInfo> access_infos(graph()->zone());
AccessInfoFactory access_info_factory(broker(), dependencies(),
graph()->zone());
access_info_factory.ComputePropertyAccessInfos(
MapHandles(regexp_maps.begin(), regexp_maps.end()),
factory()->exec_string(), AccessMode::kLoad, &access_infos);
ai_exec = access_info_factory.FinalizePropertyAccessInfosAsOne(
access_infos, AccessMode::kLoad);
}
if (ai_exec.IsInvalid()) return NoChange();
// If "exec" has been modified on {regexp}, we can't do anything.
......
......@@ -406,6 +406,7 @@ Reduction JSNativeContextSpecialization::ReduceJSInstanceOf(Node* node) {
access_info_factory.ComputePropertyAccessInfo(
receiver_map, factory()->has_instance_symbol(), AccessMode::kLoad);
if (access_info.IsInvalid()) return NoChange();
access_info.RecordDependencies(dependencies());
PropertyAccessBuilder access_builder(jsgraph(), broker(), dependencies());
......@@ -725,12 +726,17 @@ Reduction JSNativeContextSpecialization::ReduceJSResolvePromise(Node* node) {
}
// Compute property access info for "then" on {resolution}.
AccessInfoFactory access_info_factory(broker(), dependencies(),
graph()->zone());
PropertyAccessInfo access_info =
access_info_factory.ComputePropertyAccessInfo(
MapHandles(resolution_maps.begin(), resolution_maps.end()),
factory()->then_string(), AccessMode::kLoad);
PropertyAccessInfo access_info;
{
ZoneVector<PropertyAccessInfo> access_infos(graph()->zone());
AccessInfoFactory access_info_factory(broker(), dependencies(),
graph()->zone());
access_info_factory.ComputePropertyAccessInfos(
MapHandles(resolution_maps.begin(), resolution_maps.end()),
factory()->then_string(), AccessMode::kLoad, &access_infos);
access_info = access_info_factory.FinalizePropertyAccessInfosAsOne(
access_infos, AccessMode::kLoad);
}
if (access_info.IsInvalid()) return NoChange();
// We can further optimize the case where {resolution}
......@@ -2459,6 +2465,7 @@ Reduction JSNativeContextSpecialization::ReduceJSStoreDataPropertyInLiteral(
access_info_factory.ComputePropertyAccessInfo(
receiver_map, cached_name.object(), AccessMode::kStoreInLiteral);
if (access_info.IsInvalid()) return NoChange();
access_info.RecordDependencies(dependencies());
Node* receiver = NodeProperties::GetValueInput(node, 0);
Node* effect = NodeProperties::GetEffectInput(node);
......
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