Separate DescriptorArray from WeakFixedArray

This patch gives DescriptorArray its own visitor id and its
own layout that is independent from the layout of WeakFixedArray.
This allows us to use raw 16-bit integers for keeping track of
the number of descriptors (total, non-slack, and marked).

As a side-effect, we save one word per descriptor array on 64-bit.

v8:8486

Change-Id: If8389dde446319e5b3491abc948b52539dba235c
Reviewed-on: https://chromium-review.googlesource.com/c/1349245
Commit-Queue: Ulan Degenbaev <ulan@chromium.org>
Reviewed-by: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57845}
This commit is contained in:
Ulan Degenbaev 2018-11-26 16:40:55 +01:00 committed by Commit Bot
parent 0397f782cd
commit 1ad0cd560e
36 changed files with 589 additions and 447 deletions

View File

@ -4399,7 +4399,7 @@ MaybeLocal<Array> v8::Object::GetPropertyNames(
accumulator.GetKeys(static_cast<i::GetKeysConversion>(key_conversion));
DCHECK(self->map()->EnumLength() == i::kInvalidEnumCacheSentinel ||
self->map()->EnumLength() == 0 ||
self->map()->instance_descriptors()->GetEnumCache()->keys() != *value);
self->map()->instance_descriptors()->enum_cache()->keys() != *value);
auto result = isolate->factory()->NewJSArrayWithElements(value);
RETURN_ESCAPED(Utils::ToLocal(result));
}

View File

