[compiler,code] Refactor code dependencies

Prior to this CL we regularly generated high counts of code
dependencies, and installation was not the most efficient.

This CL 1) implements early dependency deduplication and
2) simplifies the way dependencies are persisted on the heap
through DependentCode.

Re 1): we dedupe twice, once based on the CompilationDependency
contents, and again once we know the final target object.

Re 2): Instead of a linked list of weak fixed arrays per
dependency group, store deps in a flat array together with a
bitset of their dependency groups.

See also:
https://docs.google.com/document/d/1B34S1s3Iv6hbquZ93RugD0b-ZKfHEptJ8Fk_YyOvjDk/edit

Bug: v8:12195,v8:12397
Change-Id: I9ab47f6d87b10558194b5de30a36b1122f7e362a
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3283074
Reviewed-by: Dominik Inführ <dinfuehr@chromium.org>
Reviewed-by: Tobias Tebbi <tebbi@chromium.org>
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/main@{#77969}
This commit is contained in:
Jakob Gruber 2021-11-18 13:34:52 +01:00 committed by V8 LUCI CQ
parent 44ba2adb40
commit f6f829b49f
22 changed files with 685 additions and 521 deletions

View File

@ -11429,7 +11429,7 @@ TNode<AllocationSite> CodeStubAssembler::CreateAllocationSiteInFeedbackVector(
// Store an empty fixed array for the code dependency.
StoreObjectFieldRoot(site, AllocationSite::kDependentCodeOffset,
RootIndex::kEmptyWeakFixedArray);
DependentCode::kEmptyDependentCode);
// Link the object to the allocation site list
TNode<ExternalReference> site_list = ExternalConstant(

View File

@ -62,6 +62,8 @@ const char* CompilationDependencyKindToString(CompilationDependencyKind kind) {
return names[kind];
}
class PendingDependencies;
} // namespace
class CompilationDependency : public ZoneObject {
@ -70,25 +72,80 @@ 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) {
// 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);
}
}
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 +160,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 +210,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 +245,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 +282,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 +291,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 +379,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 +443,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 +514,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 +546,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 +572,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 +602,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 +641,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 +650,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 +658,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 +693,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 +701,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 +738,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 +747,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 +787,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 +818,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 +852,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 +894,21 @@ class OwnConstantElementDependency final : public CompilationDependency {
return maybe_element.value() == *element_.object();
}
void Install(Handle<Code> code) const override {
// This dependency has no effect after code finalization.
}
void Install(PendingDependencies* deps) const override {}
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_);
}
const JSObjectRef holder_;
const uint32_t index_;
const ObjectRef element_;
@ -720,22 +937,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(
@ -896,21 +1125,25 @@ bool CompilationDependencies::Commit(Handle<Code> code) {
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);
{
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
@ -960,7 +1193,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 +1200,6 @@ void DependOnStablePrototypeChain(CompilationDependencies* deps, MapRef map,
}
DEPENDENCY_LIST(V)
#undef V
#endif // DEBUG
void CompilationDependencies::DependOnStablePrototypeChains(
ZoneVector<MapRef> const& receiver_maps, WhereToStart start,

View File

@ -159,10 +159,22 @@ class V8_EXPORT_PRIVATE CompilationDependencies : public ZoneObject {
const CompilationDependency* dep, const Handle<Map>& receiver_map);
#endif // DEBUG
struct CompilationDependencyHash {
size_t operator()(const CompilationDependency* dep) const;
};
struct CompilationDependencyEqual {
bool operator()(const CompilationDependency* lhs,
const CompilationDependency* rhs) const;
};
private:
using CompilationDependencySet =
ZoneUnorderedSet<const CompilationDependency*, CompilationDependencyHash,
CompilationDependencyEqual>;
Zone* const zone_;
JSHeapBroker* const broker_;
ZoneForwardList<CompilationDependency const*> dependencies_;
CompilationDependencySet dependencies_;
};
} // namespace compiler

View File

@ -1702,8 +1702,9 @@ Handle<PropertyCell> Factory::NewPropertyCell(Handle<Name> name,
PropertyCell cell = PropertyCell::cast(AllocateRawWithImmortalMap(
PropertyCell::kSize, allocation, *global_property_cell_map()));
DisallowGarbageCollection no_gc;
cell.set_dependent_code(DependentCode::cast(*empty_weak_fixed_array()),
SKIP_WRITE_BARRIER);
cell.set_dependent_code(
DependentCode::empty_dependent_code(ReadOnlyRoots(isolate())),
SKIP_WRITE_BARRIER);
WriteBarrierMode mode = allocation == AllocationType::kYoung
? SKIP_WRITE_BARRIER
: UPDATE_WRITE_BARRIER;
@ -1795,8 +1796,9 @@ Map Factory::InitializeMap(Map map, InstanceType type, int instance_size,
map.set_prototype_validity_cell(Smi::FromInt(Map::kPrototypeChainValid),
SKIP_WRITE_BARRIER);
}
map.set_dependent_code(DependentCode::cast(*empty_weak_fixed_array()),
SKIP_WRITE_BARRIER);
map.set_dependent_code(
DependentCode::empty_dependent_code(ReadOnlyRoots(isolate())),
SKIP_WRITE_BARRIER);
map.set_raw_transitions(MaybeObject::FromSmi(Smi::zero()),
SKIP_WRITE_BARRIER);
map.SetInObjectUnusedPropertyFields(inobject_properties);

View File

@ -189,7 +189,7 @@ AllocationResult Heap::AllocatePartialMap(InstanceType instance_type,
void Heap::FinalizePartialMap(Map map) {
ReadOnlyRoots roots(this);
map.set_dependent_code(DependentCode::cast(roots.empty_weak_fixed_array()));
map.set_dependent_code(DependentCode::empty_dependent_code(roots));
map.set_raw_transitions(MaybeObject::FromSmi(Smi::zero()));
map.SetInstanceDescriptors(isolate(), roots.empty_descriptor_array(), 0);
map.set_prototype(roots.null_value());

View File

@ -74,9 +74,8 @@ void AllocationSite::Initialize() {
set_nested_site(Smi::zero());
set_pretenure_data(0, kRelaxedStore);
set_pretenure_create_count(0);
set_dependent_code(
DependentCode::cast(GetReadOnlyRoots().empty_weak_fixed_array()),
SKIP_WRITE_BARRIER);
set_dependent_code(DependentCode::empty_dependent_code(GetReadOnlyRoots()),
SKIP_WRITE_BARRIER);
}
bool AllocationSite::IsZombie() const {
@ -241,7 +240,7 @@ bool AllocationSite::DigestTransitionFeedback(Handle<AllocationSite> site,
CHECK_NE(to_kind, DICTIONARY_ELEMENTS);
JSObject::TransitionElementsKind(boilerplate, to_kind);
site->dependent_code().DeoptimizeDependentCodeGroup(
DependentCode::kAllocationSiteTransitionChangedGroup);
isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
result = true;
}
}
@ -261,7 +260,7 @@ bool AllocationSite::DigestTransitionFeedback(Handle<AllocationSite> site,
}
site->SetElementsKind(to_kind);
site->dependent_code().DeoptimizeDependentCodeGroup(
DependentCode::kAllocationSiteTransitionChangedGroup);
isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
result = true;
}
}

View File

@ -34,7 +34,7 @@ namespace internal {
OBJECT_CONSTRUCTORS_IMPL(DeoptimizationData, FixedArray)
TQ_OBJECT_CONSTRUCTORS_IMPL(BytecodeArray)
OBJECT_CONSTRUCTORS_IMPL(AbstractCode, HeapObject)
OBJECT_CONSTRUCTORS_IMPL(DependentCode, WeakFixedArray)
OBJECT_CONSTRUCTORS_IMPL(DependentCode, WeakArrayList)
OBJECT_CONSTRUCTORS_IMPL(CodeDataContainer, HeapObject)
NEVER_READ_ONLY_SPACE_IMPL(AbstractCode)
@ -135,47 +135,6 @@ BytecodeArray AbstractCode::GetBytecodeArray() {
return BytecodeArray::cast(*this);
}
DependentCode DependentCode::next_link() {
return DependentCode::cast(Get(kNextLinkIndex)->GetHeapObjectAssumeStrong());
}
void DependentCode::set_next_link(DependentCode next) {
Set(kNextLinkIndex, HeapObjectReference::Strong(next));
}
int DependentCode::flags() { return Smi::ToInt(Get(kFlagsIndex)->ToSmi()); }
void DependentCode::set_flags(int flags) {
Set(kFlagsIndex, MaybeObject::FromObject(Smi::FromInt(flags)));
}
int DependentCode::count() { return CountField::decode(flags()); }
void DependentCode::set_count(int value) {
set_flags(CountField::update(flags(), value));
}
DependentCode::DependencyGroup DependentCode::group() {
return static_cast<DependencyGroup>(GroupField::decode(flags()));
}
void DependentCode::set_object_at(int i, MaybeObject object) {
Set(kCodesStartIndex + i, object);
}
MaybeObject DependentCode::object_at(int i) {
return Get(kCodesStartIndex + i);
}
void DependentCode::clear_at(int i) {
Set(kCodesStartIndex + i,
HeapObjectReference::Strong(GetReadOnlyRoots().undefined_value()));
}
void DependentCode::copy(int from, int to) {
Set(kCodesStartIndex + to, Get(kCodesStartIndex + from));
}
OBJECT_CONSTRUCTORS_IMPL(Code, HeapObject)
NEVER_READ_ONLY_SPACE_IMPL(Code)

View File

@ -763,152 +763,134 @@ void DependentCode::SetDependentCode(Handle<HeapObject> object,
}
}
namespace {
void PrintDependencyGroups(DependentCode::DependencyGroups groups) {
while (groups != 0) {
auto group = static_cast<DependentCode::DependencyGroup>(
1 << base::bits::CountTrailingZeros(static_cast<uint32_t>(groups)));
StdoutStream{} << DependentCode::DependencyGroupName(group);
groups &= ~group;
if (groups != 0) StdoutStream{} << ",";
}
}
} // namespace
void DependentCode::InstallDependency(Isolate* isolate, Handle<Code> code,
Handle<HeapObject> object,
DependencyGroup group) {
DependencyGroups groups) {
if (V8_UNLIKELY(FLAG_trace_compilation_dependencies)) {
StdoutStream{} << "Installing dependency of [" << code->GetHeapObject()
<< "] on [" << object << "] in group ["
<< DependencyGroupName(group) << "]\n";
<< "] on [" << object << "] in groups [";
PrintDependencyGroups(groups);
StdoutStream{} << "]\n";
}
Handle<DependentCode> old_deps(DependentCode::GetDependentCode(object),
isolate);
Handle<DependentCode> new_deps =
InsertWeakCode(isolate, old_deps, group, code);
InsertWeakCode(isolate, old_deps, groups, code);
// Update the list head if necessary.
if (!new_deps.is_identical_to(old_deps))
if (!new_deps.is_identical_to(old_deps)) {
DependentCode::SetDependentCode(object, new_deps);
}
}
Handle<DependentCode> DependentCode::InsertWeakCode(
Isolate* isolate, Handle<DependentCode> entries, DependencyGroup group,
Isolate* isolate, Handle<DependentCode> entries, DependencyGroups groups,
Handle<Code> code) {
if (entries->length() == 0 || entries->group() > group) {
// There is no such group.
return DependentCode::New(isolate, group, code, entries);
}
if (entries->group() < group) {
// The group comes later in the list.
Handle<DependentCode> old_next(entries->next_link(), isolate);
Handle<DependentCode> new_next =
InsertWeakCode(isolate, old_next, group, code);
if (!old_next.is_identical_to(new_next)) {
entries->set_next_link(*new_next);
}
return entries;
}
DCHECK_EQ(group, entries->group());
int count = entries->count();
// Check for existing entry to avoid duplicates.
{
DisallowHeapAllocation no_gc;
HeapObjectReference weak_code_entry =
HeapObjectReference::Weak(ToCodeT(*code));
for (int i = 0; i < count; i++) {
if (entries->object_at(i) == weak_code_entry) return entries;
}
}
if (entries->length() < kCodesStartIndex + count + 1) {
entries = EnsureSpace(isolate, entries);
// Count could have changed, reload it.
count = entries->count();
}
DisallowHeapAllocation no_gc;
HeapObjectReference weak_code_entry =
HeapObjectReference::Weak(ToCodeT(*code));
entries->set_object_at(count, weak_code_entry);
entries->set_count(count + 1);
MaybeObjectHandle code_slot(HeapObjectReference::Weak(ToCodeT(*code)),
isolate);
MaybeObjectHandle group_slot(MaybeObject::FromSmi(Smi::FromInt(groups)),
isolate);
entries = Handle<DependentCode>::cast(
WeakArrayList::AddToEnd(isolate, entries, code_slot, group_slot));
return entries;
}
Handle<DependentCode> DependentCode::New(Isolate* isolate,
DependencyGroup group,
Handle<Code> code,
Handle<DependentCode> next) {
Handle<DependentCode> result =
Handle<DependentCode>::cast(isolate->factory()->NewWeakFixedArray(
kCodesStartIndex + 1, AllocationType::kOld));
result->set_next_link(*next);
result->set_flags(GroupField::encode(group) | CountField::encode(1));
HeapObjectReference weak_code_entry =
HeapObjectReference::Weak(ToCodeT(*code));
result->set_object_at(0, weak_code_entry);
DependencyGroups groups,
Handle<Code> code) {
Handle<DependentCode> result = Handle<DependentCode>::cast(
isolate->factory()->NewWeakArrayList(LengthFor(1), AllocationType::kOld));
result->Set(0, HeapObjectReference::Weak(ToCodeT(*code)));
result->Set(1, Smi::FromInt(groups));
return result;
}
Handle<DependentCode> DependentCode::EnsureSpace(
Isolate* isolate, Handle<DependentCode> entries) {
if (entries->Compact()) return entries;
int capacity = kCodesStartIndex + DependentCode::Grow(entries->count());
int grow_by = capacity - entries->length();
return Handle<DependentCode>::cast(
isolate->factory()->CopyWeakFixedArrayAndGrow(entries, grow_by));
}
bool DependentCode::Compact() {
int old_count = count();
int new_count = 0;
for (int i = 0; i < old_count; i++) {
MaybeObject obj = object_at(i);
if (!obj->IsCleared()) {
if (i != new_count) {
copy(i, new_count);
}
new_count++;
}
}
set_count(new_count);
for (int i = new_count; i < old_count; i++) {
clear_at(i);
}
return new_count < old_count;
}
bool DependentCode::MarkCodeForDeoptimization(
DependentCode::DependencyGroup group) {
if (this->length() == 0 || this->group() > group) {
// There is no such group.
return false;
}
if (this->group() < group) {
// The group comes later in the list.
return next_link().MarkCodeForDeoptimization(group);
}
DCHECK_EQ(group, this->group());
DisallowGarbageCollection no_gc_scope;
// Mark all the code that needs to be deoptimized.
bool marked = false;
int count = this->count();
for (int i = 0; i < count; i++) {
MaybeObject obj = object_at(i);
if (obj->IsCleared()) continue;
DependentCode::DependencyGroups groups) {
DisallowGarbageCollection no_gc;
int len = length();
if (len == 0) return false;
// We compact during traversal, thus use a somewhat custom loop construct:
//
// - Loop back-to-front s.t. trailing deoptimized entries can simply drop off
// the back of the list.
// - Any cleared or deoptimized slots are filled from the back of the list.
bool marked_something = false;
int i = len - kSlotsPerEntry;
while (i >= 0) {
MaybeObject obj = Get(i + kCodeSlotOffset);
if (obj->IsCleared()) {
len = FillEntryFromBack(i, len);
i -= kSlotsPerEntry;
continue;
}
if ((Get(i + kGroupsSlotOffset).ToSmi().value() & groups) == 0) {
i -= kSlotsPerEntry;
continue;
}
// TODO(v8:11880): avoid roundtrips between cdc and code.
Code code = FromCodeT(CodeT::cast(obj->GetHeapObjectAssumeWeak()));
if (!code.marked_for_deoptimization()) {
code.SetMarkedForDeoptimization(DependencyGroupName(group));
marked = true;
code.SetMarkedForDeoptimization("code dependencies");
marked_something = true;
}
len = FillEntryFromBack(i, len);
i -= kSlotsPerEntry;
}
for (int i = 0; i < count; i++) {
clear_at(i);
set_length(len);
return marked_something;
}
int DependentCode::FillEntryFromBack(int index, int length) {
DCHECK_EQ(index % 2, 0);
DCHECK_EQ(length % 2, 0);
for (int i = length - kSlotsPerEntry; i > index; i -= kSlotsPerEntry) {
MaybeObject obj = Get(i + kCodeSlotOffset);
if (obj->IsCleared()) continue;
Set(index + kCodeSlotOffset, obj);
Set(index + kGroupsSlotOffset, Get(i + kGroupsSlotOffset),
SKIP_WRITE_BARRIER);
return i;
}
set_count(0);
return marked;
return index; // No non-cleared entry found.
}
void DependentCode::DeoptimizeDependentCodeGroup(
DependentCode::DependencyGroup group) {
Isolate* isolate, DependentCode::DependencyGroups groups) {
DisallowGarbageCollection no_gc_scope;
bool marked = MarkCodeForDeoptimization(group);
if (marked) {
bool marked_something = MarkCodeForDeoptimization(groups);
if (marked_something) {
DCHECK(AllowCodeDependencyChange::IsAllowed());
// TODO(11527): pass Isolate as an argument.
Deoptimizer::DeoptimizeMarkedCode(GetIsolateFromWritableObject(*this));
Deoptimizer::DeoptimizeMarkedCode(isolate);
}
}
// static
DependentCode DependentCode::empty_dependent_code(const ReadOnlyRoots& roots) {
return DependentCode::cast(roots.empty_weak_array_list());
}
void Code::SetMarkedForDeoptimization(const char* reason) {
set_marked_for_deoptimization(true);
Deoptimizer::TraceMarkForDeoptimization(*this, reason);

View File

@ -764,34 +764,26 @@ class AbstractCode : public HeapObject {
inline ByteArray SourcePositionTableInternal();
};
// Dependent code is a singly linked list of weak fixed arrays. Each array
// contains weak pointers to code objects for one dependent group. The suffix of
// the array can be filled with the undefined value if the number of codes is
// less than the length of the array.
// Dependent code is conceptually the list of {Code, DependencyGroup} tuples
// associated with an object, where the dependency group is a reason that could
// lead to a deopt of the corresponding code.
//
// +------+-----------------+--------+--------+-----+--------+-----------+-----+
// | next | count & group 1 | code 1 | code 2 | ... | code n | undefined | ... |
// +------+-----------------+--------+--------+-----+--------+-----------+-----+
// |
// V
// +------+-----------------+--------+--------+-----+--------+-----------+-----+
// | next | count & group 2 | code 1 | code 2 | ... | code m | undefined | ... |
// +------+-----------------+--------+--------+-----+--------+-----------+-----+
// |
// V
// empty_weak_fixed_array()
// Implementation details: DependentCode is a weak array list containing
// entries, where each entry consists of a (weak) Code object and the
// DependencyGroups bitset as a Smi.
//
// The list of weak fixed arrays is ordered by dependency groups.
class DependentCode : public WeakFixedArray {
// Note the underlying weak array list currently never shrinks physically (the
// contents may shrink).
// TODO(jgruber): Consider adding physical shrinking.
class DependentCode : public WeakArrayList {
public:
DECL_CAST(DependentCode)
enum DependencyGroup {
// Group of code that embed a transition to this map, and depend on being
// deoptimized when the transition is replaced by a new version.
kTransitionGroup,
// Group of code that omit run-time prototype checks for prototypes
// Group of code objects that embed a transition to this map, and depend on
// being deoptimized when the transition is replaced by a new version.
kTransitionGroup = 1 << 0,
// Group of code objects that omit run-time prototype checks for prototypes
// described by this map. The group is deoptimized whenever the following
// conditions hold, possibly invalidating the assumptions embedded in the
// code:
@ -800,89 +792,77 @@ class DependentCode : public WeakFixedArray {
// b) A dictionary-mode prototype described by this map changes shape, the
// const-ness of one of its properties changes, or its [[Prototype]]
// changes (only the latter causes a transition).
kPrototypeCheckGroup,
// Group of code that depends on global property values in property cells
// not being changed.
kPropertyCellChangedGroup,
// Group of code that omit run-time checks for field(s) introduced by
// this map, i.e. for the field type.
kFieldTypeGroup,
kFieldConstGroup,
kFieldRepresentationGroup,
// Group of code that omit run-time type checks for initial maps of
kPrototypeCheckGroup = 1 << 1,
// Group of code objects that depends on global property values in property
// cells not being changed.
kPropertyCellChangedGroup = 1 << 2,
// Group of code objects that omit run-time checks for field(s) introduced
// by this map, i.e. for the field type.
kFieldTypeGroup = 1 << 3,
kFieldConstGroup = 1 << 4,
kFieldRepresentationGroup = 1 << 5,
// Group of code objects that omit run-time type checks for initial maps of
// constructors.
kInitialMapChangedGroup,
// Group of code that depends on tenuring information in AllocationSites
// not being changed.
kAllocationSiteTenuringChangedGroup,
// Group of code that depends on element transition information in
kInitialMapChangedGroup = 1 << 6,
// Group of code objects that depends on tenuring information in
// AllocationSites not being changed.
kAllocationSiteTransitionChangedGroup
kAllocationSiteTenuringChangedGroup = 1 << 7,
// Group of code objects that depends on element transition information in
// AllocationSites not being changed.
kAllocationSiteTransitionChangedGroup = 1 << 8,
// IMPORTANT: The last bit must fit into a Smi, i.e. into 31 bits.
};
using DependencyGroups = base::Flags<DependencyGroup, uint32_t>;
// Register a dependency of {code} on {object}, of the kind given by {group}.
static const char* DependencyGroupName(DependencyGroup group);
// Register a dependency of {code} on {object}, of the kinds given by
// {groups}.
V8_EXPORT_PRIVATE static void InstallDependency(Isolate* isolate,
Handle<Code> code,
Handle<HeapObject> object,
DependencyGroup group);
DependencyGroups groups);
void DeoptimizeDependentCodeGroup(DependencyGroup group);
void DeoptimizeDependentCodeGroup(Isolate* isolate, DependencyGroups groups);
bool MarkCodeForDeoptimization(DependencyGroup group);
bool MarkCodeForDeoptimization(DependencyGroups groups);
// The following low-level accessors are exposed only for tests.
inline DependencyGroup group();
inline MaybeObject object_at(int i);
inline int count();
inline DependentCode next_link();
V8_EXPORT_PRIVATE static DependentCode empty_dependent_code(
const ReadOnlyRoots& roots);
static constexpr RootIndex kEmptyDependentCode =
RootIndex::kEmptyWeakArrayList;
// Constants exposed for tests.
static constexpr int kSlotsPerEntry = 2; // {code: weak Code, groups: Smi}.
static constexpr int kCodeSlotOffset = 0;
static constexpr int kGroupsSlotOffset = 1;
private:
static const char* DependencyGroupName(DependencyGroup group);
// Get/Set {object}'s {DependentCode}.
static DependentCode GetDependentCode(Handle<HeapObject> object);
static void SetDependentCode(Handle<HeapObject> object,
Handle<DependentCode> dep);
static Handle<DependentCode> New(Isolate* isolate, DependencyGroup group,
Handle<Code> code,
Handle<DependentCode> next);
static Handle<DependentCode> EnsureSpace(Isolate* isolate,
Handle<DependentCode> entries);
static Handle<DependentCode> New(Isolate* isolate, DependencyGroups groups,
Handle<Code> code);
static Handle<DependentCode> InsertWeakCode(Isolate* isolate,
Handle<DependentCode> entries,
DependencyGroup group,
DependencyGroups groups,
Handle<Code> code);
// Compact by removing cleared weak cells and return true if there was
// any cleared weak cell.
bool Compact();
// Fills the given entry with the last non-cleared entry in this list, and
// returns the new length after the last non-cleared entry has been moved.
int FillEntryFromBack(int index, int length);
static int Grow(int number_of_entries) {
if (number_of_entries < 5) return number_of_entries + 1;
return number_of_entries * 5 / 4;
static constexpr int LengthFor(int number_of_entries) {
return number_of_entries * kSlotsPerEntry;
}
static const int kGroupCount = kAllocationSiteTransitionChangedGroup + 1;
static const int kNextLinkIndex = 0;
static const int kFlagsIndex = 1;
static const int kCodesStartIndex = 2;
inline void set_next_link(DependentCode next);
inline void set_count(int value);
inline void set_object_at(int i, MaybeObject object);
inline void clear_at(int i);
inline void copy(int from, int to);
inline int flags();
inline void set_flags(int flags);
using GroupField = base::BitField<int, 0, 5>;
using CountField = base::BitField<int, 5, 27>;
STATIC_ASSERT(kGroupCount <= GroupField::kMax + 1);
OBJECT_CONSTRUCTORS(DependentCode, WeakFixedArray);
OBJECT_CONSTRUCTORS(DependentCode, WeakArrayList);
};
DEFINE_OPERATORS_FOR_FLAGS(DependentCode::DependencyGroups)
// BytecodeArray represents a sequence of interpreter bytecodes.
class BytecodeArray
: public TorqueGeneratedBytecodeArray<BytecodeArray, FixedArrayBase> {

View File

@ -42,6 +42,8 @@ class FieldIndex final {
int offset() const { return OffsetBits::decode(bit_field_); }
uint64_t bit_field() const { return bit_field_; }
// Zero-indexed from beginning of the object.
int index() const {
DCHECK(IsAligned(offset(), kTaggedSize));

View File

@ -489,6 +489,10 @@ void WeakArrayList::Set(int index, MaybeObject value, WriteBarrierMode mode) {
set_objects(index, value, mode);
}
void WeakArrayList::Set(int index, Smi value) {
Set(index, MaybeObject::FromSmi(value), SKIP_WRITE_BARRIER);
}
MaybeObjectSlot WeakArrayList::data_start() {
return RawMaybeWeakField(kObjectsOffset);
}

View File

@ -367,6 +367,7 @@ class WeakArrayList
// instead.
inline void Set(int index, MaybeObject value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
inline void Set(int index, Smi value);
static constexpr int SizeForCapacity(int capacity) {
return SizeFor(capacity);

View File

@ -408,7 +408,7 @@ void SetInstancePrototype(Isolate* isolate, Handle<JSFunction> function,
// Deoptimize all code that embeds the previous initial map.
initial_map->dependent_code().DeoptimizeDependentCodeGroup(
DependentCode::kInitialMapChangedGroup);
isolate, DependentCode::kInitialMapChangedGroup);
} else {
// Put the value in the initial map field until an initial map is
// needed. At that point, a new initial map is created and the

View File

@ -4743,8 +4743,10 @@ void InvalidateOnePrototypeValidityCellInternal(Map map) {
// of the validity cell is not used. Therefore, we always trigger the de-opt
// here, even if the cell was already invalid.
if (V8_DICT_PROPERTY_CONST_TRACKING_BOOL && map.is_dictionary_map()) {
// TODO(11527): pass Isolate as an argument.
Isolate* isolate = GetIsolateFromWritableObject(map);
map.dependent_code().DeoptimizeDependentCodeGroup(
DependentCode::kPrototypeCheckGroup);
isolate, DependentCode::kPrototypeCheckGroup);
}
}

View File

@ -666,7 +666,7 @@ void Map::NotifyLeafMapLayoutChange(Isolate* isolate) {
if (is_stable()) {
mark_unstable();
dependent_code().DeoptimizeDependentCodeGroup(
DependentCode::kPrototypeCheckGroup);
isolate, DependentCode::kPrototypeCheckGroup);
}
}

View File

@ -1192,20 +1192,19 @@ void MapUpdater::GeneralizeField(Isolate* isolate, Handle<Map> map,
UpdateFieldType(isolate, field_owner, modify_index, name, new_constness,
new_representation, wrapped_type);
DependentCode::DependencyGroups dep_groups;
if (new_constness != old_constness) {
field_owner->dependent_code().DeoptimizeDependentCodeGroup(
DependentCode::kFieldConstGroup);
dep_groups |= DependentCode::kFieldConstGroup;
}
if (!new_field_type->Equals(*old_field_type)) {
field_owner->dependent_code().DeoptimizeDependentCodeGroup(
DependentCode::kFieldTypeGroup);
dep_groups |= DependentCode::kFieldTypeGroup;
}
if (!new_representation.Equals(old_representation)) {
dep_groups |= DependentCode::kFieldRepresentationGroup;
}
if (!new_representation.Equals(old_representation)) {
field_owner->dependent_code().DeoptimizeDependentCodeGroup(
DependentCode::kFieldRepresentationGroup);
}
field_owner->dependent_code().DeoptimizeDependentCodeGroup(isolate,
dep_groups);
if (FLAG_trace_generalization) {
PrintGeneralization(

View File

@ -562,7 +562,7 @@ void Map::DeprecateTransitionTree(Isolate* isolate) {
LOG(isolate, MapEvent("Deprecate", handle(*this, isolate), Handle<Map>()));
}
dependent_code().DeoptimizeDependentCodeGroup(
DependentCode::kTransitionGroup);
isolate, DependentCode::kTransitionGroup);
NotifyLeafMapLayoutChange(isolate);
}
@ -1854,7 +1854,7 @@ Handle<Map> Map::TransitionToDataProperty(Isolate* isolate, Handle<Map> map,
// Deoptimize all code that embeds the previous initial map.
initial_map->dependent_code().DeoptimizeDependentCodeGroup(
DependentCode::kInitialMapChangedGroup);
isolate, DependentCode::kInitialMapChangedGroup);
if (!result->EquivalentToForNormalization(*map,
CLEAR_INOBJECT_PROPERTIES)) {
result =

View File

@ -299,32 +299,21 @@ DEF_GETTER(HeapObject, IsDeoptimizationData, bool) {
}
DEF_GETTER(HeapObject, IsHandlerTable, bool) {
if (!IsFixedArrayExact(cage_base)) return false;
// There's actually no way to see the difference between a fixed array and
// a handler table array.
return true;
return IsFixedArrayExact(cage_base);
}
DEF_GETTER(HeapObject, IsTemplateList, bool) {
if (!IsFixedArrayExact(cage_base)) return false;
// There's actually no way to see the difference between a fixed array and
// a template list.
if (FixedArray::cast(*this).length() < 1) return false;
return true;
}
DEF_GETTER(HeapObject, IsDependentCode, bool) {
if (!IsWeakFixedArray(cage_base)) return false;
// There's actually no way to see the difference between a weak fixed array
// and a dependent codes array.
return true;
return IsWeakArrayList(cage_base);
}
DEF_GETTER(HeapObject, IsOSROptimizedCodeCache, bool) {
if (!IsWeakFixedArray(cage_base)) return false;
// There's actually no way to see the difference between a weak fixed array
// and a osr optimized code cache.
return true;
return IsWeakFixedArray(cage_base);
}
DEF_GETTER(HeapObject, IsAbstractCode, bool) {

View File

@ -6469,8 +6469,10 @@ void PropertyCell::ClearAndInvalidate(ReadOnlyRoots roots) {
PropertyDetails details = property_details();
details = details.set_cell_type(PropertyCellType::kConstant);
Transition(details, roots.the_hole_value_handle());
// TODO(11527): pass Isolate as an argument.
Isolate* isolate = GetIsolateFromWritableObject(*this);
dependent_code().DeoptimizeDependentCodeGroup(
DependentCode::kPropertyCellChangedGroup);
isolate, DependentCode::kPropertyCellChangedGroup);
}
// static
@ -6567,7 +6569,7 @@ Handle<PropertyCell> PropertyCell::PrepareForAndSetValue(
if (original_details.cell_type() != new_type ||
(!original_details.IsReadOnly() && details.IsReadOnly())) {
cell->dependent_code().DeoptimizeDependentCodeGroup(
DependentCode::kPropertyCellChangedGroup);
isolate, DependentCode::kPropertyCellChangedGroup);
}
}
return cell;
@ -6578,8 +6580,10 @@ void PropertyCell::InvalidateProtector() {
if (value() != Smi::FromInt(Protectors::kProtectorInvalid)) {
DCHECK_EQ(value(), Smi::FromInt(Protectors::kProtectorValid));
set_value(Smi::FromInt(Protectors::kProtectorInvalid), kReleaseStore);
// TODO(11527): pass Isolate as an argument.
Isolate* isolate = GetIsolateFromWritableObject(*this);
dependent_code().DeoptimizeDependentCodeGroup(
DependentCode::kPropertyCellChangedGroup);
isolate, DependentCode::kPropertyCellChangedGroup);
}
}

View File

@ -47,8 +47,10 @@ void PropertyCell::UpdatePropertyDetailsExceptCellType(
// unless the property is also configurable, in which case it will stay
// read-only forever.
if (!old_details.IsReadOnly() && details.IsReadOnly()) {
// TODO(11527): pass Isolate as an argument.
Isolate* isolate = GetIsolateFromWritableObject(*this);
dependent_code().DeoptimizeDependentCodeGroup(
DependentCode::kPropertyCellChangedGroup);
isolate, DependentCode::kPropertyCellChangedGroup);
}
}

View File

@ -3989,23 +3989,19 @@ TEST(EnsureAllocationSiteDependentCodesProcessed) {
->Get(context.local(), v8_str("bar"))
.ToLocalChecked())));
int dependency_group_count = 0;
DependentCode dependency = site->dependent_code();
while (dependency != ReadOnlyRoots(heap).empty_weak_fixed_array()) {
CHECK(dependency.group() ==
DependentCode::kAllocationSiteTransitionChangedGroup ||
dependency.group() ==
DependentCode::kAllocationSiteTenuringChangedGroup);
CHECK_EQ(1, dependency.count());
CHECK(dependency.object_at(0)->IsWeak());
Code function_bar = FromCodeT(
CodeT::cast(dependency.object_at(0)->GetHeapObjectAssumeWeak()));
CHECK_EQ(bar_handle->code(), function_bar);
dependency = dependency.next_link();
dependency_group_count++;
}
// Expect a dependent code object for transitioning and pretenuring.
CHECK_EQ(2, dependency_group_count);
DependentCode dependency = site->dependent_code();
CHECK_NE(dependency,
DependentCode::empty_dependent_code(ReadOnlyRoots(isolate)));
CHECK_EQ(dependency.length(), DependentCode::kSlotsPerEntry);
MaybeObject code = dependency.Get(0 + DependentCode::kCodeSlotOffset);
CHECK(code->IsWeak());
CHECK_EQ(bar_handle->code(),
FromCodeT(CodeT::cast(code->GetHeapObjectAssumeWeak())));
Smi groups = dependency.Get(0 + DependentCode::kGroupsSlotOffset).ToSmi();
CHECK_EQ(static_cast<DependentCode::DependencyGroups>(groups.value()),
DependentCode::kAllocationSiteTransitionChangedGroup |
DependentCode::kAllocationSiteTenuringChangedGroup);
}
// Now make sure that a gc should get rid of the function, even though we
@ -4016,7 +4012,7 @@ TEST(EnsureAllocationSiteDependentCodesProcessed) {
// The site still exists because of our global handle, but the code is no
// longer referred to by dependent_code().
CHECK(site->dependent_code().object_at(0)->IsCleared());
CHECK(site->dependent_code().Get(0)->IsCleared());
}
void CheckNumberOfAllocations(Heap* heap, const char* source,

View File

@ -261,100 +261,100 @@ KNOWN_MAPS = {
("read_only_space", 0x02119): (243, "MetaMap"),
("read_only_space", 0x02141): (131, "NullMap"),
("read_only_space", 0x02169): (224, "StrongDescriptorArrayMap"),
("read_only_space", 0x02191): (229, "WeakFixedArrayMap"),
("read_only_space", 0x021d1): (156, "EnumCacheMap"),
("read_only_space", 0x02205): (176, "FixedArrayMap"),
("read_only_space", 0x02251): (8, "OneByteInternalizedStringMap"),
("read_only_space", 0x0229d): (240, "FreeSpaceMap"),
("read_only_space", 0x022c5): (239, "OnePointerFillerMap"),
("read_only_space", 0x022ed): (239, "TwoPointerFillerMap"),
("read_only_space", 0x02315): (131, "UninitializedMap"),
("read_only_space", 0x0238d): (131, "UndefinedMap"),
("read_only_space", 0x023d1): (130, "HeapNumberMap"),
("read_only_space", 0x02405): (131, "TheHoleMap"),
("read_only_space", 0x02465): (131, "BooleanMap"),
("read_only_space", 0x02509): (189, "ByteArrayMap"),
("read_only_space", 0x02531): (176, "FixedCOWArrayMap"),
("read_only_space", 0x02559): (177, "HashTableMap"),
("read_only_space", 0x02581): (128, "SymbolMap"),
("read_only_space", 0x025a9): (40, "OneByteStringMap"),
("read_only_space", 0x025d1): (249, "ScopeInfoMap"),
("read_only_space", 0x025f9): (250, "SharedFunctionInfoMap"),
("read_only_space", 0x02621): (233, "CodeMap"),
("read_only_space", 0x02649): (232, "CellMap"),
("read_only_space", 0x02671): (248, "GlobalPropertyCellMap"),
("read_only_space", 0x02699): (204, "ForeignMap"),
("read_only_space", 0x026c1): (230, "TransitionArrayMap"),
("read_only_space", 0x026e9): (45, "ThinOneByteStringMap"),
("read_only_space", 0x02711): (238, "FeedbackVectorMap"),
("read_only_space", 0x02749): (131, "ArgumentsMarkerMap"),
("read_only_space", 0x027a9): (131, "ExceptionMap"),
("read_only_space", 0x02805): (131, "TerminationExceptionMap"),
("read_only_space", 0x0286d): (131, "OptimizedOutMap"),
("read_only_space", 0x028cd): (131, "StaleRegisterMap"),
("read_only_space", 0x0292d): (188, "ScriptContextTableMap"),
("read_only_space", 0x02955): (186, "ClosureFeedbackCellArrayMap"),
("read_only_space", 0x0297d): (237, "FeedbackMetadataArrayMap"),
("read_only_space", 0x029a5): (176, "ArrayListMap"),
("read_only_space", 0x029cd): (129, "BigIntMap"),
("read_only_space", 0x029f5): (187, "ObjectBoilerplateDescriptionMap"),
("read_only_space", 0x02a1d): (190, "BytecodeArrayMap"),
("read_only_space", 0x02a45): (234, "CodeDataContainerMap"),
("read_only_space", 0x02a6d): (235, "CoverageInfoMap"),
("read_only_space", 0x02a95): (191, "FixedDoubleArrayMap"),
("read_only_space", 0x02abd): (179, "GlobalDictionaryMap"),
("read_only_space", 0x02ae5): (157, "ManyClosuresCellMap"),
("read_only_space", 0x02b0d): (244, "MegaDomHandlerMap"),
("read_only_space", 0x02b35): (176, "ModuleInfoMap"),
("read_only_space", 0x02b5d): (180, "NameDictionaryMap"),
("read_only_space", 0x02b85): (157, "NoClosuresCellMap"),
("read_only_space", 0x02bad): (181, "NumberDictionaryMap"),
("read_only_space", 0x02bd5): (157, "OneClosureCellMap"),
("read_only_space", 0x02bfd): (182, "OrderedHashMapMap"),
("read_only_space", 0x02c25): (183, "OrderedHashSetMap"),
("read_only_space", 0x02c4d): (184, "OrderedNameDictionaryMap"),
("read_only_space", 0x02c75): (246, "PreparseDataMap"),
("read_only_space", 0x02c9d): (247, "PropertyArrayMap"),
("read_only_space", 0x02cc5): (153, "SideEffectCallHandlerInfoMap"),
("read_only_space", 0x02ced): (153, "SideEffectFreeCallHandlerInfoMap"),
("read_only_space", 0x02d15): (153, "NextCallSideEffectFreeCallHandlerInfoMap"),
("read_only_space", 0x02d3d): (185, "SimpleNumberDictionaryMap"),
("read_only_space", 0x02d65): (218, "SmallOrderedHashMapMap"),
("read_only_space", 0x02d8d): (219, "SmallOrderedHashSetMap"),
("read_only_space", 0x02db5): (220, "SmallOrderedNameDictionaryMap"),
("read_only_space", 0x02ddd): (225, "SourceTextModuleMap"),
("read_only_space", 0x02e05): (254, "SwissNameDictionaryMap"),
("read_only_space", 0x02e2d): (226, "SyntheticModuleMap"),
("read_only_space", 0x02e55): (206, "WasmCapiFunctionDataMap"),
("read_only_space", 0x02e7d): (207, "WasmExportedFunctionDataMap"),
("read_only_space", 0x02ea5): (208, "WasmJSFunctionDataMap"),
("read_only_space", 0x02ecd): (255, "WasmApiFunctionRefMap"),
("read_only_space", 0x02ef5): (209, "WasmTypeInfoMap"),
("read_only_space", 0x02f1d): (256, "WeakArrayListMap"),
("read_only_space", 0x02f45): (178, "EphemeronHashTableMap"),
("read_only_space", 0x02f6d): (236, "EmbedderDataArrayMap"),
("read_only_space", 0x02f95): (257, "WeakCellMap"),
("read_only_space", 0x02fbd): (32, "StringMap"),
("read_only_space", 0x02fe5): (41, "ConsOneByteStringMap"),
("read_only_space", 0x0300d): (33, "ConsStringMap"),
("read_only_space", 0x03035): (37, "ThinStringMap"),
("read_only_space", 0x0305d): (35, "SlicedStringMap"),
("read_only_space", 0x03085): (43, "SlicedOneByteStringMap"),
("read_only_space", 0x030ad): (34, "ExternalStringMap"),
("read_only_space", 0x030d5): (42, "ExternalOneByteStringMap"),
("read_only_space", 0x030fd): (50, "UncachedExternalStringMap"),
("read_only_space", 0x03125): (0, "InternalizedStringMap"),
("read_only_space", 0x0314d): (2, "ExternalInternalizedStringMap"),
("read_only_space", 0x03175): (10, "ExternalOneByteInternalizedStringMap"),
("read_only_space", 0x0319d): (18, "UncachedExternalInternalizedStringMap"),
("read_only_space", 0x031c5): (26, "UncachedExternalOneByteInternalizedStringMap"),
("read_only_space", 0x031ed): (58, "UncachedExternalOneByteStringMap"),
("read_only_space", 0x03215): (104, "SharedOneByteStringMap"),
("read_only_space", 0x0323d): (96, "SharedStringMap"),
("read_only_space", 0x03265): (131, "SelfReferenceMarkerMap"),
("read_only_space", 0x0328d): (131, "BasicBlockCountersMarkerMap"),
("read_only_space", 0x032d1): (147, "ArrayBoilerplateDescriptionMap"),
("read_only_space", 0x033d1): (159, "InterceptorInfoMap"),
("read_only_space", 0x02191): (256, "WeakArrayListMap"),
("read_only_space", 0x021d5): (156, "EnumCacheMap"),
("read_only_space", 0x02209): (176, "FixedArrayMap"),
("read_only_space", 0x02255): (8, "OneByteInternalizedStringMap"),
("read_only_space", 0x022a1): (240, "FreeSpaceMap"),
("read_only_space", 0x022c9): (239, "OnePointerFillerMap"),
("read_only_space", 0x022f1): (239, "TwoPointerFillerMap"),
("read_only_space", 0x02319): (131, "UninitializedMap"),
("read_only_space", 0x02391): (131, "UndefinedMap"),
("read_only_space", 0x023d5): (130, "HeapNumberMap"),
("read_only_space", 0x02409): (131, "TheHoleMap"),
("read_only_space", 0x02469): (131, "BooleanMap"),
("read_only_space", 0x0250d): (189, "ByteArrayMap"),
("read_only_space", 0x02535): (176, "FixedCOWArrayMap"),
("read_only_space", 0x0255d): (177, "HashTableMap"),
("read_only_space", 0x02585): (128, "SymbolMap"),
("read_only_space", 0x025ad): (40, "OneByteStringMap"),
("read_only_space", 0x025d5): (249, "ScopeInfoMap"),
("read_only_space", 0x025fd): (250, "SharedFunctionInfoMap"),
("read_only_space", 0x02625): (233, "CodeMap"),
("read_only_space", 0x0264d): (232, "CellMap"),
("read_only_space", 0x02675): (248, "GlobalPropertyCellMap"),
("read_only_space", 0x0269d): (204, "ForeignMap"),
("read_only_space", 0x026c5): (230, "TransitionArrayMap"),
("read_only_space", 0x026ed): (45, "ThinOneByteStringMap"),
("read_only_space", 0x02715): (238, "FeedbackVectorMap"),
("read_only_space", 0x0274d): (131, "ArgumentsMarkerMap"),
("read_only_space", 0x027ad): (131, "ExceptionMap"),
("read_only_space", 0x02809): (131, "TerminationExceptionMap"),
("read_only_space", 0x02871): (131, "OptimizedOutMap"),
("read_only_space", 0x028d1): (131, "StaleRegisterMap"),
("read_only_space", 0x02931): (188, "ScriptContextTableMap"),
("read_only_space", 0x02959): (186, "ClosureFeedbackCellArrayMap"),
("read_only_space", 0x02981): (237, "FeedbackMetadataArrayMap"),
("read_only_space", 0x029a9): (176, "ArrayListMap"),
("read_only_space", 0x029d1): (129, "BigIntMap"),
("read_only_space", 0x029f9): (187, "ObjectBoilerplateDescriptionMap"),
("read_only_space", 0x02a21): (190, "BytecodeArrayMap"),
("read_only_space", 0x02a49): (234, "CodeDataContainerMap"),
("read_only_space", 0x02a71): (235, "CoverageInfoMap"),
("read_only_space", 0x02a99): (191, "FixedDoubleArrayMap"),
("read_only_space", 0x02ac1): (179, "GlobalDictionaryMap"),
("read_only_space", 0x02ae9): (157, "ManyClosuresCellMap"),
("read_only_space", 0x02b11): (244, "MegaDomHandlerMap"),
("read_only_space", 0x02b39): (176, "ModuleInfoMap"),
("read_only_space", 0x02b61): (180, "NameDictionaryMap"),
("read_only_space", 0x02b89): (157, "NoClosuresCellMap"),
("read_only_space", 0x02bb1): (181, "NumberDictionaryMap"),
("read_only_space", 0x02bd9): (157, "OneClosureCellMap"),
("read_only_space", 0x02c01): (182, "OrderedHashMapMap"),
("read_only_space", 0x02c29): (183, "OrderedHashSetMap"),
("read_only_space", 0x02c51): (184, "OrderedNameDictionaryMap"),
("read_only_space", 0x02c79): (246, "PreparseDataMap"),
("read_only_space", 0x02ca1): (247, "PropertyArrayMap"),
("read_only_space", 0x02cc9): (153, "SideEffectCallHandlerInfoMap"),
("read_only_space", 0x02cf1): (153, "SideEffectFreeCallHandlerInfoMap"),
("read_only_space", 0x02d19): (153, "NextCallSideEffectFreeCallHandlerInfoMap"),
("read_only_space", 0x02d41): (185, "SimpleNumberDictionaryMap"),
("read_only_space", 0x02d69): (218, "SmallOrderedHashMapMap"),
("read_only_space", 0x02d91): (219, "SmallOrderedHashSetMap"),
("read_only_space", 0x02db9): (220, "SmallOrderedNameDictionaryMap"),
("read_only_space", 0x02de1): (225, "SourceTextModuleMap"),
("read_only_space", 0x02e09): (254, "SwissNameDictionaryMap"),
("read_only_space", 0x02e31): (226, "SyntheticModuleMap"),
("read_only_space", 0x02e59): (206, "WasmCapiFunctionDataMap"),
("read_only_space", 0x02e81): (207, "WasmExportedFunctionDataMap"),
("read_only_space", 0x02ea9): (208, "WasmJSFunctionDataMap"),
("read_only_space", 0x02ed1): (255, "WasmApiFunctionRefMap"),
("read_only_space", 0x02ef9): (209, "WasmTypeInfoMap"),
("read_only_space", 0x02f21): (229, "WeakFixedArrayMap"),
("read_only_space", 0x02f49): (178, "EphemeronHashTableMap"),
("read_only_space", 0x02f71): (236, "EmbedderDataArrayMap"),
("read_only_space", 0x02f99): (257, "WeakCellMap"),
("read_only_space", 0x02fc1): (32, "StringMap"),
("read_only_space", 0x02fe9): (41, "ConsOneByteStringMap"),
("read_only_space", 0x03011): (33, "ConsStringMap"),
("read_only_space", 0x03039): (37, "ThinStringMap"),
("read_only_space", 0x03061): (35, "SlicedStringMap"),
("read_only_space", 0x03089): (43, "SlicedOneByteStringMap"),
("read_only_space", 0x030b1): (34, "ExternalStringMap"),
("read_only_space", 0x030d9): (42, "ExternalOneByteStringMap"),
("read_only_space", 0x03101): (50, "UncachedExternalStringMap"),
("read_only_space", 0x03129): (0, "InternalizedStringMap"),
("read_only_space", 0x03151): (2, "ExternalInternalizedStringMap"),
("read_only_space", 0x03179): (10, "ExternalOneByteInternalizedStringMap"),
("read_only_space", 0x031a1): (18, "UncachedExternalInternalizedStringMap"),
("read_only_space", 0x031c9): (26, "UncachedExternalOneByteInternalizedStringMap"),
("read_only_space", 0x031f1): (58, "UncachedExternalOneByteStringMap"),
("read_only_space", 0x03219): (104, "SharedOneByteStringMap"),
("read_only_space", 0x03241): (96, "SharedStringMap"),
("read_only_space", 0x03269): (131, "SelfReferenceMarkerMap"),
("read_only_space", 0x03291): (131, "BasicBlockCountersMarkerMap"),
("read_only_space", 0x032d5): (147, "ArrayBoilerplateDescriptionMap"),
("read_only_space", 0x033d5): (159, "InterceptorInfoMap"),
("read_only_space", 0x05c65): (132, "PromiseFulfillReactionJobTaskMap"),
("read_only_space", 0x05c8d): (133, "PromiseRejectReactionJobTaskMap"),
("read_only_space", 0x05cb5): (134, "CallableTaskMap"),
@ -428,39 +428,39 @@ KNOWN_MAPS = {
# List of known V8 objects.
KNOWN_OBJECTS = {
("read_only_space", 0x021b9): "EmptyWeakFixedArray",
("read_only_space", 0x021c1): "EmptyDescriptorArray",
("read_only_space", 0x021f9): "EmptyEnumCache",
("read_only_space", 0x0222d): "EmptyFixedArray",
("read_only_space", 0x02235): "NullValue",
("read_only_space", 0x0233d): "UninitializedValue",
("read_only_space", 0x023b5): "UndefinedValue",
("read_only_space", 0x023f9): "NanValue",
("read_only_space", 0x0242d): "TheHoleValue",
("read_only_space", 0x02459): "HoleNanValue",
("read_only_space", 0x0248d): "TrueValue",
("read_only_space", 0x024cd): "FalseValue",
("read_only_space", 0x024fd): "empty_string",
("read_only_space", 0x02739): "EmptyScopeInfo",
("read_only_space", 0x02771): "ArgumentsMarker",
("read_only_space", 0x027d1): "Exception",
("read_only_space", 0x0282d): "TerminationException",
("read_only_space", 0x02895): "OptimizedOut",
("read_only_space", 0x028f5): "StaleRegister",
("read_only_space", 0x032b5): "EmptyPropertyArray",
("read_only_space", 0x032bd): "EmptyByteArray",
("read_only_space", 0x032c5): "EmptyObjectBoilerplateDescription",
("read_only_space", 0x032f9): "EmptyArrayBoilerplateDescription",
("read_only_space", 0x03305): "EmptyClosureFeedbackCellArray",
("read_only_space", 0x0330d): "EmptySlowElementDictionary",
("read_only_space", 0x03331): "EmptyOrderedHashMap",
("read_only_space", 0x03345): "EmptyOrderedHashSet",
("read_only_space", 0x03359): "EmptyFeedbackMetadata",
("read_only_space", 0x03365): "EmptyPropertyDictionary",
("read_only_space", 0x0338d): "EmptyOrderedPropertyDictionary",
("read_only_space", 0x033a5): "EmptySwissPropertyDictionary",
("read_only_space", 0x033f9): "NoOpInterceptorInfo",
("read_only_space", 0x03421): "EmptyWeakArrayList",
("read_only_space", 0x021b9): "EmptyWeakArrayList",
("read_only_space", 0x021c5): "EmptyDescriptorArray",
("read_only_space", 0x021fd): "EmptyEnumCache",
("read_only_space", 0x02231): "EmptyFixedArray",
("read_only_space", 0x02239): "NullValue",
("read_only_space", 0x02341): "UninitializedValue",
("read_only_space", 0x023b9): "UndefinedValue",
("read_only_space", 0x023fd): "NanValue",
("read_only_space", 0x02431): "TheHoleValue",
("read_only_space", 0x0245d): "HoleNanValue",
("read_only_space", 0x02491): "TrueValue",
("read_only_space", 0x024d1): "FalseValue",
("read_only_space", 0x02501): "empty_string",
("read_only_space", 0x0273d): "EmptyScopeInfo",
("read_only_space", 0x02775): "ArgumentsMarker",
("read_only_space", 0x027d5): "Exception",
("read_only_space", 0x02831): "TerminationException",
("read_only_space", 0x02899): "OptimizedOut",
("read_only_space", 0x028f9): "StaleRegister",
("read_only_space", 0x032b9): "EmptyPropertyArray",
("read_only_space", 0x032c1): "EmptyByteArray",
("read_only_space", 0x032c9): "EmptyObjectBoilerplateDescription",
("read_only_space", 0x032fd): "EmptyArrayBoilerplateDescription",
("read_only_space", 0x03309): "EmptyClosureFeedbackCellArray",
("read_only_space", 0x03311): "EmptySlowElementDictionary",
("read_only_space", 0x03335): "EmptyOrderedHashMap",
("read_only_space", 0x03349): "EmptyOrderedHashSet",
("read_only_space", 0x0335d): "EmptyFeedbackMetadata",
("read_only_space", 0x03369): "EmptyPropertyDictionary",
("read_only_space", 0x03391): "EmptyOrderedPropertyDictionary",
("read_only_space", 0x033a9): "EmptySwissPropertyDictionary",
("read_only_space", 0x033fd): "NoOpInterceptorInfo",
("read_only_space", 0x03425): "EmptyWeakFixedArray",
("read_only_space", 0x0342d): "InfinityValue",
("read_only_space", 0x03439): "MinusZeroValue",
("read_only_space", 0x03445): "MinusInfinityValue",