summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/compilation-dependencies.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/compiler/compilation-dependencies.cc')
-rw-r--r--deps/v8/src/compiler/compilation-dependencies.cc510
1 files changed, 398 insertions, 112 deletions
diff --git a/deps/v8/src/compiler/compilation-dependencies.cc b/deps/v8/src/compiler/compilation-dependencies.cc
index 27720c80ed..ddd2ad807d 100644
--- a/deps/v8/src/compiler/compilation-dependencies.cc
+++ b/deps/v8/src/compiler/compilation-dependencies.cc
@@ -62,6 +62,8 @@ const char* CompilationDependencyKindToString(CompilationDependencyKind kind) {
return names[kind];
}
+class PendingDependencies;
+
} // namespace
class CompilationDependency : public ZoneObject {
@@ -70,25 +72,106 @@ class CompilationDependency : public ZoneObject {
virtual bool IsValid() const = 0;
virtual void PrepareInstall() const {}
- virtual void Install(Handle<Code> code) const = 0;
+ virtual void Install(PendingDependencies* deps) const = 0;
-#ifdef DEBUG
#define V(Name) \
bool Is##Name() const { return kind == k##Name; } \
V8_ALLOW_UNUSED const Name##Dependency* As##Name() const;
DEPENDENCY_LIST(V)
#undef V
-#endif
const char* ToString() const {
return CompilationDependencyKindToString(kind);
}
const CompilationDependencyKind kind;
+
+ private:
+ virtual size_t Hash() const = 0;
+ virtual bool Equals(const CompilationDependency* that) const = 0;
+ friend struct CompilationDependencies::CompilationDependencyHash;
+ friend struct CompilationDependencies::CompilationDependencyEqual;
};
+size_t CompilationDependencies::CompilationDependencyHash::operator()(
+ const CompilationDependency* dep) const {
+ return base::hash_combine(dep->kind, dep->Hash());
+}
+
+bool CompilationDependencies::CompilationDependencyEqual::operator()(
+ const CompilationDependency* lhs, const CompilationDependency* rhs) const {
+ return lhs->kind == rhs->kind && lhs->Equals(rhs);
+}
+
namespace {
+// Dependencies can only be fully deduplicated immediately prior to
+// installation (because PrepareInstall may create the object on which the dep
+// will be installed). We gather and dedupe deps in this class, and install
+// them from here.
+class PendingDependencies final {
+ public:
+ explicit PendingDependencies(Zone* zone) : deps_(zone) {}
+
+ void Register(Handle<HeapObject> object,
+ DependentCode::DependencyGroup group) {
+ deps_[object] |= group;
+ }
+
+ void InstallAll(Isolate* isolate, Handle<Code> code) {
+ if (V8_UNLIKELY(FLAG_predictable)) {
+ InstallAllPredictable(isolate, code);
+ return;
+ }
+
+ // With deduplication done we no longer rely on the object address for
+ // hashing.
+ AllowGarbageCollection yes_gc;
+ for (const auto& o_and_g : deps_) {
+ DependentCode::InstallDependency(isolate, code, o_and_g.first,
+ o_and_g.second);
+ }
+ }
+
+ void InstallAllPredictable(Isolate* isolate, Handle<Code> code) {
+ CHECK(FLAG_predictable);
+ // First, guarantee predictable iteration order.
+ using HandleAndGroup =
+ std::pair<Handle<HeapObject>, DependentCode::DependencyGroups>;
+ std::vector<HandleAndGroup> entries(deps_.begin(), deps_.end());
+
+ std::sort(entries.begin(), entries.end(),
+ [](const HandleAndGroup& lhs, const HandleAndGroup& rhs) {
+ return lhs.first->ptr() < rhs.first->ptr();
+ });
+
+ // With deduplication done we no longer rely on the object address for
+ // hashing.
+ AllowGarbageCollection yes_gc;
+ for (const auto& o_and_g : entries) {
+ DependentCode::InstallDependency(isolate, code, o_and_g.first,
+ o_and_g.second);
+ }
+ }
+
+ private:
+ struct HandleHash {
+ size_t operator()(const Handle<HeapObject>& x) const {
+ return static_cast<size_t>(x->ptr());
+ }
+ };
+ struct HandleEqual {
+ bool operator()(const Handle<HeapObject>& lhs,
+ const Handle<HeapObject>& rhs) const {
+ return lhs.is_identical_to(rhs);
+ }
+ };
+ ZoneUnorderedMap<Handle<HeapObject>, DependentCode::DependencyGroups,
+ HandleHash, HandleEqual>
+ deps_;
+ const DisallowGarbageCollection no_gc_;
+};
+
class InitialMapDependency final : public CompilationDependency {
public:
InitialMapDependency(JSHeapBroker* broker, const JSFunctionRef& function,
@@ -103,16 +186,26 @@ class InitialMapDependency final : public CompilationDependency {
function->initial_map() == *initial_map_.object();
}
- void Install(Handle<Code> code) const override {
+ void Install(PendingDependencies* deps) const override {
SLOW_DCHECK(IsValid());
- DependentCode::InstallDependency(function_.isolate(), code,
- initial_map_.object(),
- DependentCode::kInitialMapChangedGroup);
+ deps->Register(initial_map_.object(),
+ DependentCode::kInitialMapChangedGroup);
}
private:
- JSFunctionRef function_;
- MapRef initial_map_;
+ size_t Hash() const override {
+ ObjectRef::Hash h;
+ return base::hash_combine(h(function_), h(initial_map_));
+ }
+
+ bool Equals(const CompilationDependency* that) const override {
+ const InitialMapDependency* const zat = that->AsInitialMap();
+ return function_.equals(zat->function_) &&
+ initial_map_.equals(zat->initial_map_);
+ }
+
+ const JSFunctionRef function_;
+ const MapRef initial_map_;
};
class PrototypePropertyDependency final : public CompilationDependency {
@@ -143,18 +236,28 @@ class PrototypePropertyDependency final : public CompilationDependency {
if (!function->has_initial_map()) JSFunction::EnsureHasInitialMap(function);
}
- void Install(Handle<Code> code) const override {
+ void Install(PendingDependencies* deps) const override {
SLOW_DCHECK(IsValid());
Handle<JSFunction> function = function_.object();
CHECK(function->has_initial_map());
Handle<Map> initial_map(function->initial_map(), function_.isolate());
- DependentCode::InstallDependency(function_.isolate(), code, initial_map,
- DependentCode::kInitialMapChangedGroup);
+ deps->Register(initial_map, DependentCode::kInitialMapChangedGroup);
}
private:
- JSFunctionRef function_;
- ObjectRef prototype_;
+ size_t Hash() const override {
+ ObjectRef::Hash h;
+ return base::hash_combine(h(function_), h(prototype_));
+ }
+
+ bool Equals(const CompilationDependency* that) const override {
+ const PrototypePropertyDependency* const zat = that->AsPrototypeProperty();
+ return function_.equals(zat->function_) &&
+ prototype_.equals(zat->prototype_);
+ }
+
+ const JSFunctionRef function_;
+ const ObjectRef prototype_;
};
class StableMapDependency final : public CompilationDependency {
@@ -168,15 +271,23 @@ class StableMapDependency final : public CompilationDependency {
// heap state modifications.
return !map_.object()->is_dictionary_map() && map_.object()->is_stable();
}
-
- void Install(Handle<Code> code) const override {
+ void Install(PendingDependencies* deps) const override {
SLOW_DCHECK(IsValid());
- DependentCode::InstallDependency(map_.isolate(), code, map_.object(),
- DependentCode::kPrototypeCheckGroup);
+ deps->Register(map_.object(), DependentCode::kPrototypeCheckGroup);
}
private:
- MapRef map_;
+ size_t Hash() const override {
+ ObjectRef::Hash h;
+ return base::hash_combine(h(map_));
+ }
+
+ bool Equals(const CompilationDependency* that) const override {
+ const StableMapDependency* const zat = that->AsStableMap();
+ return map_.equals(zat->map_);
+ }
+
+ const MapRef map_;
};
class ConstantInDictionaryPrototypeChainDependency final
@@ -197,7 +308,7 @@ class ConstantInDictionaryPrototypeChainDependency final
// starting at |receiver_map_|.
bool IsValid() const override { return !GetHolderIfValid().is_null(); }
- void Install(Handle<Code> code) const override {
+ void Install(PendingDependencies* deps) const override {
SLOW_DCHECK(IsValid());
Isolate* isolate = receiver_map_.isolate();
Handle<JSObject> holder = GetHolderIfValid().ToHandleChecked();
@@ -206,14 +317,12 @@ class ConstantInDictionaryPrototypeChainDependency final
while (map->prototype() != *holder) {
map = handle(map->prototype().map(), isolate);
DCHECK(map->IsJSObjectMap()); // Due to IsValid holding.
- DependentCode::InstallDependency(isolate, code, map,
- DependentCode::kPrototypeCheckGroup);
+ deps->Register(map, DependentCode::kPrototypeCheckGroup);
}
DCHECK(map->prototype().map().IsJSObjectMap()); // Due to IsValid holding.
- DependentCode::InstallDependency(isolate, code,
- handle(map->prototype().map(), isolate),
- DependentCode::kPrototypeCheckGroup);
+ deps->Register(handle(map->prototype().map(), isolate),
+ DependentCode::kPrototypeCheckGroup);
}
private:
@@ -296,10 +405,24 @@ class ConstantInDictionaryPrototypeChainDependency final
return MaybeHandle<JSObject>();
}
- MapRef receiver_map_;
- NameRef property_name_;
- ObjectRef constant_;
- PropertyKind kind_;
+ size_t Hash() const override {
+ ObjectRef::Hash h;
+ return base::hash_combine(h(receiver_map_), h(property_name_), h(constant_),
+ static_cast<int>(kind_));
+ }
+
+ bool Equals(const CompilationDependency* that) const override {
+ const ConstantInDictionaryPrototypeChainDependency* const zat =
+ that->AsConstantInDictionaryPrototypeChain();
+ return receiver_map_.equals(zat->receiver_map_) &&
+ property_name_.equals(zat->property_name_) &&
+ constant_.equals(zat->constant_) && kind_ == zat->kind_;
+ }
+
+ const MapRef receiver_map_;
+ const NameRef property_name_;
+ const ObjectRef constant_;
+ const PropertyKind kind_;
};
class OwnConstantDataPropertyDependency final : public CompilationDependency {
@@ -346,9 +469,23 @@ class OwnConstantDataPropertyDependency final : public CompilationDependency {
return true;
}
- void Install(Handle<Code> code) const override {}
+ void Install(PendingDependencies* deps) const override {}
private:
+ size_t Hash() const override {
+ ObjectRef::Hash h;
+ return base::hash_combine(h(holder_), h(map_), representation_.kind(),
+ index_.bit_field(), h(value_));
+ }
+
+ bool Equals(const CompilationDependency* that) const override {
+ const OwnConstantDataPropertyDependency* const zat =
+ that->AsOwnConstantDataProperty();
+ return holder_.equals(zat->holder_) && map_.equals(zat->map_) &&
+ representation_.Equals(zat->representation_) &&
+ index_ == zat->index_ && value_.equals(zat->value_);
+ }
+
JSHeapBroker* const broker_;
JSObjectRef const holder_;
MapRef const map_;
@@ -403,9 +540,22 @@ class OwnConstantDictionaryPropertyDependency final
return true;
}
- void Install(Handle<Code> code) const override {}
+ void Install(PendingDependencies* deps) const override {}
private:
+ size_t Hash() const override {
+ ObjectRef::Hash h;
+ return base::hash_combine(h(holder_), h(map_), index_.raw_value(),
+ h(value_));
+ }
+
+ bool Equals(const CompilationDependency* that) const override {
+ const OwnConstantDictionaryPropertyDependency* const zat =
+ that->AsOwnConstantDictionaryProperty();
+ return holder_.equals(zat->holder_) && map_.equals(zat->map_) &&
+ index_ == zat->index_ && value_.equals(zat->value_);
+ }
+
JSHeapBroker* const broker_;
JSObjectRef const holder_;
MapRef const map_;
@@ -422,9 +572,20 @@ class ConsistentJSFunctionViewDependency final : public CompilationDependency {
return function_.IsConsistentWithHeapState();
}
- void Install(Handle<Code> code) const override {}
+ void Install(PendingDependencies* deps) const override {}
private:
+ size_t Hash() const override {
+ ObjectRef::Hash h;
+ return base::hash_combine(h(function_));
+ }
+
+ bool Equals(const CompilationDependency* that) const override {
+ const ConsistentJSFunctionViewDependency* const zat =
+ that->AsConsistentJSFunctionView();
+ return function_.equals(zat->function_);
+ }
+
const JSFunctionRef function_;
};
@@ -437,14 +598,23 @@ class TransitionDependency final : public CompilationDependency {
bool IsValid() const override { return !map_.object()->is_deprecated(); }
- void Install(Handle<Code> code) const override {
+ void Install(PendingDependencies* deps) const override {
SLOW_DCHECK(IsValid());
- DependentCode::InstallDependency(map_.isolate(), code, map_.object(),
- DependentCode::kTransitionGroup);
+ deps->Register(map_.object(), DependentCode::kTransitionGroup);
}
private:
- MapRef map_;
+ size_t Hash() const override {
+ ObjectRef::Hash h;
+ return base::hash_combine(h(map_));
+ }
+
+ bool Equals(const CompilationDependency* that) const override {
+ const TransitionDependency* const zat = that->AsTransition();
+ return map_.equals(zat->map_);
+ }
+
+ const MapRef map_;
};
class PretenureModeDependency final : public CompilationDependency {
@@ -458,17 +628,25 @@ class PretenureModeDependency final : public CompilationDependency {
bool IsValid() const override {
return allocation_ == site_.object()->GetAllocationType();
}
-
- void Install(Handle<Code> code) const override {
+ void Install(PendingDependencies* deps) const override {
SLOW_DCHECK(IsValid());
- DependentCode::InstallDependency(
- site_.isolate(), code, site_.object(),
- DependentCode::kAllocationSiteTenuringChangedGroup);
+ deps->Register(site_.object(),
+ DependentCode::kAllocationSiteTenuringChangedGroup);
}
private:
- AllocationSiteRef site_;
- AllocationType allocation_;
+ size_t Hash() const override {
+ ObjectRef::Hash h;
+ return base::hash_combine(h(site_), allocation_);
+ }
+
+ bool Equals(const CompilationDependency* that) const override {
+ const PretenureModeDependency* const zat = that->AsPretenureMode();
+ return site_.equals(zat->site_) && allocation_ == zat->allocation_;
+ }
+
+ const AllocationSiteRef site_;
+ const AllocationType allocation_;
};
class FieldRepresentationDependency final : public CompilationDependency {
@@ -489,7 +667,7 @@ class FieldRepresentationDependency final : public CompilationDependency {
.representation());
}
- void Install(Handle<Code> code) const override {
+ void Install(PendingDependencies* deps) const override {
SLOW_DCHECK(IsValid());
Isolate* isolate = map_.isolate();
Handle<Map> owner(map_.object()->FindFieldOwner(isolate, descriptor_),
@@ -498,8 +676,7 @@ class FieldRepresentationDependency final : public CompilationDependency {
CHECK(representation_.Equals(owner->instance_descriptors(isolate)
.GetDetails(descriptor_)
.representation()));
- DependentCode::InstallDependency(isolate, code, owner,
- DependentCode::kFieldRepresentationGroup);
+ deps->Register(owner, DependentCode::kFieldRepresentationGroup);
}
bool DependsOn(const Handle<Map>& receiver_map) const {
@@ -507,9 +684,22 @@ class FieldRepresentationDependency final : public CompilationDependency {
}
private:
- MapRef map_;
- InternalIndex descriptor_;
- Representation representation_;
+ size_t Hash() const override {
+ ObjectRef::Hash h;
+ return base::hash_combine(h(map_), descriptor_.as_int(),
+ representation_.kind());
+ }
+
+ bool Equals(const CompilationDependency* that) const override {
+ const FieldRepresentationDependency* const zat =
+ that->AsFieldRepresentation();
+ return map_.equals(zat->map_) && descriptor_ == zat->descriptor_ &&
+ representation_.Equals(zat->representation_);
+ }
+
+ const MapRef map_;
+ const InternalIndex descriptor_;
+ const Representation representation_;
};
class FieldTypeDependency final : public CompilationDependency {
@@ -529,7 +719,7 @@ class FieldTypeDependency final : public CompilationDependency {
.GetFieldType(descriptor_);
}
- void Install(Handle<Code> code) const override {
+ void Install(PendingDependencies* deps) const override {
SLOW_DCHECK(IsValid());
Isolate* isolate = map_.isolate();
Handle<Map> owner(map_.object()->FindFieldOwner(isolate, descriptor_),
@@ -537,14 +727,24 @@ class FieldTypeDependency final : public CompilationDependency {
CHECK(!owner->is_deprecated());
CHECK_EQ(*type_.object(),
owner->instance_descriptors(isolate).GetFieldType(descriptor_));
- DependentCode::InstallDependency(isolate, code, owner,
- DependentCode::kFieldTypeGroup);
+ deps->Register(owner, DependentCode::kFieldTypeGroup);
}
private:
- MapRef map_;
- InternalIndex descriptor_;
- ObjectRef type_;
+ size_t Hash() const override {
+ ObjectRef::Hash h;
+ return base::hash_combine(h(map_), descriptor_.as_int(), h(type_));
+ }
+
+ bool Equals(const CompilationDependency* that) const override {
+ const FieldTypeDependency* const zat = that->AsFieldType();
+ return map_.equals(zat->map_) && descriptor_ == zat->descriptor_ &&
+ type_.equals(zat->type_);
+ }
+
+ const MapRef map_;
+ const InternalIndex descriptor_;
+ const ObjectRef type_;
};
class FieldConstnessDependency final : public CompilationDependency {
@@ -564,7 +764,7 @@ class FieldConstnessDependency final : public CompilationDependency {
.constness();
}
- void Install(Handle<Code> code) const override {
+ void Install(PendingDependencies* deps) const override {
SLOW_DCHECK(IsValid());
Isolate* isolate = map_.isolate();
Handle<Map> owner(map_.object()->FindFieldOwner(isolate, descriptor_),
@@ -573,13 +773,22 @@ class FieldConstnessDependency final : public CompilationDependency {
CHECK_EQ(PropertyConstness::kConst, owner->instance_descriptors(isolate)
.GetDetails(descriptor_)
.constness());
- DependentCode::InstallDependency(isolate, code, owner,
- DependentCode::kFieldConstGroup);
+ deps->Register(owner, DependentCode::kFieldConstGroup);
}
private:
- MapRef map_;
- InternalIndex descriptor_;
+ size_t Hash() const override {
+ ObjectRef::Hash h;
+ return base::hash_combine(h(map_), descriptor_.as_int());
+ }
+
+ bool Equals(const CompilationDependency* that) const override {
+ const FieldConstnessDependency* const zat = that->AsFieldConstness();
+ return map_.equals(zat->map_) && descriptor_ == zat->descriptor_;
+ }
+
+ const MapRef map_;
+ const InternalIndex descriptor_;
};
class GlobalPropertyDependency final : public CompilationDependency {
@@ -604,17 +813,26 @@ class GlobalPropertyDependency final : public CompilationDependency {
return type_ == cell->property_details().cell_type() &&
read_only_ == cell->property_details().IsReadOnly();
}
-
- void Install(Handle<Code> code) const override {
+ void Install(PendingDependencies* deps) const override {
SLOW_DCHECK(IsValid());
- DependentCode::InstallDependency(cell_.isolate(), code, cell_.object(),
- DependentCode::kPropertyCellChangedGroup);
+ deps->Register(cell_.object(), DependentCode::kPropertyCellChangedGroup);
}
private:
- PropertyCellRef cell_;
- PropertyCellType type_;
- bool read_only_;
+ size_t Hash() const override {
+ ObjectRef::Hash h;
+ return base::hash_combine(h(cell_), static_cast<int>(type_), read_only_);
+ }
+
+ bool Equals(const CompilationDependency* that) const override {
+ const GlobalPropertyDependency* const zat = that->AsGlobalProperty();
+ return cell_.equals(zat->cell_) && type_ == zat->type_ &&
+ read_only_ == zat->read_only_;
+ }
+
+ const PropertyCellRef cell_;
+ const PropertyCellType type_;
+ const bool read_only_;
};
class ProtectorDependency final : public CompilationDependency {
@@ -626,15 +844,23 @@ class ProtectorDependency final : public CompilationDependency {
Handle<PropertyCell> cell = cell_.object();
return cell->value() == Smi::FromInt(Protectors::kProtectorValid);
}
-
- void Install(Handle<Code> code) const override {
+ void Install(PendingDependencies* deps) const override {
SLOW_DCHECK(IsValid());
- DependentCode::InstallDependency(cell_.isolate(), code, cell_.object(),
- DependentCode::kPropertyCellChangedGroup);
+ deps->Register(cell_.object(), DependentCode::kPropertyCellChangedGroup);
}
private:
- PropertyCellRef cell_;
+ size_t Hash() const override {
+ ObjectRef::Hash h;
+ return base::hash_combine(h(cell_));
+ }
+
+ bool Equals(const CompilationDependency* that) const override {
+ const ProtectorDependency* const zat = that->AsProtector();
+ return cell_.equals(zat->cell_);
+ }
+
+ const PropertyCellRef cell_;
};
class ElementsKindDependency final : public CompilationDependency {
@@ -652,17 +878,25 @@ class ElementsKindDependency final : public CompilationDependency {
: site->GetElementsKind();
return kind_ == kind;
}
-
- void Install(Handle<Code> code) const override {
+ void Install(PendingDependencies* deps) const override {
SLOW_DCHECK(IsValid());
- DependentCode::InstallDependency(
- site_.isolate(), code, site_.object(),
- DependentCode::kAllocationSiteTransitionChangedGroup);
+ deps->Register(site_.object(),
+ DependentCode::kAllocationSiteTransitionChangedGroup);
}
private:
- AllocationSiteRef site_;
- ElementsKind kind_;
+ size_t Hash() const override {
+ ObjectRef::Hash h;
+ return base::hash_combine(h(site_), static_cast<int>(kind_));
+ }
+
+ bool Equals(const CompilationDependency* that) const override {
+ const ElementsKindDependency* const zat = that->AsElementsKind();
+ return site_.equals(zat->site_) && kind_ == zat->kind_;
+ }
+
+ const AllocationSiteRef site_;
+ const ElementsKind kind_;
};
// Only valid if the holder can use direct reads, since validation uses
@@ -686,12 +920,21 @@ class OwnConstantElementDependency final : public CompilationDependency {
return maybe_element.value() == *element_.object();
}
+ void Install(PendingDependencies* deps) const override {}
- void Install(Handle<Code> code) const override {
- // This dependency has no effect after code finalization.
+ private:
+ size_t Hash() const override {
+ ObjectRef::Hash h;
+ return base::hash_combine(h(holder_), index_, h(element_));
+ }
+
+ bool Equals(const CompilationDependency* that) const override {
+ const OwnConstantElementDependency* const zat =
+ that->AsOwnConstantElement();
+ return holder_.equals(zat->holder_) && index_ == zat->index_ &&
+ element_.equals(zat->element_);
}
- private:
const JSObjectRef holder_;
const uint32_t index_;
const ObjectRef element_;
@@ -720,22 +963,34 @@ class InitialMapInstanceSizePredictionDependency final
function_.object()->CompleteInobjectSlackTrackingIfActive();
}
- void Install(Handle<Code> code) const override {
+ void Install(PendingDependencies* deps) const override {
SLOW_DCHECK(IsValid());
DCHECK(
!function_.object()->initial_map().IsInobjectSlackTrackingInProgress());
}
private:
- JSFunctionRef function_;
- int instance_size_;
+ size_t Hash() const override {
+ ObjectRef::Hash h;
+ return base::hash_combine(h(function_), instance_size_);
+ }
+
+ bool Equals(const CompilationDependency* that) const override {
+ const InitialMapInstanceSizePredictionDependency* const zat =
+ that->AsInitialMapInstanceSizePrediction();
+ return function_.equals(zat->function_) &&
+ instance_size_ == zat->instance_size_;
+ }
+
+ const JSFunctionRef function_;
+ const int instance_size_;
};
} // namespace
void CompilationDependencies::RecordDependency(
CompilationDependency const* dependency) {
- if (dependency != nullptr) dependencies_.push_front(dependency);
+ if (dependency != nullptr) dependencies_.insert(dependency);
}
MapRef CompilationDependencies::DependOnInitialMap(
@@ -885,32 +1140,27 @@ V8_INLINE void TraceInvalidCompilationDependency(
}
bool CompilationDependencies::Commit(Handle<Code> code) {
- for (auto dep : dependencies_) {
- if (!dep->IsValid()) {
- if (FLAG_trace_compilation_dependencies) {
- TraceInvalidCompilationDependency(dep);
- }
- dependencies_.clear();
- return false;
- }
- dep->PrepareInstall();
- }
-
- DisallowCodeDependencyChange no_dependency_change;
- for (auto dep : dependencies_) {
- // Check each dependency's validity again right before installing it,
- // because the first iteration above might have invalidated some
- // dependencies. For example, PrototypePropertyDependency::PrepareInstall
- // can call EnsureHasInitialMap, which can invalidate a StableMapDependency
- // on the prototype object's map.
- if (!dep->IsValid()) {
- if (FLAG_trace_compilation_dependencies) {
- TraceInvalidCompilationDependency(dep);
+ if (!PrepareInstall()) return false;
+
+ {
+ PendingDependencies pending_deps(zone_);
+ DisallowCodeDependencyChange no_dependency_change;
+ for (const CompilationDependency* dep : dependencies_) {
+ // Check each dependency's validity again right before installing it,
+ // because the first iteration above might have invalidated some
+ // dependencies. For example, PrototypePropertyDependency::PrepareInstall
+ // can call EnsureHasInitialMap, which can invalidate a
+ // StableMapDependency on the prototype object's map.
+ if (!dep->IsValid()) {
+ if (FLAG_trace_compilation_dependencies) {
+ TraceInvalidCompilationDependency(dep);
+ }
+ dependencies_.clear();
+ return false;
}
- dependencies_.clear();
- return false;
+ dep->Install(&pending_deps);
}
- dep->Install(code);
+ pending_deps.InstallAll(broker_->isolate(), code);
}
// It is even possible that a GC during the above installations invalidated
@@ -941,6 +1191,44 @@ bool CompilationDependencies::Commit(Handle<Code> code) {
return true;
}
+bool CompilationDependencies::PrepareInstall() {
+ if (V8_UNLIKELY(FLAG_predictable)) {
+ return PrepareInstallPredictable();
+ }
+
+ for (auto dep : dependencies_) {
+ if (!dep->IsValid()) {
+ if (FLAG_trace_compilation_dependencies) {
+ TraceInvalidCompilationDependency(dep);
+ }
+ dependencies_.clear();
+ return false;
+ }
+ dep->PrepareInstall();
+ }
+ return true;
+}
+
+bool CompilationDependencies::PrepareInstallPredictable() {
+ CHECK(FLAG_predictable);
+
+ std::vector<const CompilationDependency*> deps(dependencies_.begin(),
+ dependencies_.end());
+ std::sort(deps.begin(), deps.end());
+
+ for (auto dep : deps) {
+ if (!dep->IsValid()) {
+ if (FLAG_trace_compilation_dependencies) {
+ TraceInvalidCompilationDependency(dep);
+ }
+ dependencies_.clear();
+ return false;
+ }
+ dep->PrepareInstall();
+ }
+ return true;
+}
+
namespace {
// This function expects to never see a JSProxy.
@@ -960,7 +1248,6 @@ void DependOnStablePrototypeChain(CompilationDependencies* deps, MapRef map,
} // namespace
-#ifdef DEBUG
#define V(Name) \
const Name##Dependency* CompilationDependency::As##Name() const { \
DCHECK(Is##Name()); \
@@ -968,7 +1255,6 @@ void DependOnStablePrototypeChain(CompilationDependencies* deps, MapRef map,
}
DEPENDENCY_LIST(V)
#undef V
-#endif // DEBUG
void CompilationDependencies::DependOnStablePrototypeChains(
ZoneVector<MapRef> const& receiver_maps, WhereToStart start,