[heap] Introduce old-to-new invalidation set

Introduce list of invalidated objects for old-to-new slots. Objects
are registered as invalidated in NotifyObjectLayoutChange, however
no slots are filtered right now. Slots are still deleted, so all
recorded slots are valid.

Bug: v8:9454
Change-Id: Ic0ea15283c4075f4051fae6a5b148721265339f7
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1765528
Commit-Queue: Dominik Inführ <dinfuehr@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#63367}
This commit is contained in:
Dominik Inführ 2019-08-23 13:50:27 +02:00 committed by Commit Bot
parent b457623d33
commit 604b0e1e13
14 changed files with 687 additions and 326 deletions

View File

@ -1108,6 +1108,15 @@ void Heap::GarbageCollectionEpilogue() {
AllowHeapAllocation for_the_rest_of_the_epilogue;
#ifdef DEBUG
// Old-to-new slot sets must be empty after each collection.
for (SpaceIterator it(this); it.HasNext();) {
Space* space = it.Next();
for (MemoryChunk* chunk = space->first_page(); chunk != space->last_page();
chunk = chunk->list_node().next())
DCHECK_NULL(chunk->invalidated_slots<OLD_TO_NEW>());
}
if (FLAG_print_global_handles) isolate_->global_handles()->Print();
if (FLAG_print_handles) PrintHandles();
if (FLAG_gc_verbose) Print();
@ -2998,13 +3007,20 @@ FixedArrayBase Heap::LeftTrimFixedArray(FixedArrayBase object,
FixedArrayBase new_object =
FixedArrayBase::cast(HeapObject::FromAddress(new_start));
#ifdef DEBUG
if (MayContainRecordedSlots(object)) {
MemoryChunk* chunk = MemoryChunk::FromHeapObject(object);
DCHECK(!chunk->RegisteredObjectWithInvalidatedSlots<OLD_TO_NEW>(object));
}
#endif
// Handle invalidated old-to-old slots.
if (incremental_marking()->IsCompacting() &&
MayContainRecordedSlots(new_object)) {
// If the array was right-trimmed before, then it is registered in
// the invalidated_slots.
MemoryChunk::FromHeapObject(new_object)
->MoveObjectWithInvalidatedSlots(filler, new_object);
->MoveObjectWithInvalidatedSlots<OLD_TO_OLD>(filler, new_object);
// We have to clear slots in the free space to avoid stale old-to-old slots.
// Note we cannot use ClearFreedMemoryMode of CreateFillerObjectAt because
// we need pointer granularity writes to avoid race with the concurrent
@ -3083,6 +3099,13 @@ void Heap::CreateFillerForArray(T object, int elements_to_trim,
Address old_end = object.address() + old_size;
Address new_end = old_end - bytes_to_trim;
#ifdef DEBUG
if (MayContainRecordedSlots(object)) {
MemoryChunk* chunk = MemoryChunk::FromHeapObject(object);
DCHECK(!chunk->RegisteredObjectWithInvalidatedSlots<OLD_TO_NEW>(object));
}
#endif
// Register the array as an object with invalidated old-to-old slots. We
// cannot use NotifyObjectLayoutChange as it would mark the array black,
// which is not safe for left-trimming because left-trimming re-pushes
@ -3092,8 +3115,8 @@ void Heap::CreateFillerForArray(T object, int elements_to_trim,
// Ensure that the object survives because the InvalidatedSlotsFilter will
// compute its size from its map during pointers updating phase.
incremental_marking()->WhiteToGreyAndPush(object);
MemoryChunk::FromHeapObject(object)->RegisterObjectWithInvalidatedSlots(
object, old_size);
MemoryChunk* chunk = MemoryChunk::FromHeapObject(object);
chunk->RegisterObjectWithInvalidatedSlots<OLD_TO_OLD>(object, old_size);
}
// Technically in new space this write might be omitted (except for
@ -3385,10 +3408,14 @@ void Heap::NotifyObjectLayoutChange(HeapObject object, int size,
incremental_marking()->MarkBlackAndVisitObjectDueToLayoutChange(object);
if (incremental_marking()->IsCompacting() &&
MayContainRecordedSlots(object)) {
MemoryChunk::FromHeapObject(object)->RegisterObjectWithInvalidatedSlots(
object, size);
MemoryChunk::FromHeapObject(object)
->RegisterObjectWithInvalidatedSlots<OLD_TO_OLD>(object, size);
}
}
if (MayContainRecordedSlots(object)) {
MemoryChunk::FromHeapObject(object)
->RegisterObjectWithInvalidatedSlots<OLD_TO_NEW>(object, size);
}
#ifdef VERIFY_HEAP
if (FLAG_verify_heap) {
DCHECK(pending_layout_change_object_.is_null());
@ -5537,7 +5564,7 @@ void Heap::VerifyClearedSlot(HeapObject object, ObjectSlot slot) {
CHECK(!RememberedSet<OLD_TO_NEW>::Contains(page, slot.address()));
// Old to old slots are filtered with invalidated slots.
CHECK_IMPLIES(RememberedSet<OLD_TO_OLD>::Contains(page, slot.address()),
page->RegisteredObjectWithInvalidatedSlots(object));
page->RegisteredObjectWithInvalidatedSlots<OLD_TO_OLD>(object));
}
#endif

View File

@ -62,6 +62,53 @@ bool InvalidatedSlotsFilter::IsValid(Address slot) {
return invalidated_object_.IsValidSlot(invalidated_object_.map(), offset);
}
void InvalidatedSlotsCleanup::Free(Address free_start, Address free_end) {
#ifdef DEBUG
DCHECK_LT(free_start, free_end);
// Free regions should come in increasing order and do not overlap
DCHECK_LE(last_free_, free_start);
last_free_ = free_start;
#endif
if (iterator_ == iterator_end_) return;
// Ignore invalidated objects before free region
while (free_start >= invalidated_end_) {
++iterator_;
NextInvalidatedObject();
}
// Loop here: Free region might contain multiple invalidated objects
while (free_end > invalidated_start_) {
// Case: Free region starts before current invalidated object
if (free_start <= invalidated_start_) {
CHECK(invalidated_end_ <= free_end);
iterator_ = invalidated_slots_->erase(iterator_);
} else {
// Case: Free region starts within current invalidated object
// (Can happen for right-trimmed objects)
iterator_->second =
static_cast<int>(free_start - iterator_->first.address());
CHECK(free_end >= invalidated_end_);
iterator_++;
}
NextInvalidatedObject();
}
}
void InvalidatedSlotsCleanup::NextInvalidatedObject() {
if (iterator_ != iterator_end_) {
invalidated_start_ = iterator_->first.address();
invalidated_end_ = invalidated_start_ + iterator_->second;
} else {
invalidated_start_ = sentinel_;
invalidated_end_ = sentinel_;
}
}
} // namespace internal
} // namespace v8

View File

@ -8,9 +8,18 @@
namespace v8 {
namespace internal {
InvalidatedSlotsFilter::InvalidatedSlotsFilter(MemoryChunk* chunk) {
InvalidatedSlotsFilter InvalidatedSlotsFilter::OldToOld(MemoryChunk* chunk) {
return InvalidatedSlotsFilter(chunk, chunk->invalidated_slots<OLD_TO_OLD>());
}
InvalidatedSlotsFilter InvalidatedSlotsFilter::OldToNew(MemoryChunk* chunk) {
return InvalidatedSlotsFilter(chunk, chunk->invalidated_slots<OLD_TO_NEW>());
}
InvalidatedSlotsFilter::InvalidatedSlotsFilter(
MemoryChunk* chunk, InvalidatedSlots* invalidated_slots) {
// Adjust slots_in_free_space_are_valid_ if more spaces are added.
DCHECK_IMPLIES(chunk->invalidated_slots() != nullptr,
DCHECK_IMPLIES(invalidated_slots != nullptr,
chunk->InOldSpace() || chunk->InLargeObjectSpace());
// The sweeper removes invalid slots and makes free space available for
// allocation. Slots for new objects can be recorded in the free space.
@ -18,8 +27,8 @@ InvalidatedSlotsFilter::InvalidatedSlotsFilter(MemoryChunk* chunk) {
// object space are not swept but have SweepingDone() == true.
slots_in_free_space_are_valid_ = chunk->SweepingDone() && chunk->InOldSpace();
InvalidatedSlots* invalidated_slots =
chunk->invalidated_slots() ? chunk->invalidated_slots() : &empty_;
invalidated_slots = invalidated_slots ? invalidated_slots : &empty_;
iterator_ = invalidated_slots->begin();
iterator_end_ = invalidated_slots->end();
sentinel_ = chunk->area_end();
@ -37,5 +46,37 @@ InvalidatedSlotsFilter::InvalidatedSlotsFilter(MemoryChunk* chunk) {
#endif
}
InvalidatedSlotsCleanup InvalidatedSlotsCleanup::OldToOld(MemoryChunk* chunk) {
return InvalidatedSlotsCleanup(chunk, chunk->invalidated_slots<OLD_TO_OLD>());
}
InvalidatedSlotsCleanup InvalidatedSlotsCleanup::OldToNew(MemoryChunk* chunk) {
return InvalidatedSlotsCleanup(chunk, chunk->invalidated_slots<OLD_TO_NEW>());
}
InvalidatedSlotsCleanup InvalidatedSlotsCleanup::NoCleanup(MemoryChunk* chunk) {
return InvalidatedSlotsCleanup(chunk, nullptr);
}
InvalidatedSlotsCleanup::InvalidatedSlotsCleanup(
MemoryChunk* chunk, InvalidatedSlots* invalidated_slots) {
invalidated_slots_ = invalidated_slots ? invalidated_slots : &empty_;
iterator_ = invalidated_slots_->begin();
iterator_end_ = invalidated_slots_->end();
sentinel_ = chunk->area_end();
if (iterator_ != iterator_end_) {
invalidated_start_ = iterator_->first.address();
invalidated_end_ = invalidated_start_ + iterator_->second;
} else {
invalidated_start_ = sentinel_;
invalidated_end_ = sentinel_;
}
#ifdef DEBUG
last_free_ = chunk->area_start();
#endif
}
} // namespace internal
} // namespace v8

View File

@ -30,7 +30,11 @@ using InvalidatedSlots = std::map<HeapObject, int, Object::Comparer>;
// n is the number of IsValid queries.
class V8_EXPORT_PRIVATE InvalidatedSlotsFilter {
public:
explicit InvalidatedSlotsFilter(MemoryChunk* chunk);
static InvalidatedSlotsFilter OldToOld(MemoryChunk* chunk);
static InvalidatedSlotsFilter OldToNew(MemoryChunk* chunk);
explicit InvalidatedSlotsFilter(MemoryChunk* chunk,
InvalidatedSlots* invalidated_slots);
inline bool IsValid(Address slot);
private:
@ -48,6 +52,33 @@ class V8_EXPORT_PRIVATE InvalidatedSlotsFilter {
#endif
};
class V8_EXPORT_PRIVATE InvalidatedSlotsCleanup {
public:
static InvalidatedSlotsCleanup OldToOld(MemoryChunk* chunk);
static InvalidatedSlotsCleanup OldToNew(MemoryChunk* chunk);
static InvalidatedSlotsCleanup NoCleanup(MemoryChunk* chunk);
explicit InvalidatedSlotsCleanup(MemoryChunk* chunk,
InvalidatedSlots* invalidated_slots);
inline void Free(Address free_start, Address free_end);
private:
InvalidatedSlots::iterator iterator_;
InvalidatedSlots::iterator iterator_end_;
InvalidatedSlots* invalidated_slots_;
InvalidatedSlots empty_;
Address sentinel_;
Address invalidated_start_;
Address invalidated_end_;
inline void NextInvalidatedObject();
#ifdef DEBUG
Address last_free_;
#endif
};
} // namespace internal
} // namespace v8

View File

@ -2689,7 +2689,8 @@ void MarkCompactCollector::EvacuateEpilogue() {
for (Page* p : *heap()->old_space()) {
DCHECK_NULL((p->slot_set<OLD_TO_OLD, AccessMode::ATOMIC>()));
DCHECK_NULL((p->typed_slot_set<OLD_TO_OLD, AccessMode::ATOMIC>()));
DCHECK_NULL(p->invalidated_slots());
DCHECK_NULL(p->invalidated_slots<OLD_TO_OLD>());
DCHECK_NULL(p->invalidated_slots<OLD_TO_NEW>());
}
#endif
}
@ -3410,16 +3411,32 @@ class RememberedSetUpdatingItem : public UpdatingItem {
void UpdateUntypedPointers() {
if (chunk_->slot_set<OLD_TO_NEW, AccessMode::NON_ATOMIC>() != nullptr) {
InvalidatedSlotsFilter filter = InvalidatedSlotsFilter::OldToNew(chunk_);
RememberedSet<OLD_TO_NEW>::Iterate(
chunk_,
[this](MaybeObjectSlot slot) {
[this, &filter](MaybeObjectSlot slot) {
if (!filter.IsValid(slot.address())) return REMOVE_SLOT;
return CheckAndUpdateOldToNewSlot(slot);
},
SlotSet::PREFREE_EMPTY_BUCKETS);
}
if (chunk_->invalidated_slots<OLD_TO_NEW>() != nullptr) {
#ifdef DEBUG
for (auto object_size : *chunk_->invalidated_slots<OLD_TO_NEW>()) {
HeapObject object = object_size.first;
int size = object_size.second;
DCHECK_LE(object.SizeFromMap(object.map()), size);
}
#endif
// The invalidated slots are not needed after old-to-new slots were
// processed.
chunk_->ReleaseInvalidatedSlots<OLD_TO_NEW>();
}
if ((updating_mode_ == RememberedSetUpdatingMode::ALL) &&
(chunk_->slot_set<OLD_TO_OLD, AccessMode::NON_ATOMIC>() != nullptr)) {
InvalidatedSlotsFilter filter(chunk_);
InvalidatedSlotsFilter filter = InvalidatedSlotsFilter::OldToOld(chunk_);
RememberedSet<OLD_TO_OLD>::Iterate(
chunk_,
[&filter](MaybeObjectSlot slot) {
@ -3429,9 +3446,9 @@ class RememberedSetUpdatingItem : public UpdatingItem {
SlotSet::PREFREE_EMPTY_BUCKETS);
}
if ((updating_mode_ == RememberedSetUpdatingMode::ALL) &&
chunk_->invalidated_slots() != nullptr) {
chunk_->invalidated_slots<OLD_TO_OLD>() != nullptr) {
#ifdef DEBUG
for (auto object_size : *chunk_->invalidated_slots()) {
for (auto object_size : *chunk_->invalidated_slots<OLD_TO_OLD>()) {
HeapObject object = object_size.first;
int size = object_size.second;
DCHECK_LE(object.SizeFromMap(object.map()), size);
@ -3439,7 +3456,7 @@ class RememberedSetUpdatingItem : public UpdatingItem {
#endif
// The invalidated slots are not needed after old-to-old slots were
// processsed.
chunk_->ReleaseInvalidatedSlots();
chunk_->ReleaseInvalidatedSlots<OLD_TO_OLD>();
}
}
@ -3553,13 +3570,17 @@ int MarkCompactCollectorBase::CollectRememberedSetUpdatingItems(
const bool contains_old_to_new_slots =
chunk->slot_set<OLD_TO_NEW>() != nullptr ||
chunk->typed_slot_set<OLD_TO_NEW>() != nullptr;
const bool contains_invalidated_slots =
chunk->invalidated_slots() != nullptr;
const bool contains_old_to_old_invalidated_slots =
chunk->invalidated_slots<OLD_TO_OLD>() != nullptr;
const bool contains_old_to_new_invalidated_slots =
chunk->invalidated_slots<OLD_TO_NEW>() != nullptr;
if (!contains_old_to_new_slots && !contains_old_to_old_slots &&
!contains_invalidated_slots)
!contains_old_to_old_invalidated_slots &&
!contains_old_to_new_invalidated_slots)
continue;
if (mode == RememberedSetUpdatingMode::ALL || contains_old_to_new_slots ||
contains_invalidated_slots) {
contains_old_to_old_invalidated_slots ||
contains_old_to_new_invalidated_slots) {
job->AddItem(CreateRememberedSetUpdatingItem(chunk, mode));
pages++;
}
@ -4636,11 +4657,14 @@ class PageMarkingItem : public MarkingItem {
inline Heap* heap() { return chunk_->heap(); }
void MarkUntypedPointers(YoungGenerationMarkingTask* task) {
RememberedSet<OLD_TO_NEW>::Iterate(chunk_,
[this, task](MaybeObjectSlot slot) {
return CheckAndMarkObject(task, slot);
},
SlotSet::PREFREE_EMPTY_BUCKETS);
InvalidatedSlotsFilter filter = InvalidatedSlotsFilter::OldToNew(chunk_);
RememberedSet<OLD_TO_NEW>::Iterate(
chunk_,
[this, task, &filter](MaybeObjectSlot slot) {
if (!filter.IsValid(slot.address())) return REMOVE_SLOT;
return CheckAndMarkObject(task, slot);
},
SlotSet::PREFREE_EMPTY_BUCKETS);
}
void MarkTypedPointers(YoungGenerationMarkingTask* task) {

View File

@ -122,7 +122,7 @@ class RememberedSet : public AllStatic {
SlotSet* slots = chunk->slot_set<type>();
TypedSlotSet* typed_slots = chunk->typed_slot_set<type>();
if (slots != nullptr || typed_slots != nullptr ||
chunk->invalidated_slots() != nullptr) {
chunk->invalidated_slots<type>() != nullptr) {
callback(chunk);
}
}
@ -256,7 +256,7 @@ class RememberedSet : public AllStatic {
while ((chunk = it.next()) != nullptr) {
chunk->ReleaseSlotSet<OLD_TO_OLD>();
chunk->ReleaseTypedSlotSet<OLD_TO_OLD>();
chunk->ReleaseInvalidatedSlots();
chunk->ReleaseInvalidatedSlots<OLD_TO_OLD>();
}
}

View File

@ -8,6 +8,7 @@
#include "src/heap/barrier.h"
#include "src/heap/gc-tracer.h"
#include "src/heap/heap-inl.h"
#include "src/heap/invalidated-slots-inl.h"
#include "src/heap/item-parallel-job.h"
#include "src/heap/mark-compact-inl.h"
#include "src/heap/objects-visiting-inl.h"
@ -431,12 +432,28 @@ void Scavenger::AddPageToSweeperIfNecessary(MemoryChunk* page) {
void Scavenger::ScavengePage(MemoryChunk* page) {
CodePageMemoryModificationScope memory_modification_scope(page);
RememberedSet<OLD_TO_NEW>::Iterate(page,
[this](MaybeObjectSlot addr) {
return CheckAndScavengeObject(heap_,
addr);
},
SlotSet::KEEP_EMPTY_BUCKETS);
InvalidatedSlotsFilter filter = InvalidatedSlotsFilter::OldToNew(page);
RememberedSet<OLD_TO_NEW>::Iterate(
page,
[this, &filter](MaybeObjectSlot addr) {
if (!filter.IsValid(addr.address())) return REMOVE_SLOT;
return CheckAndScavengeObject(heap_, addr);
},
SlotSet::KEEP_EMPTY_BUCKETS);
if (page->invalidated_slots<OLD_TO_NEW>() != nullptr) {
#ifdef DEBUG
for (auto object_size : *page->invalidated_slots<OLD_TO_NEW>()) {
HeapObject object = object_size.first;
int size = object_size.second;
DCHECK_LE(object.SizeFromMap(object.map()), size);
}
#endif
// The invalidated slots are not needed after old-to-new slots were
// processed.
page->ReleaseInvalidatedSlots<OLD_TO_NEW>();
}
RememberedSet<OLD_TO_NEW>::IterateTyped(
page, [=](SlotType type, Address addr) {
return UpdateTypedSlotHelper::UpdateTypedSlot(

View File

@ -703,7 +703,8 @@ MemoryChunk* MemoryChunk::Initialize(Heap* heap, Address base, size_t size,
nullptr);
base::AsAtomicPointer::Release_Store(&chunk->typed_slot_set_[OLD_TO_OLD],
nullptr);
chunk->invalidated_slots_ = nullptr;
chunk->invalidated_slots_[OLD_TO_NEW] = nullptr;
chunk->invalidated_slots_[OLD_TO_OLD] = nullptr;
chunk->progress_bar_ = 0;
chunk->high_water_mark_ = static_cast<intptr_t>(area_start - base);
chunk->set_concurrent_sweeping_state(kSweepingDone);
@ -1379,7 +1380,8 @@ void MemoryChunk::ReleaseAllocatedMemoryNeededForWritableChunk() {
ReleaseSlotSet<OLD_TO_OLD>();
ReleaseTypedSlotSet<OLD_TO_NEW>();
ReleaseTypedSlotSet<OLD_TO_OLD>();
ReleaseInvalidatedSlots();
ReleaseInvalidatedSlots<OLD_TO_NEW>();
ReleaseInvalidatedSlots<OLD_TO_OLD>();
if (local_tracker_ != nullptr) ReleaseLocalTracker();
if (young_generation_bitmap_ != nullptr) ReleaseYoungGenerationBitmap();
@ -1461,53 +1463,107 @@ void MemoryChunk::ReleaseTypedSlotSet() {
}
}
template InvalidatedSlots* MemoryChunk::AllocateInvalidatedSlots<OLD_TO_NEW>();
template InvalidatedSlots* MemoryChunk::AllocateInvalidatedSlots<OLD_TO_OLD>();
template <RememberedSetType type>
InvalidatedSlots* MemoryChunk::AllocateInvalidatedSlots() {
DCHECK_NULL(invalidated_slots_);
invalidated_slots_ = new InvalidatedSlots();
return invalidated_slots_;
DCHECK_NULL(invalidated_slots_[type]);
invalidated_slots_[type] = new InvalidatedSlots();
return invalidated_slots_[type];
}
template void MemoryChunk::ReleaseInvalidatedSlots<OLD_TO_NEW>();
template void MemoryChunk::ReleaseInvalidatedSlots<OLD_TO_OLD>();
template <RememberedSetType type>
void MemoryChunk::ReleaseInvalidatedSlots() {
if (invalidated_slots_) {
delete invalidated_slots_;
invalidated_slots_ = nullptr;
if (invalidated_slots_[type]) {
delete invalidated_slots_[type];
invalidated_slots_[type] = nullptr;
}
}
template V8_EXPORT_PRIVATE void
MemoryChunk::RegisterObjectWithInvalidatedSlots<OLD_TO_NEW>(HeapObject object,
int size);
template V8_EXPORT_PRIVATE void
MemoryChunk::RegisterObjectWithInvalidatedSlots<OLD_TO_OLD>(HeapObject object,
int size);
template <RememberedSetType type>
void MemoryChunk::RegisterObjectWithInvalidatedSlots(HeapObject object,
int size) {
if (!ShouldSkipEvacuationSlotRecording()) {
if (invalidated_slots() == nullptr) {
AllocateInvalidatedSlots();
bool skip_slot_recording;
if (type == OLD_TO_NEW) {
skip_slot_recording = InYoungGeneration();
} else {
skip_slot_recording = ShouldSkipEvacuationSlotRecording();
}
if (skip_slot_recording) {
return;
}
if (invalidated_slots<type>() == nullptr) {
AllocateInvalidatedSlots<type>();
}
InvalidatedSlots* invalidated_slots = this->invalidated_slots<type>();
InvalidatedSlots::iterator it = invalidated_slots->lower_bound(object);
if (it != invalidated_slots->end() && it->first == object) {
// object was already inserted
CHECK_LE(size, it->second);
return;
}
it = invalidated_slots->insert(it, std::make_pair(object, size));
// prevent overlapping invalidated objects for old-to-new.
if (type == OLD_TO_NEW && it != invalidated_slots->begin()) {
HeapObject pred = (--it)->first;
int pred_size = it->second;
DCHECK_LT(pred.address(), object.address());
if (pred.address() + pred_size > object.address()) {
it->second = static_cast<int>(object.address() - pred.address());
}
int old_size = (*invalidated_slots())[object];
(*invalidated_slots())[object] = std::max(old_size, size);
}
}
template bool MemoryChunk::RegisteredObjectWithInvalidatedSlots<OLD_TO_NEW>(
HeapObject object);
template bool MemoryChunk::RegisteredObjectWithInvalidatedSlots<OLD_TO_OLD>(
HeapObject object);
template <RememberedSetType type>
bool MemoryChunk::RegisteredObjectWithInvalidatedSlots(HeapObject object) {
if (ShouldSkipEvacuationSlotRecording()) {
// Invalidated slots do not matter if we are not recording slots.
return true;
}
if (invalidated_slots() == nullptr) {
if (invalidated_slots<type>() == nullptr) {
return false;
}
return invalidated_slots()->find(object) != invalidated_slots()->end();
return invalidated_slots<type>()->find(object) !=
invalidated_slots<type>()->end();
}
template void MemoryChunk::MoveObjectWithInvalidatedSlots<OLD_TO_OLD>(
HeapObject old_start, HeapObject new_start);
template <RememberedSetType type>
void MemoryChunk::MoveObjectWithInvalidatedSlots(HeapObject old_start,
HeapObject new_start) {
DCHECK_LT(old_start, new_start);
DCHECK_EQ(MemoryChunk::FromHeapObject(old_start),
MemoryChunk::FromHeapObject(new_start));
if (!ShouldSkipEvacuationSlotRecording() && invalidated_slots()) {
auto it = invalidated_slots()->find(old_start);
if (it != invalidated_slots()->end()) {
static_assert(type == OLD_TO_OLD, "only use this for old-to-old slots");
if (!ShouldSkipEvacuationSlotRecording() && invalidated_slots<type>()) {
auto it = invalidated_slots<type>()->find(old_start);
if (it != invalidated_slots<type>()->end()) {
int old_size = it->second;
int delta = static_cast<int>(new_start.address() - old_start.address());
invalidated_slots()->erase(it);
(*invalidated_slots())[new_start] = old_size - delta;
invalidated_slots<type>()->erase(it);
(*invalidated_slots<type>())[new_start] = old_size - delta;
}
}
}
@ -3693,9 +3749,17 @@ bool PagedSpace::RawSlowRefillLinearAllocationArea(int size_in_bytes,
static_cast<size_t>(size_in_bytes), origin))
return true;
// Cleanup invalidated old-to-new refs for compaction space in the
// final atomic pause.
Sweeper::FreeSpaceMayContainInvalidatedSlots
invalidated_slots_in_free_space =
is_local() ? Sweeper::FreeSpaceMayContainInvalidatedSlots::kYes
: Sweeper::FreeSpaceMayContainInvalidatedSlots::kNo;
// If sweeping is still in progress try to sweep pages.
int max_freed = collector->sweeper()->ParallelSweepSpace(
identity(), size_in_bytes, kMaxPagesToSweep);
identity(), size_in_bytes, kMaxPagesToSweep,
invalidated_slots_in_free_space);
RefillFreeList();
if (max_freed >= size_in_bytes) {
if (RefillLinearAllocationAreaFromFreeList(

View File

@ -636,7 +636,8 @@ class MemoryChunk : public BasicMemoryChunk {
+ kSystemPointerSize * NUMBER_OF_REMEMBERED_SET_TYPES // SlotSet* array
+ kSystemPointerSize *
NUMBER_OF_REMEMBERED_SET_TYPES // TypedSlotSet* array
+ kSystemPointerSize // InvalidatedSlots* invalidated_slots_
+ kSystemPointerSize *
NUMBER_OF_REMEMBERED_SET_TYPES // InvalidatedSlots* array
+ kSystemPointerSize // std::atomic<intptr_t> high_water_mark_
+ kSystemPointerSize // base::Mutex* mutex_
+ kSystemPointerSize // std::atomic<ConcurrentSweepingState>
@ -722,7 +723,7 @@ class MemoryChunk : public BasicMemoryChunk {
template <RememberedSetType type>
bool ContainsSlots() {
return slot_set<type>() != nullptr || typed_slot_set<type>() != nullptr ||
invalidated_slots() != nullptr;
invalidated_slots<type>() != nullptr;
}
template <RememberedSetType type, AccessMode access_mode = AccessMode::ATOMIC>
@ -750,15 +751,23 @@ class MemoryChunk : public BasicMemoryChunk {
template <RememberedSetType type>
void ReleaseTypedSlotSet();
template <RememberedSetType type>
InvalidatedSlots* AllocateInvalidatedSlots();
template <RememberedSetType type>
void ReleaseInvalidatedSlots();
template <RememberedSetType type>
V8_EXPORT_PRIVATE void RegisterObjectWithInvalidatedSlots(HeapObject object,
int size);
// Updates invalidated_slots after array left-trimming.
template <RememberedSetType type>
void MoveObjectWithInvalidatedSlots(HeapObject old_start,
HeapObject new_start);
template <RememberedSetType type>
bool RegisteredObjectWithInvalidatedSlots(HeapObject object);
InvalidatedSlots* invalidated_slots() { return invalidated_slots_; }
template <RememberedSetType type>
InvalidatedSlots* invalidated_slots() {
return invalidated_slots_[type];
}
void ReleaseLocalTracker();
@ -934,7 +943,7 @@ class MemoryChunk : public BasicMemoryChunk {
// is ceil(size() / kPageSize).
SlotSet* slot_set_[NUMBER_OF_REMEMBERED_SET_TYPES];
TypedSlotSet* typed_slot_set_[NUMBER_OF_REMEMBERED_SET_TYPES];
InvalidatedSlots* invalidated_slots_;
InvalidatedSlots* invalidated_slots_[NUMBER_OF_REMEMBERED_SET_TYPES];
// Assuming the initial allocation on a page is sequential,
// count highest number of bytes ever allocated on the page.

View File

@ -8,6 +8,7 @@
#include "src/execution/vm-state-inl.h"
#include "src/heap/array-buffer-tracker-inl.h"
#include "src/heap/gc-tracer.h"
#include "src/heap/invalidated-slots-inl.h"
#include "src/heap/mark-compact-inl.h"
#include "src/heap/remembered-set.h"
#include "src/objects/objects-inl.h"
@ -250,8 +251,10 @@ void Sweeper::EnsureCompleted() {
bool Sweeper::AreSweeperTasksRunning() { return num_sweeping_tasks_ != 0; }
int Sweeper::RawSweep(Page* p, FreeListRebuildingMode free_list_mode,
FreeSpaceTreatmentMode free_space_mode) {
int Sweeper::RawSweep(
Page* p, FreeListRebuildingMode free_list_mode,
FreeSpaceTreatmentMode free_space_mode,
FreeSpaceMayContainInvalidatedSlots invalidated_slots_in_free_space) {
Space* space = p->owner();
DCHECK_NOT_NULL(space);
DCHECK(free_list_mode == IGNORE_FREE_LIST || space->identity() == OLD_SPACE ||
@ -274,6 +277,15 @@ int Sweeper::RawSweep(Page* p, FreeListRebuildingMode free_list_mode,
ArrayBufferTracker::FreeDead(p, marking_state_);
Address free_start = p->area_start();
InvalidatedSlotsCleanup old_to_new_cleanup =
InvalidatedSlotsCleanup::NoCleanup(p);
// Clean invalidated slots during the final atomic pause. After resuming
// execution this isn't necessary, invalid old-to-new refs were already
// removed by mark compact's update pointers phase.
if (invalidated_slots_in_free_space ==
FreeSpaceMayContainInvalidatedSlots::kYes)
old_to_new_cleanup = InvalidatedSlotsCleanup::OldToNew(p);
intptr_t live_bytes = 0;
intptr_t freed_bytes = 0;
@ -318,6 +330,8 @@ int Sweeper::RawSweep(Page* p, FreeListRebuildingMode free_list_mode,
static_cast<uint32_t>(free_start - p->address()),
static_cast<uint32_t>(free_end - p->address())));
}
old_to_new_cleanup.Free(free_start, free_end);
}
Map map = object.synchronized_map();
int size = object.SizeFromMap(map);
@ -350,6 +364,8 @@ int Sweeper::RawSweep(Page* p, FreeListRebuildingMode free_list_mode,
static_cast<uint32_t>(free_start - p->address()),
static_cast<uint32_t>(p->area_end() - p->address())));
}
old_to_new_cleanup.Free(free_start, p->area_end());
}
// Clear invalid typed slots after collection all free ranges.
@ -399,13 +415,15 @@ bool Sweeper::SweepSpaceIncrementallyFromTask(AllocationSpace identity) {
return sweeping_list_[GetSweepSpaceIndex(identity)].empty();
}
int Sweeper::ParallelSweepSpace(AllocationSpace identity,
int required_freed_bytes, int max_pages) {
int Sweeper::ParallelSweepSpace(
AllocationSpace identity, int required_freed_bytes, int max_pages,
FreeSpaceMayContainInvalidatedSlots invalidated_slots_in_free_space) {
int max_freed = 0;
int pages_freed = 0;
Page* page = nullptr;
while ((page = GetSweepingPageSafe(identity)) != nullptr) {
int freed = ParallelSweepPage(page, identity);
int freed =
ParallelSweepPage(page, identity, invalidated_slots_in_free_space);
if (page->IsFlagSet(Page::NEVER_ALLOCATE_ON_PAGE)) {
// Free list of a never-allocate page will be dropped later on.
continue;
@ -419,7 +437,9 @@ int Sweeper::ParallelSweepSpace(AllocationSpace identity,
return max_freed;
}
int Sweeper::ParallelSweepPage(Page* page, AllocationSpace identity) {
int Sweeper::ParallelSweepPage(
Page* page, AllocationSpace identity,
FreeSpaceMayContainInvalidatedSlots invalidated_slots_in_free_space) {
// Early bailout for pages that are swept outside of the regular sweeping
// path. This check here avoids taking the lock first, avoiding deadlocks.
if (page->SweepingDone()) return 0;
@ -439,7 +459,8 @@ int Sweeper::ParallelSweepPage(Page* page, AllocationSpace identity) {
page->set_concurrent_sweeping_state(Page::kSweepingInProgress);
const FreeSpaceTreatmentMode free_space_mode =
Heap::ShouldZapGarbage() ? ZAP_FREE_SPACE : IGNORE_FREE_SPACE;
max_freed = RawSweep(page, REBUILD_FREE_LIST, free_space_mode);
max_freed = RawSweep(page, REBUILD_FREE_LIST, free_space_mode,
invalidated_slots_in_free_space);
DCHECK(page->SweepingDone());
// After finishing sweeping of a page we clean up its remembered set.
@ -595,7 +616,8 @@ void Sweeper::MakeIterable(Page* page) {
DCHECK(IsValidIterabilitySpace(page->owner_identity()));
const FreeSpaceTreatmentMode free_space_mode =
Heap::ShouldZapGarbage() ? ZAP_FREE_SPACE : IGNORE_FREE_SPACE;
RawSweep(page, IGNORE_FREE_LIST, free_space_mode);
RawSweep(page, IGNORE_FREE_LIST, free_space_mode,
FreeSpaceMayContainInvalidatedSlots::kNo);
}
} // namespace internal

View File

@ -70,12 +70,8 @@ class Sweeper {
};
enum FreeListRebuildingMode { REBUILD_FREE_LIST, IGNORE_FREE_LIST };
enum ClearOldToNewSlotsMode {
DO_NOT_CLEAR,
CLEAR_REGULAR_SLOTS,
CLEAR_TYPED_SLOTS
};
enum AddPageMode { REGULAR, READD_TEMPORARY_REMOVED_PAGE };
enum class FreeSpaceMayContainInvalidatedSlots { kYes, kNo };
Sweeper(Heap* heap, MajorNonAtomicMarkingState* marking_state);
@ -83,14 +79,21 @@ class Sweeper {
void AddPage(AllocationSpace space, Page* page, AddPageMode mode);
int ParallelSweepSpace(AllocationSpace identity, int required_freed_bytes,
int max_pages = 0);
int ParallelSweepPage(Page* page, AllocationSpace identity);
int ParallelSweepSpace(
AllocationSpace identity, int required_freed_bytes, int max_pages = 0,
FreeSpaceMayContainInvalidatedSlots invalidated_slots_in_free_space =
FreeSpaceMayContainInvalidatedSlots::kNo);
int ParallelSweepPage(
Page* page, AllocationSpace identity,
FreeSpaceMayContainInvalidatedSlots invalidated_slots_in_free_space =
FreeSpaceMayContainInvalidatedSlots::kNo);
void ScheduleIncrementalSweepingTask();
int RawSweep(Page* p, FreeListRebuildingMode free_list_mode,
FreeSpaceTreatmentMode free_space_mode);
int RawSweep(
Page* p, FreeListRebuildingMode free_list_mode,
FreeSpaceTreatmentMode free_space_mode,
FreeSpaceMayContainInvalidatedSlots invalidated_slots_in_free_space);
// After calling this function sweeping is considered to be in progress
// and the main thread can sweep lazily, but the background sweeper tasks

View File

@ -19,6 +19,10 @@
V(CompactionSpaceDivideSinglePage) \
V(InvalidatedSlotsAfterTrimming) \
V(InvalidatedSlotsAllInvalidatedRanges) \
V(InvalidatedSlotsCleanupEachObject) \
V(InvalidatedSlotsCleanupFull) \
V(InvalidatedSlotsCleanupRightTrim) \
V(InvalidatedSlotsCleanupOverlapRight) \
V(InvalidatedSlotsEvacuationCandidate) \
V(InvalidatedSlotsNoInvalidatedRanges) \
V(InvalidatedSlotsResetObjectRegression) \

View File

@ -44,7 +44,7 @@ Page* HeapTester::AllocateByteArraysOnPage(
CHECK_EQ(page, Page::FromHeapObject(byte_array));
}
}
CHECK_NULL(page->invalidated_slots());
CHECK_NULL(page->invalidated_slots<OLD_TO_OLD>());
return page;
}
@ -53,7 +53,7 @@ HEAP_TEST(InvalidatedSlotsNoInvalidatedRanges) {
Heap* heap = CcTest::heap();
std::vector<ByteArray> byte_arrays;
Page* page = AllocateByteArraysOnPage(heap, &byte_arrays);
InvalidatedSlotsFilter filter(page);
InvalidatedSlotsFilter filter = InvalidatedSlotsFilter::OldToOld(page);
for (ByteArray byte_array : byte_arrays) {
Address start = byte_array.address() + ByteArray::kHeaderSize;
Address end = byte_array.address() + byte_array.Size();
@ -70,10 +70,10 @@ HEAP_TEST(InvalidatedSlotsSomeInvalidatedRanges) {
Page* page = AllocateByteArraysOnPage(heap, &byte_arrays);
// Register every second byte arrays as invalidated.
for (size_t i = 0; i < byte_arrays.size(); i += 2) {
page->RegisterObjectWithInvalidatedSlots(byte_arrays[i],
byte_arrays[i].Size());
page->RegisterObjectWithInvalidatedSlots<OLD_TO_OLD>(byte_arrays[i],
byte_arrays[i].Size());
}
InvalidatedSlotsFilter filter(page);
InvalidatedSlotsFilter filter = InvalidatedSlotsFilter::OldToOld(page);
for (size_t i = 0; i < byte_arrays.size(); i++) {
ByteArray byte_array = byte_arrays[i];
Address start = byte_array.address() + ByteArray::kHeaderSize;
@ -95,10 +95,10 @@ HEAP_TEST(InvalidatedSlotsAllInvalidatedRanges) {
Page* page = AllocateByteArraysOnPage(heap, &byte_arrays);
// Register the all byte arrays as invalidated.
for (size_t i = 0; i < byte_arrays.size(); i++) {
page->RegisterObjectWithInvalidatedSlots(byte_arrays[i],
byte_arrays[i].Size());
page->RegisterObjectWithInvalidatedSlots<OLD_TO_OLD>(byte_arrays[i],
byte_arrays[i].Size());
}
InvalidatedSlotsFilter filter(page);
InvalidatedSlotsFilter filter = InvalidatedSlotsFilter::OldToOld(page);
for (size_t i = 0; i < byte_arrays.size(); i++) {
ByteArray byte_array = byte_arrays[i];
Address start = byte_array.address() + ByteArray::kHeaderSize;
@ -117,12 +117,12 @@ HEAP_TEST(InvalidatedSlotsAfterTrimming) {
Page* page = AllocateByteArraysOnPage(heap, &byte_arrays);
// Register the all byte arrays as invalidated.
for (size_t i = 0; i < byte_arrays.size(); i++) {
page->RegisterObjectWithInvalidatedSlots(byte_arrays[i],
byte_arrays[i].Size());
page->RegisterObjectWithInvalidatedSlots<OLD_TO_OLD>(byte_arrays[i],
byte_arrays[i].Size());
}
// Trim byte arrays and check that the slots outside the byte arrays are
// considered invalid if the old space page was swept.
InvalidatedSlotsFilter filter(page);
InvalidatedSlotsFilter filter = InvalidatedSlotsFilter::OldToOld(page);
for (size_t i = 0; i < byte_arrays.size(); i++) {
ByteArray byte_array = byte_arrays[i];
Address start = byte_array.address() + ByteArray::kHeaderSize;
@ -145,11 +145,11 @@ HEAP_TEST(InvalidatedSlotsEvacuationCandidate) {
// This should be no-op because the page is marked as evacuation
// candidate.
for (size_t i = 0; i < byte_arrays.size(); i++) {
page->RegisterObjectWithInvalidatedSlots(byte_arrays[i],
byte_arrays[i].Size());
page->RegisterObjectWithInvalidatedSlots<OLD_TO_OLD>(byte_arrays[i],
byte_arrays[i].Size());
}
// All slots must still be valid.
InvalidatedSlotsFilter filter(page);
InvalidatedSlotsFilter filter = InvalidatedSlotsFilter::OldToOld(page);
for (size_t i = 0; i < byte_arrays.size(); i++) {
ByteArray byte_array = byte_arrays[i];
Address start = byte_array.address() + ByteArray::kHeaderSize;
@ -169,11 +169,11 @@ HEAP_TEST(InvalidatedSlotsResetObjectRegression) {
heap->RightTrimFixedArray(byte_arrays[0], byte_arrays[0].length() - 8);
// Register the all byte arrays as invalidated.
for (size_t i = 0; i < byte_arrays.size(); i++) {
page->RegisterObjectWithInvalidatedSlots(byte_arrays[i],
byte_arrays[i].Size());
page->RegisterObjectWithInvalidatedSlots<OLD_TO_OLD>(byte_arrays[i],
byte_arrays[i].Size());
}
// All slots must still be invalid.
InvalidatedSlotsFilter filter(page);
InvalidatedSlotsFilter filter = InvalidatedSlotsFilter::OldToOld(page);
for (size_t i = 0; i < byte_arrays.size(); i++) {
ByteArray byte_array = byte_arrays[i];
Address start = byte_array.address() + ByteArray::kHeaderSize;
@ -351,6 +351,78 @@ HEAP_TEST(InvalidatedSlotsFastToSlow) {
CcTest::CollectGarbage(i::OLD_SPACE);
}
HEAP_TEST(InvalidatedSlotsCleanupFull) {
ManualGCScope manual_gc_scope;
CcTest::InitializeVM();
Heap* heap = CcTest::heap();
std::vector<ByteArray> byte_arrays;
Page* page = AllocateByteArraysOnPage(heap, &byte_arrays);
// Register all byte arrays as invalidated.
for (size_t i = 0; i < byte_arrays.size(); i++) {
page->RegisterObjectWithInvalidatedSlots<OLD_TO_NEW>(byte_arrays[i],
byte_arrays[i].Size());
}
// Mark full page as free
InvalidatedSlotsCleanup cleanup = InvalidatedSlotsCleanup::OldToNew(page);
cleanup.Free(page->area_start(), page->area_end());
// After cleanup there should be no invalidated objects on page left
CHECK(page->invalidated_slots<OLD_TO_NEW>()->empty());
}
HEAP_TEST(InvalidatedSlotsCleanupEachObject) {
ManualGCScope manual_gc_scope;
CcTest::InitializeVM();
Heap* heap = CcTest::heap();
std::vector<ByteArray> byte_arrays;
Page* page = AllocateByteArraysOnPage(heap, &byte_arrays);
// Register all byte arrays as invalidated.
for (size_t i = 0; i < byte_arrays.size(); i++) {
page->RegisterObjectWithInvalidatedSlots<OLD_TO_NEW>(byte_arrays[i],
byte_arrays[i].Size());
}
// Mark each object as free on page
InvalidatedSlotsCleanup cleanup = InvalidatedSlotsCleanup::OldToNew(page);
for (size_t i = 0; i < byte_arrays.size(); i++) {
Address free_start = byte_arrays[i].address();
Address free_end = free_start + byte_arrays[i].Size();
cleanup.Free(free_start, free_end);
}
// After cleanup there should be no invalidated objects on page left
CHECK(page->invalidated_slots<OLD_TO_NEW>()->empty());
}
HEAP_TEST(InvalidatedSlotsCleanupRightTrim) {
ManualGCScope manual_gc_scope;
CcTest::InitializeVM();
Heap* heap = CcTest::heap();
std::vector<ByteArray> byte_arrays;
Page* page = AllocateByteArraysOnPage(heap, &byte_arrays);
CHECK_GT(byte_arrays.size(), 1);
ByteArray& invalidated = byte_arrays[1];
int invalidated_size = invalidated.Size();
heap->RightTrimFixedArray(invalidated, invalidated.length() - 8);
page->RegisterObjectWithInvalidatedSlots<OLD_TO_NEW>(invalidated,
invalidated_size);
// Free memory at end of invalidated object
InvalidatedSlotsCleanup cleanup = InvalidatedSlotsCleanup::OldToNew(page);
Address free_start = invalidated.address() + invalidated.Size();
cleanup.Free(free_start, page->area_end());
// After cleanup the invalidated object should be smaller
InvalidatedSlots* invalidated_slots = page->invalidated_slots<OLD_TO_NEW>();
CHECK_EQ((*invalidated_slots)[HeapObject::FromAddress(invalidated.address())],
invalidated.Size());
CHECK_EQ(invalidated_slots->size(), 1);
}
} // namespace heap
} // namespace internal
} // namespace v8

View File

@ -190,238 +190,238 @@ INSTANCE_TYPES = {
# List of known V8 maps.
KNOWN_MAPS = {
("read_only_space", 0x00111): (73, "FreeSpaceMap"),
("read_only_space", 0x00161): (68, "MetaMap"),
("read_only_space", 0x001e1): (67, "NullMap"),
("read_only_space", 0x00249): (153, "DescriptorArrayMap"),
("read_only_space", 0x002a9): (148, "WeakFixedArrayMap"),
("read_only_space", 0x002f9): (76, "OnePointerFillerMap"),
("read_only_space", 0x00349): (76, "TwoPointerFillerMap"),
("read_only_space", 0x003c9): (67, "UninitializedMap"),
("read_only_space", 0x00439): (8, "OneByteInternalizedStringMap"),
("read_only_space", 0x004d9): (67, "UndefinedMap"),
("read_only_space", 0x00539): (65, "HeapNumberMap"),
("read_only_space", 0x005b9): (67, "TheHoleMap"),
("read_only_space", 0x00661): (67, "BooleanMap"),
("read_only_space", 0x00739): (71, "ByteArrayMap"),
("read_only_space", 0x00789): (123, "FixedArrayMap"),
("read_only_space", 0x007d9): (123, "FixedCOWArrayMap"),
("read_only_space", 0x00829): (126, "HashTableMap"),
("read_only_space", 0x00879): (64, "SymbolMap"),
("read_only_space", 0x008c9): (40, "OneByteStringMap"),
("read_only_space", 0x00919): (136, "ScopeInfoMap"),
("read_only_space", 0x00969): (160, "SharedFunctionInfoMap"),
("read_only_space", 0x009b9): (69, "CodeMap"),
("read_only_space", 0x00a09): (143, "FunctionContextMap"),
("read_only_space", 0x00a59): (151, "CellMap"),
("read_only_space", 0x00aa9): (159, "GlobalPropertyCellMap"),
("read_only_space", 0x00af9): (70, "ForeignMap"),
("read_only_space", 0x00b49): (149, "TransitionArrayMap"),
("read_only_space", 0x00b99): (155, "FeedbackVectorMap"),
("read_only_space", 0x00c39): (67, "ArgumentsMarkerMap"),
("read_only_space", 0x00cd9): (67, "ExceptionMap"),
("read_only_space", 0x00d79): (67, "TerminationExceptionMap"),
("read_only_space", 0x00e21): (67, "OptimizedOutMap"),
("read_only_space", 0x00ec1): (67, "StaleRegisterMap"),
("read_only_space", 0x00f31): (145, "NativeContextMap"),
("read_only_space", 0x00f81): (144, "ModuleContextMap"),
("read_only_space", 0x00fd1): (142, "EvalContextMap"),
("read_only_space", 0x01021): (146, "ScriptContextMap"),
("read_only_space", 0x01071): (138, "AwaitContextMap"),
("read_only_space", 0x010c1): (139, "BlockContextMap"),
("read_only_space", 0x01111): (140, "CatchContextMap"),
("read_only_space", 0x01161): (147, "WithContextMap"),
("read_only_space", 0x011b1): (141, "DebugEvaluateContextMap"),
("read_only_space", 0x01201): (137, "ScriptContextTableMap"),
("read_only_space", 0x01251): (125, "ClosureFeedbackCellArrayMap"),
("read_only_space", 0x012a1): (75, "FeedbackMetadataArrayMap"),
("read_only_space", 0x012f1): (123, "ArrayListMap"),
("read_only_space", 0x01341): (66, "BigIntMap"),
("read_only_space", 0x01391): (124, "ObjectBoilerplateDescriptionMap"),
("read_only_space", 0x013e1): (72, "BytecodeArrayMap"),
("read_only_space", 0x01431): (152, "CodeDataContainerMap"),
("read_only_space", 0x01481): (74, "FixedDoubleArrayMap"),
("read_only_space", 0x014d1): (131, "GlobalDictionaryMap"),
("read_only_space", 0x01521): (154, "ManyClosuresCellMap"),
("read_only_space", 0x01571): (123, "ModuleInfoMap"),
("read_only_space", 0x015c1): (130, "NameDictionaryMap"),
("read_only_space", 0x01611): (154, "NoClosuresCellMap"),
("read_only_space", 0x01661): (132, "NumberDictionaryMap"),
("read_only_space", 0x016b1): (154, "OneClosureCellMap"),
("read_only_space", 0x01701): (127, "OrderedHashMapMap"),
("read_only_space", 0x01751): (128, "OrderedHashSetMap"),
("read_only_space", 0x017a1): (129, "OrderedNameDictionaryMap"),
("read_only_space", 0x017f1): (157, "PreparseDataMap"),
("read_only_space", 0x01841): (158, "PropertyArrayMap"),
("read_only_space", 0x01891): (150, "SideEffectCallHandlerInfoMap"),
("read_only_space", 0x018e1): (150, "SideEffectFreeCallHandlerInfoMap"),
("read_only_space", 0x01931): (150, "NextCallSideEffectFreeCallHandlerInfoMap"),
("read_only_space", 0x01981): (133, "SimpleNumberDictionaryMap"),
("read_only_space", 0x019d1): (123, "SloppyArgumentsElementsMap"),
("read_only_space", 0x01a21): (161, "SmallOrderedHashMapMap"),
("read_only_space", 0x01a71): (162, "SmallOrderedHashSetMap"),
("read_only_space", 0x01ac1): (163, "SmallOrderedNameDictionaryMap"),
("read_only_space", 0x01b11): (119, "SourceTextModuleMap"),
("read_only_space", 0x01b61): (134, "StringTableMap"),
("read_only_space", 0x01bb1): (120, "SyntheticModuleMap"),
("read_only_space", 0x01c01): (165, "UncompiledDataWithoutPreparseDataMap"),
("read_only_space", 0x01c51): (166, "UncompiledDataWithPreparseDataMap"),
("read_only_space", 0x01ca1): (167, "WeakArrayListMap"),
("read_only_space", 0x01cf1): (135, "EphemeronHashTableMap"),
("read_only_space", 0x01d41): (122, "EmbedderDataArrayMap"),
("read_only_space", 0x01d91): (168, "WeakCellMap"),
("read_only_space", 0x01de1): (58, "NativeSourceStringMap"),
("read_only_space", 0x01e31): (32, "StringMap"),
("read_only_space", 0x01e81): (41, "ConsOneByteStringMap"),
("read_only_space", 0x01ed1): (33, "ConsStringMap"),
("read_only_space", 0x01f21): (45, "ThinOneByteStringMap"),
("read_only_space", 0x01f71): (37, "ThinStringMap"),
("read_only_space", 0x01fc1): (35, "SlicedStringMap"),
("read_only_space", 0x02011): (43, "SlicedOneByteStringMap"),
("read_only_space", 0x02061): (34, "ExternalStringMap"),
("read_only_space", 0x020b1): (42, "ExternalOneByteStringMap"),
("read_only_space", 0x02101): (50, "UncachedExternalStringMap"),
("read_only_space", 0x02151): (0, "InternalizedStringMap"),
("read_only_space", 0x021a1): (2, "ExternalInternalizedStringMap"),
("read_only_space", 0x021f1): (10, "ExternalOneByteInternalizedStringMap"),
("read_only_space", 0x02241): (18, "UncachedExternalInternalizedStringMap"),
("read_only_space", 0x02291): (26, "UncachedExternalOneByteInternalizedStringMap"),
("read_only_space", 0x022e1): (58, "UncachedExternalOneByteStringMap"),
("read_only_space", 0x02331): (67, "SelfReferenceMarkerMap"),
("read_only_space", 0x02399): (87, "EnumCacheMap"),
("read_only_space", 0x02439): (82, "ArrayBoilerplateDescriptionMap"),
("read_only_space", 0x02629): (90, "InterceptorInfoMap"),
("read_only_space", 0x04ec1): (77, "AccessCheckInfoMap"),
("read_only_space", 0x04f11): (78, "AccessorInfoMap"),
("read_only_space", 0x04f61): (79, "AccessorPairMap"),
("read_only_space", 0x04fb1): (80, "AliasedArgumentsEntryMap"),
("read_only_space", 0x05001): (81, "AllocationMementoMap"),
("read_only_space", 0x05051): (83, "AsmWasmDataMap"),
("read_only_space", 0x050a1): (84, "AsyncGeneratorRequestMap"),
("read_only_space", 0x050f1): (85, "ClassPositionsMap"),
("read_only_space", 0x05141): (86, "DebugInfoMap"),
("read_only_space", 0x05191): (88, "FunctionTemplateInfoMap"),
("read_only_space", 0x051e1): (89, "FunctionTemplateRareDataMap"),
("read_only_space", 0x05231): (91, "InterpreterDataMap"),
("read_only_space", 0x05281): (92, "ObjectTemplateInfoMap"),
("read_only_space", 0x052d1): (93, "PromiseCapabilityMap"),
("read_only_space", 0x05321): (94, "PromiseReactionMap"),
("read_only_space", 0x05371): (95, "PrototypeInfoMap"),
("read_only_space", 0x053c1): (96, "ScriptMap"),
("read_only_space", 0x05411): (97, "SourcePositionTableWithFrameCacheMap"),
("read_only_space", 0x05461): (98, "SourceTextModuleInfoEntryMap"),
("read_only_space", 0x054b1): (99, "StackFrameInfoMap"),
("read_only_space", 0x05501): (100, "StackTraceFrameMap"),
("read_only_space", 0x05551): (101, "TemplateObjectDescriptionMap"),
("read_only_space", 0x055a1): (102, "Tuple2Map"),
("read_only_space", 0x055f1): (103, "Tuple3Map"),
("read_only_space", 0x05641): (104, "WasmCapiFunctionDataMap"),
("read_only_space", 0x05691): (105, "WasmDebugInfoMap"),
("read_only_space", 0x056e1): (106, "WasmExceptionTagMap"),
("read_only_space", 0x05731): (107, "WasmExportedFunctionDataMap"),
("read_only_space", 0x05781): (108, "WasmIndirectFunctionTableMap"),
("read_only_space", 0x057d1): (109, "WasmJSFunctionDataMap"),
("read_only_space", 0x05821): (110, "CallableTaskMap"),
("read_only_space", 0x05871): (111, "CallbackTaskMap"),
("read_only_space", 0x058c1): (112, "PromiseFulfillReactionJobTaskMap"),
("read_only_space", 0x05911): (113, "PromiseRejectReactionJobTaskMap"),
("read_only_space", 0x05961): (114, "PromiseResolveThenableJobTaskMap"),
("read_only_space", 0x059b1): (115, "InternalClassMap"),
("read_only_space", 0x05a01): (116, "SmiPairMap"),
("read_only_space", 0x05a51): (117, "SmiBoxMap"),
("read_only_space", 0x05aa1): (118, "SortStateMap"),
("read_only_space", 0x05af1): (121, "AllocationSiteWithWeakNextMap"),
("read_only_space", 0x05b41): (121, "AllocationSiteWithoutWeakNextMap"),
("read_only_space", 0x05b91): (156, "LoadHandler1Map"),
("read_only_space", 0x05be1): (156, "LoadHandler2Map"),
("read_only_space", 0x05c31): (156, "LoadHandler3Map"),
("read_only_space", 0x05c81): (164, "StoreHandler0Map"),
("read_only_space", 0x05cd1): (164, "StoreHandler1Map"),
("read_only_space", 0x05d21): (164, "StoreHandler2Map"),
("read_only_space", 0x05d71): (164, "StoreHandler3Map"),
("map_space", 0x00111): (1057, "ExternalMap"),
("map_space", 0x00161): (1073, "JSMessageObjectMap"),
("read_only_space", 0x00119): (73, "FreeSpaceMap"),
("read_only_space", 0x00169): (68, "MetaMap"),
("read_only_space", 0x001e9): (67, "NullMap"),
("read_only_space", 0x00251): (153, "DescriptorArrayMap"),
("read_only_space", 0x002b1): (148, "WeakFixedArrayMap"),
("read_only_space", 0x00301): (76, "OnePointerFillerMap"),
("read_only_space", 0x00351): (76, "TwoPointerFillerMap"),
("read_only_space", 0x003d1): (67, "UninitializedMap"),
("read_only_space", 0x00441): (8, "OneByteInternalizedStringMap"),
("read_only_space", 0x004e1): (67, "UndefinedMap"),
("read_only_space", 0x00541): (65, "HeapNumberMap"),
("read_only_space", 0x005c1): (67, "TheHoleMap"),
("read_only_space", 0x00669): (67, "BooleanMap"),
("read_only_space", 0x00741): (71, "ByteArrayMap"),
("read_only_space", 0x00791): (123, "FixedArrayMap"),
("read_only_space", 0x007e1): (123, "FixedCOWArrayMap"),
("read_only_space", 0x00831): (126, "HashTableMap"),
("read_only_space", 0x00881): (64, "SymbolMap"),
("read_only_space", 0x008d1): (40, "OneByteStringMap"),
("read_only_space", 0x00921): (136, "ScopeInfoMap"),
("read_only_space", 0x00971): (160, "SharedFunctionInfoMap"),
("read_only_space", 0x009c1): (69, "CodeMap"),
("read_only_space", 0x00a11): (143, "FunctionContextMap"),
("read_only_space", 0x00a61): (151, "CellMap"),
("read_only_space", 0x00ab1): (159, "GlobalPropertyCellMap"),
("read_only_space", 0x00b01): (70, "ForeignMap"),
("read_only_space", 0x00b51): (149, "TransitionArrayMap"),
("read_only_space", 0x00ba1): (155, "FeedbackVectorMap"),
("read_only_space", 0x00c41): (67, "ArgumentsMarkerMap"),
("read_only_space", 0x00ce1): (67, "ExceptionMap"),
("read_only_space", 0x00d81): (67, "TerminationExceptionMap"),
("read_only_space", 0x00e29): (67, "OptimizedOutMap"),
("read_only_space", 0x00ec9): (67, "StaleRegisterMap"),
("read_only_space", 0x00f39): (145, "NativeContextMap"),
("read_only_space", 0x00f89): (144, "ModuleContextMap"),
("read_only_space", 0x00fd9): (142, "EvalContextMap"),
("read_only_space", 0x01029): (146, "ScriptContextMap"),
("read_only_space", 0x01079): (138, "AwaitContextMap"),
("read_only_space", 0x010c9): (139, "BlockContextMap"),
("read_only_space", 0x01119): (140, "CatchContextMap"),
("read_only_space", 0x01169): (147, "WithContextMap"),
("read_only_space", 0x011b9): (141, "DebugEvaluateContextMap"),
("read_only_space", 0x01209): (137, "ScriptContextTableMap"),
("read_only_space", 0x01259): (125, "ClosureFeedbackCellArrayMap"),
("read_only_space", 0x012a9): (75, "FeedbackMetadataArrayMap"),
("read_only_space", 0x012f9): (123, "ArrayListMap"),
("read_only_space", 0x01349): (66, "BigIntMap"),
("read_only_space", 0x01399): (124, "ObjectBoilerplateDescriptionMap"),
("read_only_space", 0x013e9): (72, "BytecodeArrayMap"),
("read_only_space", 0x01439): (152, "CodeDataContainerMap"),
("read_only_space", 0x01489): (74, "FixedDoubleArrayMap"),
("read_only_space", 0x014d9): (131, "GlobalDictionaryMap"),
("read_only_space", 0x01529): (154, "ManyClosuresCellMap"),
("read_only_space", 0x01579): (123, "ModuleInfoMap"),
("read_only_space", 0x015c9): (130, "NameDictionaryMap"),
("read_only_space", 0x01619): (154, "NoClosuresCellMap"),
("read_only_space", 0x01669): (132, "NumberDictionaryMap"),
("read_only_space", 0x016b9): (154, "OneClosureCellMap"),
("read_only_space", 0x01709): (127, "OrderedHashMapMap"),
("read_only_space", 0x01759): (128, "OrderedHashSetMap"),
("read_only_space", 0x017a9): (129, "OrderedNameDictionaryMap"),
("read_only_space", 0x017f9): (157, "PreparseDataMap"),
("read_only_space", 0x01849): (158, "PropertyArrayMap"),
("read_only_space", 0x01899): (150, "SideEffectCallHandlerInfoMap"),
("read_only_space", 0x018e9): (150, "SideEffectFreeCallHandlerInfoMap"),
("read_only_space", 0x01939): (150, "NextCallSideEffectFreeCallHandlerInfoMap"),
("read_only_space", 0x01989): (133, "SimpleNumberDictionaryMap"),
("read_only_space", 0x019d9): (123, "SloppyArgumentsElementsMap"),
("read_only_space", 0x01a29): (161, "SmallOrderedHashMapMap"),
("read_only_space", 0x01a79): (162, "SmallOrderedHashSetMap"),
("read_only_space", 0x01ac9): (163, "SmallOrderedNameDictionaryMap"),
("read_only_space", 0x01b19): (119, "SourceTextModuleMap"),
("read_only_space", 0x01b69): (134, "StringTableMap"),
("read_only_space", 0x01bb9): (120, "SyntheticModuleMap"),
("read_only_space", 0x01c09): (165, "UncompiledDataWithoutPreparseDataMap"),
("read_only_space", 0x01c59): (166, "UncompiledDataWithPreparseDataMap"),
("read_only_space", 0x01ca9): (167, "WeakArrayListMap"),
("read_only_space", 0x01cf9): (135, "EphemeronHashTableMap"),
("read_only_space", 0x01d49): (122, "EmbedderDataArrayMap"),
("read_only_space", 0x01d99): (168, "WeakCellMap"),
("read_only_space", 0x01de9): (58, "NativeSourceStringMap"),
("read_only_space", 0x01e39): (32, "StringMap"),
("read_only_space", 0x01e89): (41, "ConsOneByteStringMap"),
("read_only_space", 0x01ed9): (33, "ConsStringMap"),
("read_only_space", 0x01f29): (45, "ThinOneByteStringMap"),
("read_only_space", 0x01f79): (37, "ThinStringMap"),
("read_only_space", 0x01fc9): (35, "SlicedStringMap"),
("read_only_space", 0x02019): (43, "SlicedOneByteStringMap"),
("read_only_space", 0x02069): (34, "ExternalStringMap"),
("read_only_space", 0x020b9): (42, "ExternalOneByteStringMap"),
("read_only_space", 0x02109): (50, "UncachedExternalStringMap"),
("read_only_space", 0x02159): (0, "InternalizedStringMap"),
("read_only_space", 0x021a9): (2, "ExternalInternalizedStringMap"),
("read_only_space", 0x021f9): (10, "ExternalOneByteInternalizedStringMap"),
("read_only_space", 0x02249): (18, "UncachedExternalInternalizedStringMap"),
("read_only_space", 0x02299): (26, "UncachedExternalOneByteInternalizedStringMap"),
("read_only_space", 0x022e9): (58, "UncachedExternalOneByteStringMap"),
("read_only_space", 0x02339): (67, "SelfReferenceMarkerMap"),
("read_only_space", 0x023a1): (87, "EnumCacheMap"),
("read_only_space", 0x02441): (82, "ArrayBoilerplateDescriptionMap"),
("read_only_space", 0x02631): (90, "InterceptorInfoMap"),
("read_only_space", 0x04ec9): (77, "AccessCheckInfoMap"),
("read_only_space", 0x04f19): (78, "AccessorInfoMap"),
("read_only_space", 0x04f69): (79, "AccessorPairMap"),
("read_only_space", 0x04fb9): (80, "AliasedArgumentsEntryMap"),
("read_only_space", 0x05009): (81, "AllocationMementoMap"),
("read_only_space", 0x05059): (83, "AsmWasmDataMap"),
("read_only_space", 0x050a9): (84, "AsyncGeneratorRequestMap"),
("read_only_space", 0x050f9): (85, "ClassPositionsMap"),
("read_only_space", 0x05149): (86, "DebugInfoMap"),
("read_only_space", 0x05199): (88, "FunctionTemplateInfoMap"),
("read_only_space", 0x051e9): (89, "FunctionTemplateRareDataMap"),
("read_only_space", 0x05239): (91, "InterpreterDataMap"),
("read_only_space", 0x05289): (92, "ObjectTemplateInfoMap"),
("read_only_space", 0x052d9): (93, "PromiseCapabilityMap"),
("read_only_space", 0x05329): (94, "PromiseReactionMap"),
("read_only_space", 0x05379): (95, "PrototypeInfoMap"),
("read_only_space", 0x053c9): (96, "ScriptMap"),
("read_only_space", 0x05419): (97, "SourcePositionTableWithFrameCacheMap"),
("read_only_space", 0x05469): (98, "SourceTextModuleInfoEntryMap"),
("read_only_space", 0x054b9): (99, "StackFrameInfoMap"),
("read_only_space", 0x05509): (100, "StackTraceFrameMap"),
("read_only_space", 0x05559): (101, "TemplateObjectDescriptionMap"),
("read_only_space", 0x055a9): (102, "Tuple2Map"),
("read_only_space", 0x055f9): (103, "Tuple3Map"),
("read_only_space", 0x05649): (104, "WasmCapiFunctionDataMap"),
("read_only_space", 0x05699): (105, "WasmDebugInfoMap"),
("read_only_space", 0x056e9): (106, "WasmExceptionTagMap"),
("read_only_space", 0x05739): (107, "WasmExportedFunctionDataMap"),
("read_only_space", 0x05789): (108, "WasmIndirectFunctionTableMap"),
("read_only_space", 0x057d9): (109, "WasmJSFunctionDataMap"),
("read_only_space", 0x05829): (110, "CallableTaskMap"),
("read_only_space", 0x05879): (111, "CallbackTaskMap"),
("read_only_space", 0x058c9): (112, "PromiseFulfillReactionJobTaskMap"),
("read_only_space", 0x05919): (113, "PromiseRejectReactionJobTaskMap"),
("read_only_space", 0x05969): (114, "PromiseResolveThenableJobTaskMap"),
("read_only_space", 0x059b9): (115, "InternalClassMap"),
("read_only_space", 0x05a09): (116, "SmiPairMap"),
("read_only_space", 0x05a59): (117, "SmiBoxMap"),
("read_only_space", 0x05aa9): (118, "SortStateMap"),
("read_only_space", 0x05af9): (121, "AllocationSiteWithWeakNextMap"),
("read_only_space", 0x05b49): (121, "AllocationSiteWithoutWeakNextMap"),
("read_only_space", 0x05b99): (156, "LoadHandler1Map"),
("read_only_space", 0x05be9): (156, "LoadHandler2Map"),
("read_only_space", 0x05c39): (156, "LoadHandler3Map"),
("read_only_space", 0x05c89): (164, "StoreHandler0Map"),
("read_only_space", 0x05cd9): (164, "StoreHandler1Map"),
("read_only_space", 0x05d29): (164, "StoreHandler2Map"),
("read_only_space", 0x05d79): (164, "StoreHandler3Map"),
("map_space", 0x00119): (1057, "ExternalMap"),
("map_space", 0x00169): (1073, "JSMessageObjectMap"),
}
# List of known V8 objects.
KNOWN_OBJECTS = {
("read_only_space", 0x001b1): "NullValue",
("read_only_space", 0x00231): "EmptyDescriptorArray",
("read_only_space", 0x00299): "EmptyWeakFixedArray",
("read_only_space", 0x00399): "UninitializedValue",
("read_only_space", 0x004a9): "UndefinedValue",
("read_only_space", 0x00529): "NanValue",
("read_only_space", 0x00589): "TheHoleValue",
("read_only_space", 0x00621): "HoleNanValue",
("read_only_space", 0x00631): "TrueValue",
("read_only_space", 0x006e1): "FalseValue",
("read_only_space", 0x00729): "empty_string",
("read_only_space", 0x00be9): "EmptyScopeInfo",
("read_only_space", 0x00bf9): "EmptyFixedArray",
("read_only_space", 0x00c09): "ArgumentsMarker",
("read_only_space", 0x00ca9): "Exception",
("read_only_space", 0x00d49): "TerminationException",
("read_only_space", 0x00df1): "OptimizedOut",
("read_only_space", 0x00e91): "StaleRegister",
("read_only_space", 0x02381): "EmptyEnumCache",
("read_only_space", 0x023e9): "EmptyPropertyArray",
("read_only_space", 0x023f9): "EmptyByteArray",
("read_only_space", 0x02409): "EmptyObjectBoilerplateDescription",
("read_only_space", 0x02421): "EmptyArrayBoilerplateDescription",
("read_only_space", 0x02489): "EmptyClosureFeedbackCellArray",
("read_only_space", 0x02499): "EmptySloppyArgumentsElements",
("read_only_space", 0x024b9): "EmptySlowElementDictionary",
("read_only_space", 0x02501): "EmptyOrderedHashMap",
("read_only_space", 0x02529): "EmptyOrderedHashSet",
("read_only_space", 0x02551): "EmptyFeedbackMetadata",
("read_only_space", 0x02561): "EmptyPropertyCell",
("read_only_space", 0x02589): "EmptyPropertyDictionary",
("read_only_space", 0x025d9): "NoOpInterceptorInfo",
("read_only_space", 0x02679): "EmptyWeakArrayList",
("read_only_space", 0x02691): "InfinityValue",
("read_only_space", 0x026a1): "MinusZeroValue",
("read_only_space", 0x026b1): "MinusInfinityValue",
("read_only_space", 0x026c1): "SelfReferenceMarker",
("read_only_space", 0x02719): "OffHeapTrampolineRelocationInfo",
("read_only_space", 0x02731): "TrampolineTrivialCodeDataContainer",
("read_only_space", 0x02749): "TrampolinePromiseRejectionCodeDataContainer",
("read_only_space", 0x02761): "GlobalThisBindingScopeInfo",
("read_only_space", 0x027c9): "EmptyFunctionScopeInfo",
("read_only_space", 0x02819): "HashSeed",
("old_space", 0x00111): "ArgumentsIteratorAccessor",
("old_space", 0x00181): "ArrayLengthAccessor",
("old_space", 0x001f1): "BoundFunctionLengthAccessor",
("old_space", 0x00261): "BoundFunctionNameAccessor",
("old_space", 0x002d1): "ErrorStackAccessor",
("old_space", 0x00341): "FunctionArgumentsAccessor",
("old_space", 0x003b1): "FunctionCallerAccessor",
("old_space", 0x00421): "FunctionNameAccessor",
("old_space", 0x00491): "FunctionLengthAccessor",
("old_space", 0x00501): "FunctionPrototypeAccessor",
("old_space", 0x00571): "RegExpResultIndicesAccessor",
("old_space", 0x005e1): "StringLengthAccessor",
("old_space", 0x00651): "InvalidPrototypeValidityCell",
("old_space", 0x00661): "EmptyScript",
("old_space", 0x006e1): "ManyClosuresCell",
("old_space", 0x006f9): "ArrayConstructorProtector",
("old_space", 0x00709): "NoElementsProtector",
("old_space", 0x00731): "IsConcatSpreadableProtector",
("old_space", 0x00741): "ArraySpeciesProtector",
("old_space", 0x00769): "TypedArraySpeciesProtector",
("old_space", 0x00791): "PromiseSpeciesProtector",
("old_space", 0x007b9): "StringLengthProtector",
("old_space", 0x007c9): "ArrayIteratorProtector",
("old_space", 0x007f1): "ArrayBufferDetachingProtector",
("old_space", 0x00819): "PromiseHookProtector",
("old_space", 0x00841): "PromiseResolveProtector",
("old_space", 0x00851): "MapIteratorProtector",
("old_space", 0x00879): "PromiseThenProtector",
("old_space", 0x008a1): "SetIteratorProtector",
("old_space", 0x008c9): "StringIteratorProtector",
("old_space", 0x008f1): "SingleCharacterStringCache",
("old_space", 0x01101): "StringSplitCache",
("old_space", 0x01911): "RegExpMultipleCache",
("old_space", 0x02121): "BuiltinsConstantsTable",
("read_only_space", 0x001b9): "NullValue",
("read_only_space", 0x00239): "EmptyDescriptorArray",
("read_only_space", 0x002a1): "EmptyWeakFixedArray",
("read_only_space", 0x003a1): "UninitializedValue",
("read_only_space", 0x004b1): "UndefinedValue",
("read_only_space", 0x00531): "NanValue",
("read_only_space", 0x00591): "TheHoleValue",
("read_only_space", 0x00629): "HoleNanValue",
("read_only_space", 0x00639): "TrueValue",
("read_only_space", 0x006e9): "FalseValue",
("read_only_space", 0x00731): "empty_string",
("read_only_space", 0x00bf1): "EmptyScopeInfo",
("read_only_space", 0x00c01): "EmptyFixedArray",
("read_only_space", 0x00c11): "ArgumentsMarker",
("read_only_space", 0x00cb1): "Exception",
("read_only_space", 0x00d51): "TerminationException",
("read_only_space", 0x00df9): "OptimizedOut",
("read_only_space", 0x00e99): "StaleRegister",
("read_only_space", 0x02389): "EmptyEnumCache",
("read_only_space", 0x023f1): "EmptyPropertyArray",
("read_only_space", 0x02401): "EmptyByteArray",
("read_only_space", 0x02411): "EmptyObjectBoilerplateDescription",
("read_only_space", 0x02429): "EmptyArrayBoilerplateDescription",
("read_only_space", 0x02491): "EmptyClosureFeedbackCellArray",
("read_only_space", 0x024a1): "EmptySloppyArgumentsElements",
("read_only_space", 0x024c1): "EmptySlowElementDictionary",
("read_only_space", 0x02509): "EmptyOrderedHashMap",
("read_only_space", 0x02531): "EmptyOrderedHashSet",
("read_only_space", 0x02559): "EmptyFeedbackMetadata",
("read_only_space", 0x02569): "EmptyPropertyCell",
("read_only_space", 0x02591): "EmptyPropertyDictionary",
("read_only_space", 0x025e1): "NoOpInterceptorInfo",
("read_only_space", 0x02681): "EmptyWeakArrayList",
("read_only_space", 0x02699): "InfinityValue",
("read_only_space", 0x026a9): "MinusZeroValue",
("read_only_space", 0x026b9): "MinusInfinityValue",
("read_only_space", 0x026c9): "SelfReferenceMarker",
("read_only_space", 0x02721): "OffHeapTrampolineRelocationInfo",
("read_only_space", 0x02739): "TrampolineTrivialCodeDataContainer",
("read_only_space", 0x02751): "TrampolinePromiseRejectionCodeDataContainer",
("read_only_space", 0x02769): "GlobalThisBindingScopeInfo",
("read_only_space", 0x027d1): "EmptyFunctionScopeInfo",
("read_only_space", 0x02821): "HashSeed",
("old_space", 0x00119): "ArgumentsIteratorAccessor",
("old_space", 0x00189): "ArrayLengthAccessor",
("old_space", 0x001f9): "BoundFunctionLengthAccessor",
("old_space", 0x00269): "BoundFunctionNameAccessor",
("old_space", 0x002d9): "ErrorStackAccessor",
("old_space", 0x00349): "FunctionArgumentsAccessor",
("old_space", 0x003b9): "FunctionCallerAccessor",
("old_space", 0x00429): "FunctionNameAccessor",
("old_space", 0x00499): "FunctionLengthAccessor",
("old_space", 0x00509): "FunctionPrototypeAccessor",
("old_space", 0x00579): "RegExpResultIndicesAccessor",
("old_space", 0x005e9): "StringLengthAccessor",
("old_space", 0x00659): "InvalidPrototypeValidityCell",
("old_space", 0x00669): "EmptyScript",
("old_space", 0x006e9): "ManyClosuresCell",
("old_space", 0x00701): "ArrayConstructorProtector",
("old_space", 0x00711): "NoElementsProtector",
("old_space", 0x00739): "IsConcatSpreadableProtector",
("old_space", 0x00749): "ArraySpeciesProtector",
("old_space", 0x00771): "TypedArraySpeciesProtector",
("old_space", 0x00799): "PromiseSpeciesProtector",
("old_space", 0x007c1): "StringLengthProtector",
("old_space", 0x007d1): "ArrayIteratorProtector",
("old_space", 0x007f9): "ArrayBufferDetachingProtector",
("old_space", 0x00821): "PromiseHookProtector",
("old_space", 0x00849): "PromiseResolveProtector",
("old_space", 0x00859): "MapIteratorProtector",
("old_space", 0x00881): "PromiseThenProtector",
("old_space", 0x008a9): "SetIteratorProtector",
("old_space", 0x008d1): "StringIteratorProtector",
("old_space", 0x008f9): "SingleCharacterStringCache",
("old_space", 0x01109): "StringSplitCache",
("old_space", 0x01919): "RegExpMultipleCache",
("old_space", 0x02129): "BuiltinsConstantsTable",
}
# List of known V8 Frame Markers.