@ -40,6 +40,7 @@ namespace v8 {
namespace base {
typedef char Atomic8;
typedef int16_t Atomic16;
typedef int32_t Atomic32;
#if defined(V8_HOST_ARCH_64_BIT)
// We need to be able to go between Atomic64 and AtomicWord implicitly. This
@ -97,10 +98,12 @@ Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
void SeqCst_MemoryFence();
void Relaxed_Store(volatile Atomic8* ptr, Atomic8 value);
void Relaxed_Store(volatile Atomic16* ptr, Atomic16 value);
void Relaxed_Store(volatile Atomic32* ptr, Atomic32 value);
void Release_Store(volatile Atomic32* ptr, Atomic32 value);
Atomic8 Relaxed_Load(volatile const Atomic8* ptr);
Atomic16 Relaxed_Load(volatile const Atomic16* ptr);
Atomic32 Relaxed_Load(volatile const Atomic32* ptr);
Atomic32 Acquire_Load(volatile const Atomic32* ptr);

View File

@ -98,6 +98,10 @@ inline void Relaxed_Store(volatile Atomic8* ptr, Atomic8 value) {
__atomic_store_n(ptr, value, __ATOMIC_RELAXED);
}
inline void Relaxed_Store(volatile Atomic16* ptr, Atomic16 value) {
__atomic_store_n(ptr, value, __ATOMIC_RELAXED);
}
inline void Relaxed_Store(volatile Atomic32* ptr, Atomic32 value) {
__atomic_store_n(ptr, value, __ATOMIC_RELAXED);
}
@ -110,6 +114,10 @@ inline Atomic8 Relaxed_Load(volatile const Atomic8* ptr) {
return __atomic_load_n(ptr, __ATOMIC_RELAXED);
}
inline Atomic16 Relaxed_Load(volatile const Atomic16* ptr) {
return __atomic_load_n(ptr, __ATOMIC_RELAXED);
}
inline Atomic32 Relaxed_Load(volatile const Atomic32* ptr) {
return __atomic_load_n(ptr, __ATOMIC_RELAXED);
}

View File

@ -86,6 +86,11 @@ inline void Relaxed_Store(volatile Atomic8* ptr, Atomic8 value) {
std::memory_order_relaxed);
}
inline void Relaxed_Store(volatile Atomic16* ptr, Atomic16 value) {
std::atomic_store_explicit(helper::to_std_atomic(ptr), value,
std::memory_order_relaxed);
}
inline void Relaxed_Store(volatile Atomic32* ptr, Atomic32 value) {
std::atomic_store_explicit(helper::to_std_atomic(ptr), value,
std::memory_order_relaxed);
@ -101,6 +106,11 @@ inline Atomic8 Relaxed_Load(volatile const Atomic8* ptr) {
std::memory_order_relaxed);
}
inline Atomic16 Relaxed_Load(volatile const Atomic16* ptr) {
return std::atomic_load_explicit(helper::to_std_atomic_const(ptr),
std::memory_order_relaxed);
}
inline Atomic32 Relaxed_Load(volatile const Atomic32* ptr) {
return std::atomic_load_explicit(helper::to_std_atomic_const(ptr),
std::memory_order_relaxed);

View File

@ -47,12 +47,12 @@ TF_BUILTIN(FastFunctionPrototypeBind, CodeStubAssembler) {
Comment("Check descriptor array length");
TNode<DescriptorArray> descriptors = LoadMapDescriptors(receiver_map);
// Minimum descriptor array length required for fast path.
const int min_descriptors_length = DescriptorArray::LengthFor(i::Max(
JSFunction::kLengthDescriptorIndex, JSFunction::kNameDescriptorIndex));
TNode<Smi> descriptors_length = LoadWeakFixedArrayLength(descriptors);
GotoIf(SmiLessThanOrEqual(descriptors_length,
SmiConstant(min_descriptors_length)),
&slow);
const int min_nof_descriptors = i::Max(JSFunction::kLengthDescriptorIndex,
JSFunction::kNameDescriptorIndex);
TNode<Int32T> nof_descriptors = LoadNumberOfDescriptors(descriptors);
GotoIf(
Int32LessThanOrEqual(nof_descriptors, Int32Constant(min_nof_descriptors)),
&slow);
// Check whether the length and name properties are still present as
// AccessorInfo objects. In that case, their value can be recomputed even if

View File

@ -1605,6 +1605,13 @@ TNode<IntPtrT> CodeStubAssembler::LoadAndUntagWeakFixedArrayLength(
return LoadAndUntagObjectField(array, WeakFixedArray::kLengthOffset);
}
TNode<Int32T> CodeStubAssembler::LoadNumberOfDescriptors(
TNode<DescriptorArray> array) {
return UncheckedCast<Int32T>(
LoadObjectField(array, DescriptorArray::kNumberOfDescriptorsOffset,
MachineType::Int16()));
}
TNode<Int32T> CodeStubAssembler::LoadMapBitField(SloppyTNode<Map> map) {
CSA_SLOW_ASSERT(this, IsMap(map));
return UncheckedCast<Int32T>(
@ -1961,7 +1968,8 @@ TNode<IntPtrT> CodeStubAssembler::LoadArrayLength(TNode<PropertyArray> array) {
template <>
TNode<IntPtrT> CodeStubAssembler::LoadArrayLength(
TNode<DescriptorArray> array) {
return LoadAndUntagWeakFixedArrayLength(array);
return IntPtrMul(ChangeInt32ToIntPtr(LoadNumberOfDescriptors(array)),
IntPtrConstant(DescriptorArray::kEntrySize));
}
template <>
@ -8701,7 +8709,8 @@ void CodeStubAssembler::LookupLinear(TNode<Name> unique_name,
TVariable<IntPtrT>* var_name_index,
Label* if_not_found) {
static_assert(std::is_base_of<FixedArray, Array>::value ||
std::is_base_of<WeakFixedArray, Array>::value,
std::is_base_of<WeakFixedArray, Array>::value ||
std::is_base_of<DescriptorArray, Array>::value,
"T must be a descendant of FixedArray or a WeakFixedArray");
Comment("LookupLinear");
TNode<IntPtrT> first_inclusive = IntPtrConstant(Array::ToKeyIndex(0));
@ -8725,9 +8734,7 @@ void CodeStubAssembler::LookupLinear(TNode<Name> unique_name,
template <>
TNode<Uint32T> CodeStubAssembler::NumberOfEntries<DescriptorArray>(
TNode<DescriptorArray> descriptors) {
return Unsigned(LoadAndUntagToWord32ArrayElement(
descriptors, WeakFixedArray::kHeaderSize,
IntPtrConstant(DescriptorArray::kDescriptorLengthIndex)));
return Unsigned(LoadNumberOfDescriptors(descriptors));
}
template <>
@ -8780,9 +8787,9 @@ TNode<Uint32T> CodeStubAssembler::GetSortedKeyIndex<TransitionArray>(
template <typename Array>
TNode<Name> CodeStubAssembler::GetKey(TNode<Array> array,
TNode<Uint32T> entry_index) {
static_assert(std::is_base_of<FixedArray, Array>::value ||
std::is_base_of<WeakFixedArray, Array>::value,
"T must be a descendant of FixedArray or a TransitionArray");
static_assert(std::is_base_of<TransitionArray, Array>::value ||
std::is_base_of<DescriptorArray, Array>::value,
"T must be a descendant of DescriptorArray or TransitionArray");
const int key_offset = Array::ToKeyIndex(0) * kPointerSize;
TNode<MaybeObject> element =
LoadArrayElement(array, Array::kHeaderSize,
@ -13703,8 +13710,8 @@ void CodeStubAssembler::GotoIfInitialPrototypePropertiesModified(
for (int i = 0; i < properties.length(); i++) {
// Assert the descriptor index is in-bounds.
int descriptor = properties[i].descriptor_index;
CSA_ASSERT(this, SmiLessThan(SmiConstant(descriptor),
LoadWeakFixedArrayLength(descriptors)));
CSA_ASSERT(this, Int32LessThan(Int32Constant(descriptor),
LoadNumberOfDescriptors(descriptors)));
// Assert that the name is correct. This essentially checks that
// the descriptor index corresponds to the insertion order in
// the bootstrapper.

View File

@ -931,6 +931,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<Smi> LoadWeakFixedArrayLength(TNode<WeakFixedArray> array);
TNode<IntPtrT> LoadAndUntagWeakFixedArrayLength(
SloppyTNode<WeakFixedArray> array);
// Load the number of descriptors in DescriptorArray.
TNode<Int32T> LoadNumberOfDescriptors(TNode<DescriptorArray> array);
// Load the bit field of a Map.
TNode<Int32T> LoadMapBitField(SloppyTNode<Map> map);
// Load bit field 2 of a map.

View File

@ -343,10 +343,6 @@ Handle<T> Factory::NewWeakFixedArrayWithMap(RootIndex map_root_index,
template Handle<FixedArray> Factory::NewFixedArrayWithMap<FixedArray>(
RootIndex, int, PretenureFlag);
template Handle<DescriptorArray>
Factory::NewWeakFixedArrayWithMap<DescriptorArray>(RootIndex, int,
PretenureFlag);
Handle<FixedArray> Factory::NewFixedArray(int length, PretenureFlag pretenure) {
DCHECK_LE(0, length);
if (length == 0) return empty_fixed_array();
@ -1857,6 +1853,22 @@ Handle<PropertyCell> Factory::NewPropertyCell(Handle<Name> name,
return cell;
}
Handle<DescriptorArray> Factory::NewDescriptorArray(int number_of_descriptors,
int slack) {
int number_of_all_descriptors = number_of_descriptors + slack;
// Zero-length case must be handled outside.
DCHECK_LT(0, number_of_all_descriptors);
int size = DescriptorArray::SizeFor(number_of_all_descriptors);
DCHECK_LT(size, kMaxRegularHeapObjectSize);
HeapObject* obj =
isolate()->heap()->AllocateRawWithRetryOrFail(size, OLD_SPACE);
obj->set_map_after_allocation(*descriptor_array_map(), SKIP_WRITE_BARRIER);
DescriptorArray* array = DescriptorArray::cast(obj);
array->Initialize(*empty_enum_cache(), *undefined_value(),
number_of_descriptors, slack);
return Handle<DescriptorArray>(array, isolate());
}
Handle<TransitionArray> Factory::NewTransitionArray(int number_of_transitions,
int slack) {
int capacity = TransitionArray::LengthFor(number_of_transitions + slack);

View File

@ -483,6 +483,8 @@ class V8_EXPORT_PRIVATE Factory {
Handle<FeedbackCell> NewManyClosuresCell(Handle<HeapObject> value);
Handle<FeedbackCell> NewNoFeedbackCell();
Handle<DescriptorArray> NewDescriptorArray(int number_of_entries,
int slack = 0);
Handle<TransitionArray> NewTransitionArray(int number_of_transitions,
int slack = 0);

View File

@ -367,15 +367,16 @@ void MarkingVisitor<fixed_array_mode, retaining_path_mode,
// just mark the entire descriptor array.
if (!map->is_prototype_map()) {
DescriptorArray* descriptors = map->instance_descriptors();
if (MarkObjectWithoutPush(map, descriptors) && descriptors->length() > 0) {
VisitPointers(descriptors, descriptors->data_start(),
descriptors->GetDescriptorEndSlot(0));
if (MarkObjectWithoutPush(map, descriptors)) {
VisitPointers(descriptors, descriptors->GetFirstPointerSlot(),
descriptors->GetDescriptorSlot(0));
}
int start = 0;
int end = map->NumberOfOwnDescriptors();
if (start < end) {
VisitPointers(descriptors, descriptors->GetDescriptorStartSlot(start),
descriptors->GetDescriptorEndSlot(end));
VisitPointers(descriptors,
MaybeObjectSlot(descriptors->GetDescriptorSlot(start)),
MaybeObjectSlot(descriptors->GetDescriptorSlot(end)));
}
}

View File

@ -2007,6 +2007,25 @@ bool MarkCompactCollector::CompactTransitionArray(
return descriptors_owner_died;
}
void MarkCompactCollector::RightTrimDescriptorArray(DescriptorArray* array,
int descriptors_to_trim) {
int old_nof_all_descriptors = array->number_of_all_descriptors();
int new_nof_all_descriptors = old_nof_all_descriptors - descriptors_to_trim;
DCHECK_LT(0, descriptors_to_trim);
DCHECK_LE(0, new_nof_all_descriptors);
Address start = array->GetDescriptorSlot(new_nof_all_descriptors).address();
Address end = array->GetDescriptorSlot(old_nof_all_descriptors).address();
RememberedSet<OLD_TO_NEW>::RemoveRange(MemoryChunk::FromHeapObject(array),
start, end,
SlotSet::PREFREE_EMPTY_BUCKETS);
RememberedSet<OLD_TO_OLD>::RemoveRange(MemoryChunk::FromHeapObject(array),
start, end,
SlotSet::PREFREE_EMPTY_BUCKETS);
heap()->CreateFillerObjectAt(start, static_cast<int>(end - start),
ClearRecordedSlots::kNo);
array->set_number_of_all_descriptors(new_nof_all_descriptors);
}
void MarkCompactCollector::TrimDescriptorArray(Map map,
DescriptorArray* descriptors) {
int number_of_own_descriptors = map->NumberOfOwnDescriptors();
@ -2014,13 +2033,12 @@ void MarkCompactCollector::TrimDescriptorArray(Map map,
DCHECK(descriptors == ReadOnlyRoots(heap_).empty_descriptor_array());
return;
}
int number_of_descriptors = descriptors->number_of_descriptors_storage();
int to_trim = number_of_descriptors - number_of_own_descriptors;
// TODO(ulan): Trim only if slack is greater than some percentage threshold.
int to_trim =
descriptors->number_of_all_descriptors() - number_of_own_descriptors;
if (to_trim > 0) {
heap_->RightTrimWeakFixedArray(descriptors,
to_trim * DescriptorArray::kEntrySize);
descriptors->SetNumberOfDescriptors(number_of_own_descriptors);
descriptors->set_number_of_descriptors(number_of_own_descriptors);
RightTrimDescriptorArray(descriptors, to_trim);
TrimEnumCache(map, descriptors);
descriptors->Sort();
@ -2043,7 +2061,7 @@ void MarkCompactCollector::TrimEnumCache(Map map,
live_enum = map->NumberOfEnumerableProperties();
}
if (live_enum == 0) return descriptors->ClearEnumCache();
EnumCache* enum_cache = descriptors->GetEnumCache();
EnumCache* enum_cache = descriptors->enum_cache();
FixedArray keys = enum_cache->keys();
int to_trim = keys->length() - live_enum;

View File

@ -854,6 +854,9 @@ class MarkCompactCollector final : public MarkCompactCollectorBase {
int NumberOfParallelEphemeronVisitingTasks(size_t elements);
void RightTrimDescriptorArray(DescriptorArray* array,
int descriptors_to_trim);
base::Mutex mutex_;
base::Semaphore page_parallel_job_semaphore_;

View File

@ -773,7 +773,7 @@ void ObjectStatsCollectorImpl::RecordVirtualMapDetails(Map map) {
if (map->owns_descriptors() &&
array != ReadOnlyRoots(heap_).empty_descriptor_array()) {
// DescriptorArray has its own instance type.
EnumCache* enum_cache = array->GetEnumCache();
EnumCache* enum_cache = array->enum_cache();
RecordSimpleVirtualObjectStats(array, enum_cache->keys(),
ObjectStats::ENUM_CACHE_TYPE);
RecordSimpleVirtualObjectStats(array, enum_cache->indices(),

View File

@ -42,6 +42,7 @@ class WasmInstanceObject;
V(CodeDataContainer, CodeDataContainer*) \
V(ConsString, ConsString*) \
V(DataHandler, DataHandler*) \
V(DescriptorArray, DescriptorArray*) \
V(EmbedderDataArray, EmbedderDataArray) \
V(EphemeronHashTable, EphemeronHashTable) \
V(FeedbackCell, FeedbackCell*) \

View File

@ -310,19 +310,14 @@ bool Heap::CreateInitialMaps() {
// Allocate the empty descriptor array.
{
STATIC_ASSERT(DescriptorArray::kFirstIndex != 0);
int length = DescriptorArray::kFirstIndex;
int size = WeakFixedArray::SizeFor(length);
int size = DescriptorArray::SizeFor(0);
if (!AllocateRaw(size, RO_SPACE).To(&obj)) return false;
obj->set_map_after_allocation(roots.descriptor_array_map(),
SKIP_WRITE_BARRIER);
DescriptorArray::cast(obj)->set_length(length);
DescriptorArray* array = DescriptorArray::cast(obj);
array->Initialize(roots.empty_enum_cache(), roots.undefined_value(), 0, 0);
}
set_empty_descriptor_array(DescriptorArray::cast(obj));
DescriptorArray::cast(obj)->SetNumberOfDescriptors(0);
WeakFixedArray::cast(obj)->Set(
DescriptorArray::kEnumCacheIndex,
MaybeObject::FromObject(roots.empty_enum_cache()));
// Fix the instance_descriptors for the existing maps.
FinalizePartialMap(roots.meta_map());

View File

@ -285,7 +285,7 @@ Handle<FixedArray> ReduceFixedArrayTo(Isolate* isolate,
Handle<FixedArray> GetFastEnumPropertyKeys(Isolate* isolate,
Handle<JSObject> object) {
Handle<Map> map(object->map(), isolate);
Handle<FixedArray> keys(map->instance_descriptors()->GetEnumCache()->keys(),
Handle<FixedArray> keys(map->instance_descriptors()->enum_cache()->keys(),
isolate);
// Check if the {map} has a valid enum length, which implies that it
@ -351,7 +351,8 @@ Handle<FixedArray> GetFastEnumPropertyKeys(Isolate* isolate,
DCHECK_EQ(index, indices->length());
}
DescriptorArray::SetEnumCache(descriptors, isolate, keys, indices);
DescriptorArray::InitializeOrChangeEnumCache(descriptors, isolate, keys,
indices);
if (map->OnlyHasSimpleProperties()) map->SetEnumLength(enum_length);
return keys;

View File

@ -442,11 +442,13 @@ Handle<DescriptorArray> MapUpdater::BuildDescriptorArray() {
// descriptors, with minimally the exact same size as the old descriptor
// array.
int new_slack =
Max(old_nof_, old_descriptors_->number_of_descriptors()) - old_nof_;
std::max<int>(old_nof_, old_descriptors_->number_of_descriptors()) -
old_nof_;
Handle<DescriptorArray> new_descriptors =
DescriptorArray::Allocate(isolate_, old_nof_, new_slack);
DCHECK(new_descriptors->length() > target_descriptors->length() ||
new_descriptors->NumberOfSlackDescriptors() > 0 ||
DCHECK(new_descriptors->number_of_all_descriptors() >
target_descriptors->number_of_all_descriptors() ||
new_descriptors->number_of_slack_descriptors() > 0 ||
new_descriptors->number_of_descriptors() ==
old_descriptors_->number_of_descriptors());
DCHECK(new_descriptors->number_of_descriptors() == old_nof_);

View File

@ -23,6 +23,12 @@ int FlexibleBodyDescriptor<start_offset>::SizeOf(Map map, HeapObject* object) {
return object->SizeFromMap(map);
}
template <int start_offset>
int FlexibleWeakBodyDescriptor<start_offset>::SizeOf(Map map,
HeapObject* object) {
return object->SizeFromMap(map);
}
bool BodyDescriptorBase::IsValidSlotImpl(Map map, HeapObject* obj, int offset) {
if (!FLAG_unbox_double_fields || map->HasFastPointerLayout()) {
return true;
@ -381,21 +387,6 @@ class FixedTypedArrayBase::BodyDescriptor final : public BodyDescriptorBase {
}
};
class WeakArrayBodyDescriptor final : public BodyDescriptorBase {
public:
static bool IsValidSlot(Map map, HeapObject* obj, int offset) { return true; }
template <typename ObjectVisitor>
static inline void IterateBody(Map map, HeapObject* obj, int object_size,
ObjectVisitor* v) {
IterateMaybeWeakPointers(obj, HeapObject::kHeaderSize, object_size, v);
}
static inline int SizeOf(Map map, HeapObject* object) {
return object->SizeFromMap(map);
}
};
class FeedbackMetadata::BodyDescriptor final : public BodyDescriptorBase {
public:
static bool IsValidSlot(Map map, HeapObject* obj, int offset) {

View File

@ -118,6 +118,24 @@ class FlexibleBodyDescriptor final : public BodyDescriptorBase {
typedef FlexibleBodyDescriptor<HeapObject::kHeaderSize> StructBodyDescriptor;
template <int start_offset>
class FlexibleWeakBodyDescriptor final : public BodyDescriptorBase {
public:
static const int kStartOffset = start_offset;
static bool IsValidSlot(Map map, HeapObject* obj, int offset) {
return (offset >= kStartOffset);
}
template <typename ObjectVisitor>
static inline void IterateBody(Map map, HeapObject* obj, int object_size,
ObjectVisitor* v) {
IterateMaybeWeakPointers(obj, start_offset, object_size, v);
}
static inline int SizeOf(Map map, HeapObject* object);
};
// This class describes a body of an object which has a parent class that also
// has a body descriptor. This represents a union of the parent's body
// descriptor, and a new descriptor for the child -- so, both parent and child's

View File

@ -612,7 +612,7 @@ void JSObject::JSObjectVerify(Isolate* isolate) {
}
if (map()->EnumLength() != kInvalidEnumCacheSentinel) {
EnumCache* enum_cache = descriptors->GetEnumCache();
EnumCache* enum_cache = descriptors->enum_cache();
FixedArray keys = enum_cache->keys();
FixedArray indices = enum_cache->indices();
CHECK_LE(map()->EnumLength(), keys->length());
@ -769,20 +769,24 @@ void FeedbackMetadata::FeedbackMetadataVerify(Isolate* isolate) {
}
void DescriptorArray::DescriptorArrayVerify(Isolate* isolate) {
WeakFixedArrayVerify(isolate);
int nof_descriptors = number_of_descriptors();
if (number_of_descriptors_storage() == 0) {
for (int i = 0; i < number_of_all_descriptors(); i++) {
MaybeObject::VerifyMaybeObjectPointer(isolate, get(ToKeyIndex(i)));
MaybeObject::VerifyMaybeObjectPointer(isolate, get(ToDetailsIndex(i)));
MaybeObject::VerifyMaybeObjectPointer(isolate, get(ToValueIndex(i)));
}
if (number_of_all_descriptors() == 0) {
Heap* heap = isolate->heap();
CHECK_EQ(ReadOnlyRoots(heap).empty_descriptor_array(), this);
CHECK_EQ(2, length());
CHECK_EQ(0, nof_descriptors);
CHECK_EQ(ReadOnlyRoots(heap).empty_enum_cache(), GetEnumCache());
CHECK_EQ(0, number_of_all_descriptors());
CHECK_EQ(0, number_of_descriptors());
CHECK_EQ(ReadOnlyRoots(heap).empty_enum_cache(), enum_cache());
} else {
CHECK_LT(2, length());
CHECK_LE(LengthFor(nof_descriptors), length());
CHECK_LT(0, number_of_all_descriptors());
CHECK_LE(number_of_descriptors(), number_of_all_descriptors());
// Check that properties with private symbols names are non-enumerable.
for (int descriptor = 0; descriptor < nof_descriptors; descriptor++) {
for (int descriptor = 0; descriptor < number_of_descriptors();
descriptor++) {
Object* key = get(ToKeyIndex(descriptor))->cast<Object>();
// number_of_descriptors() may be out of sync with the actual descriptors
// written during descriptor array construction.

View File

@ -156,12 +156,12 @@ namespace internal {
V(WITH_CONTEXT_TYPE) \
\
V(WEAK_FIXED_ARRAY_TYPE) \
V(DESCRIPTOR_ARRAY_TYPE) \
V(TRANSITION_ARRAY_TYPE) \
\
V(CALL_HANDLER_INFO_TYPE) \
V(CELL_TYPE) \
V(CODE_DATA_CONTAINER_TYPE) \
V(DESCRIPTOR_ARRAY_TYPE) \
V(FEEDBACK_CELL_TYPE) \
V(FEEDBACK_VECTOR_TYPE) \
V(LOAD_HANDLER_TYPE) \

View File

@ -1115,22 +1115,17 @@ Address HeapObject::GetFieldAddress(int field_offset) const {
ACCESSORS2(EnumCache, keys, FixedArray, kKeysOffset)
ACCESSORS2(EnumCache, indices, FixedArray, kIndicesOffset)
int DescriptorArray::number_of_descriptors() const {
return Smi::ToInt(get(kDescriptorLengthIndex).ToSmi());
}
ACCESSORS(DescriptorArray, enum_cache, EnumCache, kEnumCacheOffset)
RELAXED_INT16_ACCESSORS(DescriptorArray, number_of_all_descriptors,
kNumberOfAllDescriptorsOffset)
RELAXED_INT16_ACCESSORS(DescriptorArray, number_of_descriptors,
kNumberOfDescriptorsOffset)
RELAXED_INT16_ACCESSORS(DescriptorArray, number_of_marked_descriptors,
kNumberOfMarkedDescriptorsOffset)
RELAXED_INT16_ACCESSORS(DescriptorArray, filler16bits, kFiller16BitsOffset)
int DescriptorArray::number_of_descriptors_storage() const {
return (length() - kFirstIndex) / kEntrySize;
}
int DescriptorArray::NumberOfSlackDescriptors() const {
return number_of_descriptors_storage() - number_of_descriptors();
}
void DescriptorArray::SetNumberOfDescriptors(int number_of_descriptors) {
set(kDescriptorLengthIndex,
MaybeObject::FromObject(Smi::FromInt(number_of_descriptors)));
inline int16_t DescriptorArray::number_of_slack_descriptors() const {
return number_of_all_descriptors() - number_of_descriptors();
}
inline int DescriptorArray::number_of_entries() const {
@ -1138,11 +1133,7 @@ inline int DescriptorArray::number_of_entries() const {
}
void DescriptorArray::CopyEnumCacheFrom(DescriptorArray* array) {
set(kEnumCacheIndex, array->get(kEnumCacheIndex));
}
EnumCache* DescriptorArray::GetEnumCache() {
return EnumCache::cast(get(kEnumCacheIndex)->GetHeapObjectAssumeStrong());
set_enum_cache(array->enum_cache());
}
// Perform a binary search in a fixed array.
@ -1193,7 +1184,6 @@ int BinarySearch(T* array, Name* name, int valid_entries,
return T::kNotFound;
}
// Perform a linear search in this fixed array. len is the number of entry
// indices that are valid.
template <SearchMode search_mode, typename T>
@ -1247,7 +1237,6 @@ int Search(T* array, Name* name, int valid_entries, int* out_insertion_index) {
out_insertion_index);
}
int DescriptorArray::Search(Name* name, int valid_descriptors) {
DCHECK(name->IsUniqueName());
return internal::Search<VALID_ENTRIES>(this, name, valid_descriptors,
@ -1277,52 +1266,48 @@ int DescriptorArray::SearchWithCache(Isolate* isolate, Name* name, Map map) {
return number;
}
ObjectSlot DescriptorArray::GetKeySlot(int descriptor_number) {
DCHECK(descriptor_number < number_of_descriptors());
DCHECK((*RawFieldOfElementAt(ToKeyIndex(descriptor_number)))->IsObject());
return ObjectSlot(RawFieldOfElementAt(ToKeyIndex(descriptor_number)));
ObjectSlot DescriptorArray::GetFirstPointerSlot() {
return ObjectSlot(
HeapObject::RawField(this, DescriptorArray::kPointersStartOffset));
}
MaybeObjectSlot DescriptorArray::GetDescriptorStartSlot(int descriptor_number) {
return MaybeObjectSlot(GetKeySlot(descriptor_number));
ObjectSlot DescriptorArray::GetDescriptorSlot(int descriptor) {
// Allow descriptor == number_of_all_descriptors() for computing the slot
// address that comes after the last descriptor (for iterating).
DCHECK_LE(descriptor, number_of_all_descriptors());
return HeapObject::RawField(this, OffsetOfDescriptorAt(descriptor));
}
MaybeObjectSlot DescriptorArray::GetDescriptorEndSlot(int descriptor_number) {
return GetValueSlot(descriptor_number - 1) + 1;
ObjectSlot DescriptorArray::GetKeySlot(int descriptor) {
DCHECK_LE(descriptor, number_of_all_descriptors());
ObjectSlot slot = GetDescriptorSlot(descriptor) + kEntryKeyIndex;
DCHECK((*slot)->IsObject());
return slot;
}
Name* DescriptorArray::GetKey(int descriptor_number) {
DCHECK(descriptor_number < number_of_descriptors());
return Name::cast(
get(ToKeyIndex(descriptor_number))->GetHeapObjectAssumeStrong());
}
int DescriptorArray::GetSortedKeyIndex(int descriptor_number) {
return GetDetails(descriptor_number).pointer();
}
Name* DescriptorArray::GetSortedKey(int descriptor_number) {
return GetKey(GetSortedKeyIndex(descriptor_number));
}
void DescriptorArray::SetSortedKey(int descriptor_index, int pointer) {
PropertyDetails details = GetDetails(descriptor_index);
set(ToDetailsIndex(descriptor_index),
MaybeObject::FromObject(details.set_pointer(pointer).AsSmi()));
}
MaybeObjectSlot DescriptorArray::GetValueSlot(int descriptor_number) {
DCHECK(descriptor_number < number_of_descriptors());
return RawFieldOfElementAt(ToValueIndex(descriptor_number));
}
int DescriptorArray::GetValueOffset(int descriptor_number) {
return OffsetOfElementAt(ToValueIndex(descriptor_number));
MaybeObjectSlot DescriptorArray::GetValueSlot(int descriptor) {
DCHECK_LT(descriptor, number_of_descriptors());
return MaybeObjectSlot(GetDescriptorSlot(descriptor) + kEntryValueIndex);
}
Object* DescriptorArray::GetStrongValue(int descriptor_number) {
@ -1330,7 +1315,6 @@ Object* DescriptorArray::GetStrongValue(int descriptor_number) {
return get(ToValueIndex(descriptor_number))->cast<Object>();
}
void DescriptorArray::SetValue(int descriptor_index, Object* value) {
set(ToValueIndex(descriptor_index), MaybeObject::FromObject(value));
}
@ -1377,7 +1361,8 @@ void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
void DescriptorArray::Append(Descriptor* desc) {
DisallowHeapAllocation no_gc;
int descriptor_number = number_of_descriptors();
SetNumberOfDescriptors(descriptor_number + 1);
DCHECK_LE(descriptor_number + 1, number_of_all_descriptors());
set_number_of_descriptors(descriptor_number + 1);
Set(descriptor_number, desc);
uint32_t hash = desc->GetKey()->Hash();
@ -1400,12 +1385,19 @@ void DescriptorArray::SwapSortedKeys(int first, int second) {
SetSortedKey(second, first_key);
}
int DescriptorArray::length() const {
return number_of_all_descriptors() * kEntrySize;
}
MaybeObject DescriptorArray::get(int index) const {
return WeakFixedArray::Get(index);
DCHECK(index >= 0 && index < this->length());
return RELAXED_READ_WEAK_FIELD(this, offset(index));
}
void DescriptorArray::set(int index, MaybeObject value) {
WeakFixedArray::Set(index, value);
DCHECK(index >= 0 && index < this->length());
RELAXED_WRITE_FIELD(this, offset(index), value);
WEAK_WRITE_BARRIER(this, offset(index), value);
}
bool StringSetShape::IsMatch(String* key, Object* value) {
@ -1553,6 +1545,11 @@ int HeapObject::SizeFromMap(Map map) const {
reinterpret_cast<const FeedbackMetadata*>(this)
->synchronized_slot_count());
}
if (instance_type == DESCRIPTOR_ARRAY_TYPE) {
return DescriptorArray::SizeFor(
reinterpret_cast<const DescriptorArray*>(this)
->number_of_all_descriptors());
}
if (IsInRange(instance_type, FIRST_WEAK_FIXED_ARRAY_TYPE,
LAST_WEAK_FIXED_ARRAY_TYPE)) {
return WeakFixedArray::SizeFor(

View File

@ -922,16 +922,15 @@ void Map::MapPrint(std::ostream& os) { // NOLINT
void DescriptorArray::DescriptorArrayPrint(std::ostream& os) {
HeapObject::PrintHeader(os, "DescriptorArray");
os << "\n - capacity: " << length();
EnumCache* enum_cache = GetEnumCache();
os << "\n - enum_cache: ";
if (enum_cache->keys()->length() == 0) {
if (enum_cache()->keys()->length() == 0) {
os << "empty";
} else {
os << enum_cache->keys()->length();
os << "\n - keys: " << Brief(enum_cache->keys());
os << "\n - indices: " << Brief(enum_cache->indices());
os << enum_cache()->keys()->length();
os << "\n - keys: " << Brief(enum_cache()->keys());
os << "\n - indices: " << Brief(enum_cache()->indices());
}
os << "\n - nof slack descriptors: " << number_of_slack_descriptors();
os << "\n - nof descriptors: " << number_of_descriptors();
PrintDescriptors(os);
}

View File

@ -3150,7 +3150,6 @@ VisitorId Map::GetVisitorId(Map map) {
case WEAK_FIXED_ARRAY_TYPE:
case WEAK_ARRAY_LIST_TYPE:
case DESCRIPTOR_ARRAY_TYPE:
return kVisitWeakArray;
case FIXED_DOUBLE_ARRAY_TYPE:
@ -3180,6 +3179,9 @@ VisitorId Map::GetVisitorId(Map map) {
case PROPERTY_CELL_TYPE:
return kVisitPropertyCell;
case DESCRIPTOR_ARRAY_TYPE:
return kVisitDescriptorArray;
case TRANSITION_ARRAY_TYPE:
return kVisitTransitionArray;
@ -3540,8 +3542,8 @@ void HeapObject::HeapObjectShortPrint(std::ostream& os) { // NOLINT
os << "<BytecodeArray[" << BytecodeArray::cast(this)->length() << "]>";
break;
case DESCRIPTOR_ARRAY_TYPE:
os << "<DescriptorArray[" << DescriptorArray::cast(this)->length()
<< "]>";
os << "<DescriptorArray["
<< DescriptorArray::cast(this)->number_of_descriptors() << "]>";
break;
case TRANSITION_ARRAY_TYPE:
os << "<TransitionArray[" << TransitionArray::cast(this)->length()
@ -5575,7 +5577,7 @@ void Map::EnsureDescriptorSlack(Isolate* isolate, Handle<Map> map, int slack) {
Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
int old_size = map->NumberOfOwnDescriptors();
if (slack <= descriptors->NumberOfSlackDescriptors()) return;
if (slack <= descriptors->number_of_slack_descriptors()) return;
Handle<DescriptorArray> new_descriptors =
DescriptorArray::CopyUpTo(isolate, descriptors, old_size, slack);
@ -6682,8 +6684,8 @@ void JSObject::MigrateSlowToFast(Handle<JSObject> object,
}
// Allocate the instance descriptor.
Handle<DescriptorArray> descriptors = DescriptorArray::Allocate(
isolate, instance_descriptor_length, 0, TENURED);
Handle<DescriptorArray> descriptors =
DescriptorArray::Allocate(isolate, instance_descriptor_length, 0);
int number_of_allocated_fields =
number_of_fields + unused_property_fields - inobject_props;
@ -9536,7 +9538,7 @@ Handle<Map> Map::ShareDescriptor(Isolate* isolate, Handle<Map> map,
}
// Ensure there's space for the new descriptor in the shared descriptor array.
if (descriptors->NumberOfSlackDescriptors() == 0) {
if (descriptors->number_of_slack_descriptors() == 0) {
int old_size = descriptors->number_of_descriptors();
if (old_size == 0) {
descriptors = DescriptorArray::Allocate(isolate, 0, 1);
@ -10722,28 +10724,30 @@ Handle<FrameArray> FrameArray::EnsureSpace(Isolate* isolate,
}
Handle<DescriptorArray> DescriptorArray::Allocate(Isolate* isolate,
int number_of_descriptors,
int slack,
PretenureFlag pretenure) {
DCHECK_LE(0, number_of_descriptors);
Factory* factory = isolate->factory();
// Do not use DescriptorArray::cast on incomplete object.
int size = number_of_descriptors + slack;
if (size == 0) return factory->empty_descriptor_array();
// Allocate the array of keys.
Handle<WeakFixedArray> result =
factory->NewWeakFixedArrayWithMap<DescriptorArray>(
RootIndex::kDescriptorArrayMap, LengthFor(size), pretenure);
result->Set(kDescriptorLengthIndex,
MaybeObject::FromObject(Smi::FromInt(number_of_descriptors)));
result->Set(kEnumCacheIndex, MaybeObject::FromObject(
ReadOnlyRoots(isolate).empty_enum_cache()));
return Handle<DescriptorArray>::cast(result);
int nof_descriptors,
int slack) {
return nof_descriptors + slack == 0
? isolate->factory()->empty_descriptor_array()
: isolate->factory()->NewDescriptorArray(nof_descriptors, slack);
}
void DescriptorArray::Initialize(EnumCache* enum_cache,
HeapObject* undefined_value,
int nof_descriptors, int slack) {
DCHECK_GE(nof_descriptors, 0);
DCHECK_GE(slack, 0);
DCHECK_LE(nof_descriptors + slack, kMaxNumberOfDescriptors);
set_number_of_all_descriptors(nof_descriptors + slack);
set_number_of_descriptors(nof_descriptors);
set_number_of_marked_descriptors(0);
set_filler16bits(0);
set_enum_cache(enum_cache);
MemsetPointer(GetDescriptorSlot(0), undefined_value,
number_of_all_descriptors() * kEntrySize);
}
void DescriptorArray::ClearEnumCache() {
set(kEnumCacheIndex,
MaybeObject::FromObject(GetReadOnlyRoots().empty_enum_cache()));
set_enum_cache(GetReadOnlyRoots().empty_enum_cache());
}
void DescriptorArray::Replace(int index, Descriptor* descriptor) {
@ -10752,13 +10756,13 @@ void DescriptorArray::Replace(int index, Descriptor* descriptor) {
}
// static
void DescriptorArray::SetEnumCache(Handle<DescriptorArray> descriptors,
Isolate* isolate, Handle<FixedArray> keys,
Handle<FixedArray> indices) {
EnumCache* enum_cache = descriptors->GetEnumCache();
void DescriptorArray::InitializeOrChangeEnumCache(
Handle<DescriptorArray> descriptors, Isolate* isolate,
Handle<FixedArray> keys, Handle<FixedArray> indices) {
EnumCache* enum_cache = descriptors->enum_cache();
if (enum_cache == ReadOnlyRoots(isolate).empty_enum_cache()) {
enum_cache = *isolate->factory()->NewEnumCache(keys, indices);
descriptors->set(kEnumCacheIndex, MaybeObject::FromObject(enum_cache));
descriptors->set_enum_cache(enum_cache);
} else {
enum_cache->set_keys(*keys);
enum_cache->set_indices(*indices);
@ -10869,8 +10873,9 @@ SharedFunctionInfo* DeoptimizationData::GetInlinedFunction(int index) {
#ifdef DEBUG
bool DescriptorArray::IsEqualTo(DescriptorArray* other) {
if (length() != other->length()) return false;
for (int i = 0; i < length(); ++i) {
if (number_of_all_descriptors() != other->number_of_all_descriptors())
return false;
for (int i = 0; i < number_of_all_descriptors(); ++i) {
if (get(i) != other->get(i)) return false;
}
return true;

View File

@ -85,7 +85,6 @@
// - ByteArray
// - BytecodeArray
// - FixedArray
// - DescriptorArray
// - FrameArray
// - HashTable
// - Dictionary
@ -127,6 +126,7 @@
// - HeapNumber
// - BigInt
// - Cell
// - DescriptorArray
// - PropertyCell
// - PropertyArray
// - Code
@ -1226,6 +1226,9 @@ class FixedBodyDescriptor;
template <int start_offset>
class FlexibleBodyDescriptor;
template <int start_offset>
class FlexibleWeakBodyDescriptor;
template <class ParentBodyDescriptor, class ChildBodyDescriptor>
class SubclassBodyDescriptor;

View File

@ -36,47 +36,43 @@ class EnumCache : public Tuple2 {
DISALLOW_IMPLICIT_CONSTRUCTORS(EnumCache);
};
// A DescriptorArray is a fixed array used to hold instance descriptors.
// The format of these objects is:
// [0]: Number of descriptors
// [1]: Enum cache.
// [2]: first key (and internalized String)
// [3]: first descriptor details (see PropertyDetails)
// [4]: first value for constants | Smi(1) when not used
//
// [2 + number of descriptors * 3]: start of slack
// A DescriptorArray is a custom array that holds instance descriptors.
// It has the following layout:
// Header:
// [16:0 bits]: number_of_all_descriptors (including slack)
// [32:16 bits]: number_of_descriptors
// [48:32 bits]: number_of_marked_descriptors (used by GC)
// [64:48 bits]: alignment filler
// [kEnumCacheOffset]: enum cache
// Elements:
// [kHeaderSize + 0]: first key (and internalized String)
// [kHeaderSize + 1]: first descriptor details (see PropertyDetails)
// [kHeaderSize + 2]: first value for constants / Smi(1) when not used
// Slack:
// [kHeaderSize + number of descriptors * 3]: start of slack
// The "value" fields store either values or field types. A field type is either
// FieldType::None(), FieldType::Any() or a weak reference to a Map. All other
// references are strong.
class DescriptorArray : public WeakFixedArray {
class DescriptorArray : public HeapObject {
public:
// Returns the number of descriptors in the array.
inline int number_of_descriptors() const;
inline int number_of_descriptors_storage() const;
inline int NumberOfSlackDescriptors() const;
inline void SetNumberOfDescriptors(int number_of_descriptors);
DECL_INT16_ACCESSORS(number_of_all_descriptors)
DECL_INT16_ACCESSORS(number_of_descriptors)
inline int16_t number_of_slack_descriptors() const;
inline int number_of_entries() const;
inline EnumCache* GetEnumCache();
DECL_ACCESSORS(enum_cache, EnumCache)
void ClearEnumCache();
inline void CopyEnumCacheFrom(DescriptorArray* array);
// Initialize or change the enum cache,
static void SetEnumCache(Handle<DescriptorArray> descriptors,
Isolate* isolate, Handle<FixedArray> keys,
Handle<FixedArray> indices);
static void InitializeOrChangeEnumCache(Handle<DescriptorArray> descriptors,
Isolate* isolate,
Handle<FixedArray> keys,
Handle<FixedArray> indices);
// Accessors for fetching instance descriptor at descriptor number.
inline Name* GetKey(int descriptor_number);
inline ObjectSlot GetKeySlot(int descriptor_number);
inline Object* GetStrongValue(int descriptor_number);
inline void SetValue(int descriptor_number, Object* value);
inline MaybeObject GetValue(int descriptor_number);
inline MaybeObjectSlot GetValueSlot(int descriptor_number);
static inline int GetValueOffset(int descriptor_number);
inline MaybeObjectSlot GetDescriptorStartSlot(int descriptor_number);
inline MaybeObjectSlot GetDescriptorEndSlot(int descriptor_number);
inline PropertyDetails GetDetails(int descriptor_number);
inline int GetFieldIndex(int descriptor_number);
inline FieldType GetFieldType(int descriptor_number);
@ -127,30 +123,49 @@ class DescriptorArray : public WeakFixedArray {
// Allocates a DescriptorArray, but returns the singleton
// empty descriptor array object if number_of_descriptors is 0.
static Handle<DescriptorArray> Allocate(
Isolate* isolate, int number_of_descriptors, int slack,
PretenureFlag pretenure = NOT_TENURED);
static Handle<DescriptorArray> Allocate(Isolate* isolate, int nof_descriptors,
int slack);
void Initialize(EnumCache* enum_cache, HeapObject* undefined_value,
int nof_descriptors, int slack);
DECL_CAST(DescriptorArray)
// Constant for denoting key was not found.
static const int kNotFound = -1;
static const int kDescriptorLengthIndex = 0;
static const int kEnumCacheIndex = 1;
static const int kFirstIndex = 2;
// Layout description.
#define DESCRIPTOR_ARRAY_FIELDS(V) \
V(kDescriptorLengthOffset, kTaggedSize) \
V(kEnumCacheOffset, kTaggedSize) \
/* Header size. */ \
V(kFirstOffset, 0)
#define DESCRIPTOR_ARRAY_FIELDS(V) \
V(kNumberOfAllDescriptorsOffset, kUInt16Size) \
V(kNumberOfDescriptorsOffset, kUInt16Size) \
V(kNumberOfMarkedDescriptorsOffset, kUInt16Size) \
V(kFiller16BitsOffset, kUInt16Size) \
V(kPointersStartOffset, 0) \
V(kEnumCacheOffset, kTaggedSize) \
V(kHeaderSize, 0)
DEFINE_FIELD_OFFSET_CONSTANTS(FixedArray::kHeaderSize,
DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize,
DESCRIPTOR_ARRAY_FIELDS)
#undef DESCRIPTOR_ARRAY_FIELDS
STATIC_ASSERT(IsAligned(kPointersStartOffset, kTaggedSize));
STATIC_ASSERT(IsAligned(kHeaderSize, kTaggedSize));
// Garbage collection support.
DECL_INT16_ACCESSORS(number_of_marked_descriptors)
static constexpr int SizeFor(int number_of_all_descriptors) {
return offset(number_of_all_descriptors * kEntrySize);
}
static constexpr int OffsetOfDescriptorAt(int descriptor) {
return offset(descriptor * kEntrySize);
}
inline ObjectSlot GetFirstPointerSlot();
inline ObjectSlot GetDescriptorSlot(int descriptor);
inline ObjectSlot GetKeySlot(int descriptor);
inline MaybeObjectSlot GetValueSlot(int descriptor);
typedef FlexibleWeakBodyDescriptor<kPointersStartOffset> BodyDescriptor;
// Layout of descriptor.
// Naming is consistent with Dictionary classes for easy templating.
static const int kEntryKeyIndex = 0;
@ -174,26 +189,26 @@ class DescriptorArray : public WeakFixedArray {
bool IsEqualTo(DescriptorArray* other);
#endif
// Returns the fixed array length required to hold number_of_descriptors
// descriptors.
static constexpr int LengthFor(int number_of_descriptors) {
return ToKeyIndex(number_of_descriptors);
}
static constexpr int ToDetailsIndex(int descriptor_number) {
return kFirstIndex + (descriptor_number * kEntrySize) + kEntryDetailsIndex;
return (descriptor_number * kEntrySize) + kEntryDetailsIndex;
}
// Conversion from descriptor number to array indices.
static constexpr int ToKeyIndex(int descriptor_number) {
return kFirstIndex + (descriptor_number * kEntrySize) + kEntryKeyIndex;
return (descriptor_number * kEntrySize) + kEntryKeyIndex;
}
static constexpr int ToValueIndex(int descriptor_number) {
return kFirstIndex + (descriptor_number * kEntrySize) + kEntryValueIndex;
return (descriptor_number * kEntrySize) + kEntryValueIndex;
}
private:
DECL_INT16_ACCESSORS(filler16bits)
// Low-level per-element accessors.
static constexpr int offset(int index) {
return kHeaderSize + index * kPointerSize;
}
inline int length() const;
inline MaybeObject get(int index) const;
inline void set(int index, MaybeObject value);

View File

@ -15,8 +15,8 @@
namespace v8 {
namespace internal {
class WeakArrayBodyDescriptor;
typedef FlexibleWeakBodyDescriptor<HeapObject::kHeaderSize>
WeakArrayBodyDescriptor;
#define FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(V) \
V(BYTECODE_ARRAY_CONSTANT_POOL_SUB_TYPE) \
@ -369,7 +369,6 @@ class WeakArrayList : public HeapObject, public NeverReadOnlySpaceObject {
inline int synchronized_capacity() const;
inline void synchronized_set_capacity(int value);
typedef WeakArrayBodyDescriptor BodyDescriptor;
// Layout description.
#define WEAK_ARRAY_LIST_FIELDS(V) \
@ -381,6 +380,8 @@ class WeakArrayList : public HeapObject, public NeverReadOnlySpaceObject {
DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, WEAK_ARRAY_LIST_FIELDS)
#undef WEAK_ARRAY_LIST_FIELDS
typedef WeakArrayBodyDescriptor BodyDescriptor;
static const int kMaxCapacity =
(FixedArray::kMaxSize - kHeaderSize) / kTaggedSize;

View File

@ -229,13 +229,13 @@ enum InstanceType : uint16_t {
WITH_CONTEXT_TYPE, // LAST_FIXED_ARRAY_TYPE, LAST_CONTEXT_TYPE
WEAK_FIXED_ARRAY_TYPE, // FIRST_WEAK_FIXED_ARRAY_TYPE
DESCRIPTOR_ARRAY_TYPE,
TRANSITION_ARRAY_TYPE, // LAST_WEAK_FIXED_ARRAY_TYPE
// Misc.
CALL_HANDLER_INFO_TYPE,
CELL_TYPE,
CODE_DATA_CONTAINER_TYPE,
DESCRIPTOR_ARRAY_TYPE,
FEEDBACK_CELL_TYPE,
FEEDBACK_VECTOR_TYPE,
LOAD_HANDLER_TYPE,

View File

@ -29,6 +29,7 @@ enum InstanceType : uint16_t;
V(ConsString) \
V(DataHandler) \
V(DataObject) \
V(DescriptorArray) \
V(EmbedderDataArray) \
V(EphemeronHashTable) \
V(FeedbackCell) \

View File

@ -56,6 +56,10 @@
inline uint16_t name() const; \
inline void set_##name(int value);
#define DECL_INT16_ACCESSORS(name) \
inline int16_t name() const; \
inline void set_##name(int16_t value);
#define DECL_UINT8_ACCESSORS(name) \
inline uint8_t name() const; \
inline void set_##name(int value);
@ -282,6 +286,14 @@
return InstanceTypeChecker::Is##type(map()->instance_type()); \
}
#define RELAXED_INT16_ACCESSORS(holder, name, offset) \
int16_t holder::name() const { \
return RELAXED_READ_INT16_FIELD(this, offset); \
} \
void holder::set_##name(int16_t value) { \
RELAXED_WRITE_INT16_FIELD(this, offset, value); \
}
#define FIELD_ADDR(p, offset) ((p)->ptr() + offset - kHeapObjectTag)
#define READ_FIELD(p, offset) \
@ -437,6 +449,15 @@
#define WRITE_INT16_FIELD(p, offset, value) \
(*reinterpret_cast<int16_t*>(FIELD_ADDR(p, offset)) = value)
#define RELAXED_READ_INT16_FIELD(p, offset) \
static_cast<int16_t>(base::Relaxed_Load( \
reinterpret_cast<const base::Atomic16*>(FIELD_ADDR(p, offset))))
#define RELAXED_WRITE_INT16_FIELD(p, offset, value) \
base::Relaxed_Store( \
reinterpret_cast<base::Atomic16*>(FIELD_ADDR(p, offset)), \
static_cast<base::Atomic16>(value));
#define READ_UINT32_FIELD(p, offset) \
(*reinterpret_cast<const uint32_t*>(FIELD_ADDR(p, offset)))

View File

@ -756,6 +756,8 @@ void V8HeapExplorer::ExtractReferences(HeapEntry* entry, HeapObject* obj) {
entry, ArrayBoilerplateDescription::cast(obj));
} else if (obj->IsFeedbackVector()) {
ExtractFeedbackVectorReferences(entry, FeedbackVector::cast(obj));
} else if (obj->IsDescriptorArray()) {
ExtractDescriptorArrayReferences(entry, DescriptorArray::cast(obj));
} else if (obj->IsWeakFixedArray()) {
ExtractWeakArrayReferences(WeakFixedArray::kHeaderSize, entry,
WeakFixedArray::cast(obj));
@ -1240,6 +1242,26 @@ void V8HeapExplorer::ExtractFeedbackVectorReferences(
}
}
void V8HeapExplorer::ExtractDescriptorArrayReferences(HeapEntry* entry,
DescriptorArray* array) {
SetInternalReference(entry, "enum_cache", array->enum_cache(),
DescriptorArray::kEnumCacheOffset);
MaybeObjectSlot start = MaybeObjectSlot(array->GetDescriptorSlot(0));
MaybeObjectSlot end = MaybeObjectSlot(
array->GetDescriptorSlot(array->number_of_all_descriptors()));
for (int i = 0; start + i < end; ++i) {
MaybeObjectSlot slot = start + i;
int offset = static_cast<int>(slot.address() - array->address());
MaybeObject object = *slot;
HeapObject* heap_object;
if (object->GetHeapObjectIfWeak(&heap_object)) {
SetWeakReference(entry, i, heap_object, offset);
} else if (object->GetHeapObjectIfStrong(&heap_object)) {
SetInternalReference(entry, i, heap_object, offset);
}
}
}
template <typename T>
void V8HeapExplorer::ExtractWeakArrayReferences(int header_size,
HeapEntry* entry, T* array) {

View File

@ -378,6 +378,8 @@ class V8HeapExplorer : public HeapEntriesAllocator {
void ExtractFixedArrayReferences(HeapEntry* entry, FixedArray array);
void ExtractFeedbackVectorReferences(HeapEntry* entry,
FeedbackVector* feedback_vector);
void ExtractDescriptorArrayReferences(HeapEntry* entry,
DescriptorArray* array);
template <typename T>
void ExtractWeakArrayReferences(int header_size, HeapEntry* entry, T* array);
void ExtractPropertyReferences(JSObject* js_obj, HeapEntry* entry);

View File

@ -2206,12 +2206,12 @@ TEST(AccessorInfo) {
env->GetIsolate(), map, v8::HeapGraphEdge::kInternal, "descriptors");
CHECK(descriptors);
const v8::HeapGraphNode* length_name = GetProperty(
env->GetIsolate(), descriptors, v8::HeapGraphEdge::kInternal, "2");
env->GetIsolate(), descriptors, v8::HeapGraphEdge::kInternal, "0");
CHECK(length_name);
CHECK_EQ(0, strcmp("length", *v8::String::Utf8Value(env->GetIsolate(),
length_name->GetName())));
const v8::HeapGraphNode* length_accessor = GetProperty(
env->GetIsolate(), descriptors, v8::HeapGraphEdge::kInternal, "4");
env->GetIsolate(), descriptors, v8::HeapGraphEdge::kInternal, "2");
CHECK(length_accessor);
CHECK_EQ(0, strcmp("system / AccessorInfo",
*v8::String::Utf8Value(env->GetIsolate(),

View File

@ -123,13 +123,13 @@ TEST(EnumCache) {
CHECK_EQ(cc->map()->EnumLength(), kInvalidEnumCacheSentinel);
// Check that the EnumCache is empty.
CHECK_EQ(a->map()->instance_descriptors()->GetEnumCache(),
CHECK_EQ(a->map()->instance_descriptors()->enum_cache(),
*factory->empty_enum_cache());
CHECK_EQ(b->map()->instance_descriptors()->GetEnumCache(),
CHECK_EQ(b->map()->instance_descriptors()->enum_cache(),
*factory->empty_enum_cache());
CHECK_EQ(c->map()->instance_descriptors()->GetEnumCache(),
CHECK_EQ(c->map()->instance_descriptors()->enum_cache(),
*factory->empty_enum_cache());
CHECK_EQ(cc->map()->instance_descriptors()->GetEnumCache(),
CHECK_EQ(cc->map()->instance_descriptors()->enum_cache(),
*factory->empty_enum_cache());
// The EnumCache is shared on the DescriptorArray, creating it on {cc} has no
@ -141,14 +141,14 @@ TEST(EnumCache) {
CHECK_EQ(c->map()->EnumLength(), kInvalidEnumCacheSentinel);
CHECK_EQ(cc->map()->EnumLength(), 3);
CHECK_EQ(a->map()->instance_descriptors()->GetEnumCache(),
CHECK_EQ(a->map()->instance_descriptors()->enum_cache(),
*factory->empty_enum_cache());
CHECK_EQ(b->map()->instance_descriptors()->GetEnumCache(),
CHECK_EQ(b->map()->instance_descriptors()->enum_cache(),
*factory->empty_enum_cache());
CHECK_EQ(c->map()->instance_descriptors()->GetEnumCache(),
CHECK_EQ(c->map()->instance_descriptors()->enum_cache(),
*factory->empty_enum_cache());
EnumCache* enum_cache = cc->map()->instance_descriptors()->GetEnumCache();
EnumCache* enum_cache = cc->map()->instance_descriptors()->enum_cache();
CHECK_NE(enum_cache, *factory->empty_enum_cache());
CHECK_EQ(enum_cache->keys()->length(), 3);
CHECK_EQ(enum_cache->indices()->length(), 3);
@ -165,14 +165,14 @@ TEST(EnumCache) {
// The enum cache is shared on the descriptor array of maps {a}, {b} and
// {c} only.
EnumCache* enum_cache = a->map()->instance_descriptors()->GetEnumCache();
EnumCache* enum_cache = a->map()->instance_descriptors()->enum_cache();
CHECK_NE(enum_cache, *factory->empty_enum_cache());
CHECK_NE(cc->map()->instance_descriptors()->GetEnumCache(),
CHECK_NE(cc->map()->instance_descriptors()->enum_cache(),
*factory->empty_enum_cache());
CHECK_NE(cc->map()->instance_descriptors()->GetEnumCache(), enum_cache);
CHECK_EQ(a->map()->instance_descriptors()->GetEnumCache(), enum_cache);
CHECK_EQ(b->map()->instance_descriptors()->GetEnumCache(), enum_cache);
CHECK_EQ(c->map()->instance_descriptors()->GetEnumCache(), enum_cache);
CHECK_NE(cc->map()->instance_descriptors()->enum_cache(), enum_cache);
CHECK_EQ(a->map()->instance_descriptors()->enum_cache(), enum_cache);
CHECK_EQ(b->map()->instance_descriptors()->enum_cache(), enum_cache);
CHECK_EQ(c->map()->instance_descriptors()->enum_cache(), enum_cache);
CHECK_EQ(enum_cache->keys()->length(), 1);
CHECK_EQ(enum_cache->indices()->length(), 1);
@ -181,7 +181,7 @@ TEST(EnumCache) {
// Creating the EnumCache for {c} will create a new EnumCache on the shared
// DescriptorArray.
Handle<EnumCache> previous_enum_cache(
a->map()->instance_descriptors()->GetEnumCache(), a->GetIsolate());
a->map()->instance_descriptors()->enum_cache(), a->GetIsolate());
Handle<FixedArray> previous_keys(previous_enum_cache->keys(),
a->GetIsolate());
Handle<FixedArray> previous_indices(previous_enum_cache->indices(),
@ -193,7 +193,7 @@ TEST(EnumCache) {
CHECK_EQ(c->map()->EnumLength(), 3);
CHECK_EQ(cc->map()->EnumLength(), 3);
EnumCache* enum_cache = c->map()->instance_descriptors()->GetEnumCache();
EnumCache* enum_cache = c->map()->instance_descriptors()->enum_cache();
CHECK_NE(enum_cache, *factory->empty_enum_cache());
// The keys and indices caches are updated.
CHECK_EQ(enum_cache, *previous_enum_cache);
@ -206,20 +206,20 @@ TEST(EnumCache) {
// The enum cache is shared on the descriptor array of maps {a}, {b} and
// {c} only.
CHECK_NE(cc->map()->instance_descriptors()->GetEnumCache(),
CHECK_NE(cc->map()->instance_descriptors()->enum_cache(),
*factory->empty_enum_cache());
CHECK_NE(cc->map()->instance_descriptors()->GetEnumCache(), enum_cache);
CHECK_NE(cc->map()->instance_descriptors()->GetEnumCache(),
CHECK_NE(cc->map()->instance_descriptors()->enum_cache(), enum_cache);
CHECK_NE(cc->map()->instance_descriptors()->enum_cache(),
*previous_enum_cache);
CHECK_EQ(a->map()->instance_descriptors()->GetEnumCache(), enum_cache);
CHECK_EQ(b->map()->instance_descriptors()->GetEnumCache(), enum_cache);
CHECK_EQ(c->map()->instance_descriptors()->GetEnumCache(), enum_cache);
CHECK_EQ(a->map()->instance_descriptors()->enum_cache(), enum_cache);
CHECK_EQ(b->map()->instance_descriptors()->enum_cache(), enum_cache);
CHECK_EQ(c->map()->instance_descriptors()->enum_cache(), enum_cache);
}
// {b} can reuse the existing EnumCache, hence we only need to set the correct
// EnumLength on the map without modifying the cache itself.
previous_enum_cache =
handle(a->map()->instance_descriptors()->GetEnumCache(), a->GetIsolate());
handle(a->map()->instance_descriptors()->enum_cache(), a->GetIsolate());
previous_keys = handle(previous_enum_cache->keys(), a->GetIsolate());
previous_indices = handle(previous_enum_cache->indices(), a->GetIsolate());
CompileRun("var s = 0; for (let key in b) { s += b[key] };");
@ -229,7 +229,7 @@ TEST(EnumCache) {
CHECK_EQ(c->map()->EnumLength(), 3);
CHECK_EQ(cc->map()->EnumLength(), 3);
EnumCache* enum_cache = c->map()->instance_descriptors()->GetEnumCache();
EnumCache* enum_cache = c->map()->instance_descriptors()->enum_cache();
CHECK_NE(enum_cache, *factory->empty_enum_cache());
// The keys and indices caches are not updated.
CHECK_EQ(enum_cache, *previous_enum_cache);
@ -240,14 +240,14 @@ TEST(EnumCache) {
// The enum cache is shared on the descriptor array of maps {a}, {b} and
// {c} only.
CHECK_NE(cc->map()->instance_descriptors()->GetEnumCache(),
CHECK_NE(cc->map()->instance_descriptors()->enum_cache(),
*factory->empty_enum_cache());
CHECK_NE(cc->map()->instance_descriptors()->GetEnumCache(), enum_cache);
CHECK_NE(cc->map()->instance_descriptors()->GetEnumCache(),
CHECK_NE(cc->map()->instance_descriptors()->enum_cache(), enum_cache);
CHECK_NE(cc->map()->instance_descriptors()->enum_cache(),
*previous_enum_cache);
CHECK_EQ(a->map()->instance_descriptors()->GetEnumCache(), enum_cache);
CHECK_EQ(b->map()->instance_descriptors()->GetEnumCache(), enum_cache);
CHECK_EQ(c->map()->instance_descriptors()->GetEnumCache(), enum_cache);
CHECK_EQ(a->map()->instance_descriptors()->enum_cache(), enum_cache);
CHECK_EQ(b->map()->instance_descriptors()->enum_cache(), enum_cache);
CHECK_EQ(c->map()->instance_descriptors()->enum_cache(), enum_cache);
}
}

View File

@ -94,8 +94,6 @@ consts_misc = [
{ 'name': 'OddballOther', 'value': 'Oddball::kOther' },
{ 'name': 'OddballException', 'value': 'Oddball::kException' },
{ 'name': 'prop_idx_first',
'value': 'DescriptorArray::kFirstIndex' },
{ 'name': 'prop_kind_Data',
'value': 'kData' },
{ 'name': 'prop_kind_Accessor',

View File

@ -113,11 +113,11 @@ INSTANCE_TYPES = {
209: "SCRIPT_CONTEXT_TYPE",
210: "WITH_CONTEXT_TYPE",
211: "WEAK_FIXED_ARRAY_TYPE",
212: "DESCRIPTOR_ARRAY_TYPE",
213: "TRANSITION_ARRAY_TYPE",
214: "CALL_HANDLER_INFO_TYPE",
215: "CELL_TYPE",
216: "CODE_DATA_CONTAINER_TYPE",
212: "TRANSITION_ARRAY_TYPE",
213: "CALL_HANDLER_INFO_TYPE",
214: "CELL_TYPE",
215: "CODE_DATA_CONTAINER_TYPE",
216: "DESCRIPTOR_ARRAY_TYPE",
217: "FEEDBACK_CELL_TYPE",
218: "FEEDBACK_VECTOR_TYPE",
219: "LOAD_HANDLER_TYPE",
@ -196,155 +196,155 @@ KNOWN_MAPS = {
("RO_SPACE", 0x00139): (138, "FreeSpaceMap"),
("RO_SPACE", 0x00189): (132, "MetaMap"),
("RO_SPACE", 0x00209): (131, "NullMap"),
("RO_SPACE", 0x00279): (212, "DescriptorArrayMap"),
("RO_SPACE", 0x002d9): (211, "WeakFixedArrayMap"),
("RO_SPACE", 0x00329): (152, "OnePointerFillerMap"),
("RO_SPACE", 0x00379): (152, "TwoPointerFillerMap"),
("RO_SPACE", 0x003f9): (131, "UninitializedMap"),
("RO_SPACE", 0x00469): (8, "OneByteInternalizedStringMap"),
("RO_SPACE", 0x00509): (131, "UndefinedMap"),
("RO_SPACE", 0x00569): (129, "HeapNumberMap"),
("RO_SPACE", 0x005e9): (131, "TheHoleMap"),
("RO_SPACE", 0x00691): (131, "BooleanMap"),
("RO_SPACE", 0x00769): (136, "ByteArrayMap"),
("RO_SPACE", 0x007b9): (187, "FixedArrayMap"),
("RO_SPACE", 0x00809): (187, "FixedCOWArrayMap"),
("RO_SPACE", 0x00859): (189, "HashTableMap"),
("RO_SPACE", 0x008a9): (128, "SymbolMap"),
("RO_SPACE", 0x008f9): (72, "OneByteStringMap"),
("RO_SPACE", 0x00949): (199, "ScopeInfoMap"),
("RO_SPACE", 0x00999): (223, "SharedFunctionInfoMap"),
("RO_SPACE", 0x009e9): (133, "CodeMap"),
("RO_SPACE", 0x00a39): (206, "FunctionContextMap"),
("RO_SPACE", 0x00a89): (215, "CellMap"),
("RO_SPACE", 0x00ad9): (222, "GlobalPropertyCellMap"),
("RO_SPACE", 0x00b29): (135, "ForeignMap"),
("RO_SPACE", 0x00b79): (213, "TransitionArrayMap"),
("RO_SPACE", 0x00bc9): (218, "FeedbackVectorMap"),
("RO_SPACE", 0x00c69): (131, "ArgumentsMarkerMap"),
("RO_SPACE", 0x00d09): (131, "ExceptionMap"),
("RO_SPACE", 0x00da9): (131, "TerminationExceptionMap"),
("RO_SPACE", 0x00e51): (131, "OptimizedOutMap"),
("RO_SPACE", 0x00ef1): (131, "StaleRegisterMap"),
("RO_SPACE", 0x00f61): (208, "NativeContextMap"),
("RO_SPACE", 0x00fb1): (207, "ModuleContextMap"),
("RO_SPACE", 0x01001): (205, "EvalContextMap"),
("RO_SPACE", 0x01051): (209, "ScriptContextMap"),
("RO_SPACE", 0x010a1): (201, "AwaitContextMap"),
("RO_SPACE", 0x010f1): (202, "BlockContextMap"),
("RO_SPACE", 0x01141): (203, "CatchContextMap"),
("RO_SPACE", 0x01191): (210, "WithContextMap"),
("RO_SPACE", 0x011e1): (204, "DebugEvaluateContextMap"),
("RO_SPACE", 0x01231): (200, "ScriptContextTableMap"),
("RO_SPACE", 0x01281): (151, "FeedbackMetadataArrayMap"),
("RO_SPACE", 0x012d1): (187, "ArrayListMap"),
("RO_SPACE", 0x01321): (130, "BigIntMap"),
("RO_SPACE", 0x01371): (188, "ObjectBoilerplateDescriptionMap"),
("RO_SPACE", 0x013c1): (137, "BytecodeArrayMap"),
("RO_SPACE", 0x01411): (216, "CodeDataContainerMap"),
("RO_SPACE", 0x01461): (150, "FixedDoubleArrayMap"),
("RO_SPACE", 0x014b1): (194, "GlobalDictionaryMap"),
("RO_SPACE", 0x01501): (217, "ManyClosuresCellMap"),
("RO_SPACE", 0x01551): (187, "ModuleInfoMap"),
("RO_SPACE", 0x015a1): (134, "MutableHeapNumberMap"),
("RO_SPACE", 0x015f1): (193, "NameDictionaryMap"),
("RO_SPACE", 0x01641): (217, "NoClosuresCellMap"),
("RO_SPACE", 0x01691): (217, "NoFeedbackCellMap"),
("RO_SPACE", 0x016e1): (195, "NumberDictionaryMap"),
("RO_SPACE", 0x01731): (217, "OneClosureCellMap"),
("RO_SPACE", 0x01781): (190, "OrderedHashMapMap"),
("RO_SPACE", 0x017d1): (191, "OrderedHashSetMap"),
("RO_SPACE", 0x01821): (192, "OrderedNameDictionaryMap"),
("RO_SPACE", 0x01871): (220, "PreParsedScopeDataMap"),
("RO_SPACE", 0x018c1): (221, "PropertyArrayMap"),
("RO_SPACE", 0x01911): (214, "SideEffectCallHandlerInfoMap"),
("RO_SPACE", 0x01961): (214, "SideEffectFreeCallHandlerInfoMap"),
("RO_SPACE", 0x019b1): (214, "NextCallSideEffectFreeCallHandlerInfoMap"),
("RO_SPACE", 0x01a01): (196, "SimpleNumberDictionaryMap"),
("RO_SPACE", 0x01a51): (187, "SloppyArgumentsElementsMap"),
("RO_SPACE", 0x01aa1): (224, "SmallOrderedHashMapMap"),
("RO_SPACE", 0x01af1): (225, "SmallOrderedHashSetMap"),
("RO_SPACE", 0x01b41): (226, "SmallOrderedNameDictionaryMap"),
("RO_SPACE", 0x01b91): (197, "StringTableMap"),
("RO_SPACE", 0x01be1): (228, "UncompiledDataWithoutPreParsedScopeMap"),
("RO_SPACE", 0x01c31): (229, "UncompiledDataWithPreParsedScopeMap"),
("RO_SPACE", 0x01c81): (230, "WeakArrayListMap"),
("RO_SPACE", 0x01cd1): (198, "EphemeronHashTableMap"),
("RO_SPACE", 0x01d21): (186, "EmbedderDataArrayMap"),
("RO_SPACE", 0x01d71): (106, "NativeSourceStringMap"),
("RO_SPACE", 0x01dc1): (64, "StringMap"),
("RO_SPACE", 0x01e11): (73, "ConsOneByteStringMap"),
("RO_SPACE", 0x01e61): (65, "ConsStringMap"),
("RO_SPACE", 0x01eb1): (77, "ThinOneByteStringMap"),
("RO_SPACE", 0x01f01): (69, "ThinStringMap"),
("RO_SPACE", 0x01f51): (67, "SlicedStringMap"),
("RO_SPACE", 0x01fa1): (75, "SlicedOneByteStringMap"),
("RO_SPACE", 0x01ff1): (66, "ExternalStringMap"),
("RO_SPACE", 0x02041): (82, "ExternalStringWithOneByteDataMap"),
("RO_SPACE", 0x02091): (74, "ExternalOneByteStringMap"),
("RO_SPACE", 0x020e1): (98, "UncachedExternalStringMap"),
("RO_SPACE", 0x02131): (114, "UncachedExternalStringWithOneByteDataMap"),
("RO_SPACE", 0x02181): (0, "InternalizedStringMap"),
("RO_SPACE", 0x021d1): (2, "ExternalInternalizedStringMap"),
("RO_SPACE", 0x02221): (18, "ExternalInternalizedStringWithOneByteDataMap"),
("RO_SPACE", 0x02271): (10, "ExternalOneByteInternalizedStringMap"),
("RO_SPACE", 0x022c1): (34, "UncachedExternalInternalizedStringMap"),
("RO_SPACE", 0x02311): (50, "UncachedExternalInternalizedStringWithOneByteDataMap"),
("RO_SPACE", 0x02361): (42, "UncachedExternalOneByteInternalizedStringMap"),
("RO_SPACE", 0x023b1): (106, "UncachedExternalOneByteStringMap"),
("RO_SPACE", 0x02401): (140, "FixedUint8ArrayMap"),
("RO_SPACE", 0x02451): (139, "FixedInt8ArrayMap"),
("RO_SPACE", 0x024a1): (142, "FixedUint16ArrayMap"),
("RO_SPACE", 0x024f1): (141, "FixedInt16ArrayMap"),
("RO_SPACE", 0x02541): (144, "FixedUint32ArrayMap"),
("RO_SPACE", 0x02591): (143, "FixedInt32ArrayMap"),
("RO_SPACE", 0x025e1): (145, "FixedFloat32ArrayMap"),
("RO_SPACE", 0x02631): (146, "FixedFloat64ArrayMap"),
("RO_SPACE", 0x02681): (147, "FixedUint8ClampedArrayMap"),
("RO_SPACE", 0x026d1): (149, "FixedBigUint64ArrayMap"),
("RO_SPACE", 0x02721): (148, "FixedBigInt64ArrayMap"),
("RO_SPACE", 0x02771): (131, "SelfReferenceMarkerMap"),
("RO_SPACE", 0x027d9): (173, "Tuple2Map"),
("RO_SPACE", 0x02879): (175, "ArrayBoilerplateDescriptionMap"),
("RO_SPACE", 0x02bb9): (163, "InterceptorInfoMap"),
("RO_SPACE", 0x050d9): (153, "AccessCheckInfoMap"),
("RO_SPACE", 0x05129): (154, "AccessorInfoMap"),
("RO_SPACE", 0x05179): (155, "AccessorPairMap"),
("RO_SPACE", 0x051c9): (156, "AliasedArgumentsEntryMap"),
("RO_SPACE", 0x05219): (157, "AllocationMementoMap"),
("RO_SPACE", 0x05269): (158, "AsmWasmDataMap"),
("RO_SPACE", 0x052b9): (159, "AsyncGeneratorRequestMap"),
("RO_SPACE", 0x05309): (160, "DebugInfoMap"),
("RO_SPACE", 0x05359): (161, "FunctionTemplateInfoMap"),
("RO_SPACE", 0x053a9): (162, "FunctionTemplateRareDataMap"),
("RO_SPACE", 0x053f9): (164, "InterpreterDataMap"),
("RO_SPACE", 0x05449): (165, "ModuleInfoEntryMap"),
("RO_SPACE", 0x05499): (166, "ModuleMap"),
("RO_SPACE", 0x054e9): (167, "ObjectTemplateInfoMap"),
("RO_SPACE", 0x05539): (168, "PromiseCapabilityMap"),
("RO_SPACE", 0x05589): (169, "PromiseReactionMap"),
("RO_SPACE", 0x055d9): (170, "PrototypeInfoMap"),
("RO_SPACE", 0x05629): (171, "ScriptMap"),
("RO_SPACE", 0x05679): (172, "StackFrameInfoMap"),
("RO_SPACE", 0x056c9): (174, "Tuple3Map"),
("RO_SPACE", 0x05719): (176, "WasmDebugInfoMap"),
("RO_SPACE", 0x05769): (177, "WasmExportedFunctionDataMap"),
("RO_SPACE", 0x057b9): (178, "CallableTaskMap"),
("RO_SPACE", 0x05809): (179, "CallbackTaskMap"),
("RO_SPACE", 0x05859): (180, "PromiseFulfillReactionJobTaskMap"),
("RO_SPACE", 0x058a9): (181, "PromiseRejectReactionJobTaskMap"),
("RO_SPACE", 0x058f9): (182, "PromiseResolveThenableJobTaskMap"),
("RO_SPACE", 0x05949): (183, "WeakFactoryCleanupJobTaskMap"),
("RO_SPACE", 0x05999): (184, "MicrotaskQueueMap"),
("RO_SPACE", 0x059e9): (185, "AllocationSiteWithWeakNextMap"),
("RO_SPACE", 0x05a39): (185, "AllocationSiteWithoutWeakNextMap"),
("RO_SPACE", 0x05a89): (219, "LoadHandler1Map"),
("RO_SPACE", 0x05ad9): (219, "LoadHandler2Map"),
("RO_SPACE", 0x05b29): (219, "LoadHandler3Map"),
("RO_SPACE", 0x05b79): (227, "StoreHandler0Map"),
("RO_SPACE", 0x05bc9): (227, "StoreHandler1Map"),
("RO_SPACE", 0x05c19): (227, "StoreHandler2Map"),
("RO_SPACE", 0x05c69): (227, "StoreHandler3Map"),
("RO_SPACE", 0x00271): (216, "DescriptorArrayMap"),
("RO_SPACE", 0x002d1): (211, "WeakFixedArrayMap"),
("RO_SPACE", 0x00321): (152, "OnePointerFillerMap"),
("RO_SPACE", 0x00371): (152, "TwoPointerFillerMap"),
("RO_SPACE", 0x003f1): (131, "UninitializedMap"),
("RO_SPACE", 0x00461): (8, "OneByteInternalizedStringMap"),
("RO_SPACE", 0x00501): (131, "UndefinedMap"),
("RO_SPACE", 0x00561): (129, "HeapNumberMap"),
("RO_SPACE", 0x005e1): (131, "TheHoleMap"),
("RO_SPACE", 0x00689): (131, "BooleanMap"),
("RO_SPACE", 0x00761): (136, "ByteArrayMap"),
("RO_SPACE", 0x007b1): (187, "FixedArrayMap"),
("RO_SPACE", 0x00801): (187, "FixedCOWArrayMap"),
("RO_SPACE", 0x00851): (189, "HashTableMap"),
("RO_SPACE", 0x008a1): (128, "SymbolMap"),
("RO_SPACE", 0x008f1): (72, "OneByteStringMap"),
("RO_SPACE", 0x00941): (199, "ScopeInfoMap"),
("RO_SPACE", 0x00991): (223, "SharedFunctionInfoMap"),
("RO_SPACE", 0x009e1): (133, "CodeMap"),
("RO_SPACE", 0x00a31): (206, "FunctionContextMap"),
("RO_SPACE", 0x00a81): (214, "CellMap"),
("RO_SPACE", 0x00ad1): (222, "GlobalPropertyCellMap"),
("RO_SPACE", 0x00b21): (135, "ForeignMap"),
("RO_SPACE", 0x00b71): (212, "TransitionArrayMap"),
("RO_SPACE", 0x00bc1): (218, "FeedbackVectorMap"),
("RO_SPACE", 0x00c61): (131, "ArgumentsMarkerMap"),
("RO_SPACE", 0x00d01): (131, "ExceptionMap"),
("RO_SPACE", 0x00da1): (131, "TerminationExceptionMap"),
("RO_SPACE", 0x00e49): (131, "OptimizedOutMap"),
("RO_SPACE", 0x00ee9): (131, "StaleRegisterMap"),
("RO_SPACE", 0x00f59): (208, "NativeContextMap"),
("RO_SPACE", 0x00fa9): (207, "ModuleContextMap"),
("RO_SPACE", 0x00ff9): (205, "EvalContextMap"),
("RO_SPACE", 0x01049): (209, "ScriptContextMap"),
("RO_SPACE", 0x01099): (201, "AwaitContextMap"),
("RO_SPACE", 0x010e9): (202, "BlockContextMap"),
("RO_SPACE", 0x01139): (203, "CatchContextMap"),
("RO_SPACE", 0x01189): (210, "WithContextMap"),
("RO_SPACE", 0x011d9): (204, "DebugEvaluateContextMap"),
("RO_SPACE", 0x01229): (200, "ScriptContextTableMap"),
("RO_SPACE", 0x01279): (151, "FeedbackMetadataArrayMap"),
("RO_SPACE", 0x012c9): (187, "ArrayListMap"),
("RO_SPACE", 0x01319): (130, "BigIntMap"),
("RO_SPACE", 0x01369): (188, "ObjectBoilerplateDescriptionMap"),
("RO_SPACE", 0x013b9): (137, "BytecodeArrayMap"),
("RO_SPACE", 0x01409): (215, "CodeDataContainerMap"),
("RO_SPACE", 0x01459): (150, "FixedDoubleArrayMap"),
("RO_SPACE", 0x014a9): (194, "GlobalDictionaryMap"),
("RO_SPACE", 0x014f9): (217, "ManyClosuresCellMap"),
("RO_SPACE", 0x01549): (187, "ModuleInfoMap"),
("RO_SPACE", 0x01599): (134, "MutableHeapNumberMap"),
("RO_SPACE", 0x015e9): (193, "NameDictionaryMap"),
("RO_SPACE", 0x01639): (217, "NoClosuresCellMap"),
("RO_SPACE", 0x01689): (217, "NoFeedbackCellMap"),
("RO_SPACE", 0x016d9): (195, "NumberDictionaryMap"),
("RO_SPACE", 0x01729): (217, "OneClosureCellMap"),
("RO_SPACE", 0x01779): (190, "OrderedHashMapMap"),
("RO_SPACE", 0x017c9): (191, "OrderedHashSetMap"),
("RO_SPACE", 0x01819): (192, "OrderedNameDictionaryMap"),
("RO_SPACE", 0x01869): (220, "PreParsedScopeDataMap"),
("RO_SPACE", 0x018b9): (221, "PropertyArrayMap"),
("RO_SPACE", 0x01909): (213, "SideEffectCallHandlerInfoMap"),
("RO_SPACE", 0x01959): (213, "SideEffectFreeCallHandlerInfoMap"),
("RO_SPACE", 0x019a9): (213, "NextCallSideEffectFreeCallHandlerInfoMap"),
("RO_SPACE", 0x019f9): (196, "SimpleNumberDictionaryMap"),
("RO_SPACE", 0x01a49): (187, "SloppyArgumentsElementsMap"),
("RO_SPACE", 0x01a99): (224, "SmallOrderedHashMapMap"),
("RO_SPACE", 0x01ae9): (225, "SmallOrderedHashSetMap"),
("RO_SPACE", 0x01b39): (226, "SmallOrderedNameDictionaryMap"),
("RO_SPACE", 0x01b89): (197, "StringTableMap"),
("RO_SPACE", 0x01bd9): (228, "UncompiledDataWithoutPreParsedScopeMap"),
("RO_SPACE", 0x01c29): (229, "UncompiledDataWithPreParsedScopeMap"),
("RO_SPACE", 0x01c79): (230, "WeakArrayListMap"),
("RO_SPACE", 0x01cc9): (198, "EphemeronHashTableMap"),
("RO_SPACE", 0x01d19): (186, "EmbedderDataArrayMap"),
("RO_SPACE", 0x01d69): (106, "NativeSourceStringMap"),
("RO_SPACE", 0x01db9): (64, "StringMap"),
("RO_SPACE", 0x01e09): (73, "ConsOneByteStringMap"),
("RO_SPACE", 0x01e59): (65, "ConsStringMap"),
("RO_SPACE", 0x01ea9): (77, "ThinOneByteStringMap"),
("RO_SPACE", 0x01ef9): (69, "ThinStringMap"),
("RO_SPACE", 0x01f49): (67, "SlicedStringMap"),
("RO_SPACE", 0x01f99): (75, "SlicedOneByteStringMap"),
("RO_SPACE", 0x01fe9): (66, "ExternalStringMap"),
("RO_SPACE", 0x02039): (82, "ExternalStringWithOneByteDataMap"),
("RO_SPACE", 0x02089): (74, "ExternalOneByteStringMap"),
("RO_SPACE", 0x020d9): (98, "UncachedExternalStringMap"),
("RO_SPACE", 0x02129): (114, "UncachedExternalStringWithOneByteDataMap"),
("RO_SPACE", 0x02179): (0, "InternalizedStringMap"),
("RO_SPACE", 0x021c9): (2, "ExternalInternalizedStringMap"),
("RO_SPACE", 0x02219): (18, "ExternalInternalizedStringWithOneByteDataMap"),
("RO_SPACE", 0x02269): (10, "ExternalOneByteInternalizedStringMap"),
("RO_SPACE", 0x022b9): (34, "UncachedExternalInternalizedStringMap"),
("RO_SPACE", 0x02309): (50, "UncachedExternalInternalizedStringWithOneByteDataMap"),
("RO_SPACE", 0x02359): (42, "UncachedExternalOneByteInternalizedStringMap"),
("RO_SPACE", 0x023a9): (106, "UncachedExternalOneByteStringMap"),
("RO_SPACE", 0x023f9): (140, "FixedUint8ArrayMap"),
("RO_SPACE", 0x02449): (139, "FixedInt8ArrayMap"),
("RO_SPACE", 0x02499): (142, "FixedUint16ArrayMap"),
("RO_SPACE", 0x024e9): (141, "FixedInt16ArrayMap"),
("RO_SPACE", 0x02539): (144, "FixedUint32ArrayMap"),
("RO_SPACE", 0x02589): (143, "FixedInt32ArrayMap"),
("RO_SPACE", 0x025d9): (145, "FixedFloat32ArrayMap"),
("RO_SPACE", 0x02629): (146, "FixedFloat64ArrayMap"),
("RO_SPACE", 0x02679): (147, "FixedUint8ClampedArrayMap"),
("RO_SPACE", 0x026c9): (149, "FixedBigUint64ArrayMap"),
("RO_SPACE", 0x02719): (148, "FixedBigInt64ArrayMap"),
("RO_SPACE", 0x02769): (131, "SelfReferenceMarkerMap"),
("RO_SPACE", 0x027d1): (173, "Tuple2Map"),
("RO_SPACE", 0x02871): (175, "ArrayBoilerplateDescriptionMap"),
("RO_SPACE", 0x02bb1): (163, "InterceptorInfoMap"),
("RO_SPACE", 0x050d1): (153, "AccessCheckInfoMap"),
("RO_SPACE", 0x05121): (154, "AccessorInfoMap"),
("RO_SPACE", 0x05171): (155, "AccessorPairMap"),
("RO_SPACE", 0x051c1): (156, "AliasedArgumentsEntryMap"),
("RO_SPACE", 0x05211): (157, "AllocationMementoMap"),
("RO_SPACE", 0x05261): (158, "AsmWasmDataMap"),
("RO_SPACE", 0x052b1): (159, "AsyncGeneratorRequestMap"),
("RO_SPACE", 0x05301): (160, "DebugInfoMap"),
("RO_SPACE", 0x05351): (161, "FunctionTemplateInfoMap"),
("RO_SPACE", 0x053a1): (162, "FunctionTemplateRareDataMap"),
("RO_SPACE", 0x053f1): (164, "InterpreterDataMap"),
("RO_SPACE", 0x05441): (165, "ModuleInfoEntryMap"),
("RO_SPACE", 0x05491): (166, "ModuleMap"),
("RO_SPACE", 0x054e1): (167, "ObjectTemplateInfoMap"),
("RO_SPACE", 0x05531): (168, "PromiseCapabilityMap"),
("RO_SPACE", 0x05581): (169, "PromiseReactionMap"),
("RO_SPACE", 0x055d1): (170, "PrototypeInfoMap"),
("RO_SPACE", 0x05621): (171, "ScriptMap"),
("RO_SPACE", 0x05671): (172, "StackFrameInfoMap"),
("RO_SPACE", 0x056c1): (174, "Tuple3Map"),
("RO_SPACE", 0x05711): (176, "WasmDebugInfoMap"),
("RO_SPACE", 0x05761): (177, "WasmExportedFunctionDataMap"),
("RO_SPACE", 0x057b1): (178, "CallableTaskMap"),
("RO_SPACE", 0x05801): (179, "CallbackTaskMap"),
("RO_SPACE", 0x05851): (180, "PromiseFulfillReactionJobTaskMap"),
("RO_SPACE", 0x058a1): (181, "PromiseRejectReactionJobTaskMap"),
("RO_SPACE", 0x058f1): (182, "PromiseResolveThenableJobTaskMap"),
("RO_SPACE", 0x05941): (183, "WeakFactoryCleanupJobTaskMap"),
("RO_SPACE", 0x05991): (184, "MicrotaskQueueMap"),
("RO_SPACE", 0x059e1): (185, "AllocationSiteWithWeakNextMap"),
("RO_SPACE", 0x05a31): (185, "AllocationSiteWithoutWeakNextMap"),
("RO_SPACE", 0x05a81): (219, "LoadHandler1Map"),
("RO_SPACE", 0x05ad1): (219, "LoadHandler2Map"),
("RO_SPACE", 0x05b21): (219, "LoadHandler3Map"),
("RO_SPACE", 0x05b71): (227, "StoreHandler0Map"),
("RO_SPACE", 0x05bc1): (227, "StoreHandler1Map"),
("RO_SPACE", 0x05c11): (227, "StoreHandler2Map"),
("RO_SPACE", 0x05c61): (227, "StoreHandler3Map"),
("MAP_SPACE", 0x00139): (1057, "ExternalMap"),
("MAP_SPACE", 0x00189): (1073, "JSMessageObjectMap"),
}
@ -353,53 +353,53 @@ KNOWN_MAPS = {
KNOWN_OBJECTS = {
("RO_SPACE", 0x001d9): "NullValue",
("RO_SPACE", 0x00259): "EmptyDescriptorArray",
("RO_SPACE", 0x002c9): "EmptyWeakFixedArray",
("RO_SPACE", 0x003c9): "UninitializedValue",
("RO_SPACE", 0x004d9): "UndefinedValue",
("RO_SPACE", 0x00559): "NanValue",
("RO_SPACE", 0x005b9): "TheHoleValue",
("RO_SPACE", 0x00651): "HoleNanValue",
("RO_SPACE", 0x00661): "TrueValue",
("RO_SPACE", 0x00711): "FalseValue",
("RO_SPACE", 0x00759): "empty_string",
("RO_SPACE", 0x00c19): "EmptyScopeInfo",
("RO_SPACE", 0x00c29): "EmptyFixedArray",
("RO_SPACE", 0x00c39): "ArgumentsMarker",
("RO_SPACE", 0x00cd9): "Exception",
("RO_SPACE", 0x00d79): "TerminationException",
("RO_SPACE", 0x00e21): "OptimizedOut",
("RO_SPACE", 0x00ec1): "StaleRegister",
("RO_SPACE", 0x027c1): "EmptyEnumCache",
("RO_SPACE", 0x02829): "EmptyPropertyArray",
("RO_SPACE", 0x02839): "EmptyByteArray",
("RO_SPACE", 0x02849): "EmptyObjectBoilerplateDescription",
("RO_SPACE", 0x02861): "EmptyArrayBoilerplateDescription",
("RO_SPACE", 0x028c9): "EmptyFixedUint8Array",
("RO_SPACE", 0x028e9): "EmptyFixedInt8Array",
("RO_SPACE", 0x02909): "EmptyFixedUint16Array",
("RO_SPACE", 0x02929): "EmptyFixedInt16Array",
("RO_SPACE", 0x02949): "EmptyFixedUint32Array",
("RO_SPACE", 0x02969): "EmptyFixedInt32Array",
("RO_SPACE", 0x02989): "EmptyFixedFloat32Array",
("RO_SPACE", 0x029a9): "EmptyFixedFloat64Array",
("RO_SPACE", 0x029c9): "EmptyFixedUint8ClampedArray",
("RO_SPACE", 0x029e9): "EmptyFixedBigUint64Array",
("RO_SPACE", 0x02a09): "EmptyFixedBigInt64Array",
("RO_SPACE", 0x02a29): "EmptySloppyArgumentsElements",
("RO_SPACE", 0x02a49): "EmptySlowElementDictionary",
("RO_SPACE", 0x02a91): "EmptyOrderedHashMap",
("RO_SPACE", 0x02ab9): "EmptyOrderedHashSet",
("RO_SPACE", 0x02ae1): "EmptyFeedbackMetadata",
("RO_SPACE", 0x02af1): "EmptyPropertyCell",
("RO_SPACE", 0x02b19): "EmptyPropertyDictionary",
("RO_SPACE", 0x02b69): "NoOpInterceptorInfo",
("RO_SPACE", 0x02c09): "EmptyWeakArrayList",
("RO_SPACE", 0x02c21): "InfinityValue",
("RO_SPACE", 0x02c31): "MinusZeroValue",
("RO_SPACE", 0x02c41): "MinusInfinityValue",
("RO_SPACE", 0x02c51): "SelfReferenceMarker",
("RO_SPACE", 0x02ca9): "OffHeapTrampolineRelocationInfo",
("RO_SPACE", 0x02cc1): "HashSeed",
("RO_SPACE", 0x002c1): "EmptyWeakFixedArray",
("RO_SPACE", 0x003c1): "UninitializedValue",
("RO_SPACE", 0x004d1): "UndefinedValue",
("RO_SPACE", 0x00551): "NanValue",
("RO_SPACE", 0x005b1): "TheHoleValue",
("RO_SPACE", 0x00649): "HoleNanValue",
("RO_SPACE", 0x00659): "TrueValue",
("RO_SPACE", 0x00709): "FalseValue",
("RO_SPACE", 0x00751): "empty_string",
("RO_SPACE", 0x00c11): "EmptyScopeInfo",
("RO_SPACE", 0x00c21): "EmptyFixedArray",
("RO_SPACE", 0x00c31): "ArgumentsMarker",
("RO_SPACE", 0x00cd1): "Exception",
("RO_SPACE", 0x00d71): "TerminationException",
("RO_SPACE", 0x00e19): "OptimizedOut",
("RO_SPACE", 0x00eb9): "StaleRegister",
("RO_SPACE", 0x027b9): "EmptyEnumCache",
("RO_SPACE", 0x02821): "EmptyPropertyArray",
("RO_SPACE", 0x02831): "EmptyByteArray",
("RO_SPACE", 0x02841): "EmptyObjectBoilerplateDescription",
("RO_SPACE", 0x02859): "EmptyArrayBoilerplateDescription",
("RO_SPACE", 0x028c1): "EmptyFixedUint8Array",
("RO_SPACE", 0x028e1): "EmptyFixedInt8Array",
("RO_SPACE", 0x02901): "EmptyFixedUint16Array",
("RO_SPACE", 0x02921): "EmptyFixedInt16Array",
("RO_SPACE", 0x02941): "EmptyFixedUint32Array",
("RO_SPACE", 0x02961): "EmptyFixedInt32Array",
("RO_SPACE", 0x02981): "EmptyFixedFloat32Array",
("RO_SPACE", 0x029a1): "EmptyFixedFloat64Array",
("RO_SPACE", 0x029c1): "EmptyFixedUint8ClampedArray",
("RO_SPACE", 0x029e1): "EmptyFixedBigUint64Array",
("RO_SPACE", 0x02a01): "EmptyFixedBigInt64Array",
("RO_SPACE", 0x02a21): "EmptySloppyArgumentsElements",
("RO_SPACE", 0x02a41): "EmptySlowElementDictionary",
("RO_SPACE", 0x02a89): "EmptyOrderedHashMap",
("RO_SPACE", 0x02ab1): "EmptyOrderedHashSet",
("RO_SPACE", 0x02ad9): "EmptyFeedbackMetadata",
("RO_SPACE", 0x02ae9): "EmptyPropertyCell",
("RO_SPACE", 0x02b11): "EmptyPropertyDictionary",
("RO_SPACE", 0x02b61): "NoOpInterceptorInfo",
("RO_SPACE", 0x02c01): "EmptyWeakArrayList",
("RO_SPACE", 0x02c19): "InfinityValue",
("RO_SPACE", 0x02c29): "MinusZeroValue",
("RO_SPACE", 0x02c39): "MinusInfinityValue",
("RO_SPACE", 0x02c49): "SelfReferenceMarker",
("RO_SPACE", 0x02ca1): "OffHeapTrampolineRelocationInfo",
("RO_SPACE", 0x02cb9): "HashSeed",
("OLD_SPACE", 0x00139): "ArgumentsIteratorAccessor",
("OLD_SPACE", 0x001a9): "ArrayLengthAccessor",
("OLD_SPACE", 0x00219): "BoundFunctionLengthAccessor",