[in-place weak refs] Replace WeakCells in TransitionArray.

BUG=v8:7308

Change-Id: I1976cd7e542a0304f6e14744e634c62dd06a83f5
Reviewed-on: https://chromium-review.googlesource.com/1014090
Commit-Queue: Marja Hölttä <marja@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52672}
This commit is contained in:
Marja Hölttä 2018-04-18 15:29:58 +02:00 committed by Commit Bot
parent ddb2856f39
commit 7560b33eba
21 changed files with 359 additions and 185 deletions

View File

@ -1434,6 +1434,7 @@ TNode<Smi> CodeStubAssembler::LoadFastJSArrayLength(
TNode<Smi> CodeStubAssembler::LoadFixedArrayBaseLength(
SloppyTNode<FixedArrayBase> array) {
CSA_SLOW_ASSERT(this, IsNotWeakFixedArraySubclass(array));
return CAST(LoadObjectField(array, FixedArrayBase::kLengthOffset));
}
@ -1442,6 +1443,11 @@ TNode<IntPtrT> CodeStubAssembler::LoadAndUntagFixedArrayBaseLength(
return LoadAndUntagObjectField(array, FixedArrayBase::kLengthOffset);
}
TNode<IntPtrT> CodeStubAssembler::LoadAndUntagWeakFixedArrayLength(
SloppyTNode<WeakFixedArray> array) {
return LoadAndUntagObjectField(array, WeakFixedArray::kLengthOffset);
}
TNode<Int32T> CodeStubAssembler::LoadMapBitField(SloppyTNode<Map> map) {
CSA_SLOW_ASSERT(this, IsMap(map));
return UncheckedCast<Int32T>(
@ -1706,20 +1712,42 @@ void CodeStubAssembler::DispatchMaybeObject(Node* maybe_object, Label* if_smi,
Goto(if_strong);
}
TNode<Object> CodeStubAssembler::LoadFixedArrayElement(
SloppyTNode<Object> object, Node* index_node, int additional_offset,
ParameterMode parameter_mode, LoadSensitivity needs_poisoning) {
Node* CodeStubAssembler::IsStrongHeapObject(Node* value) {
return WordEqual(
WordAnd(BitcastTaggedToWord(value), IntPtrConstant(kWeakHeapObjectMask)),
IntPtrConstant(0));
}
Node* CodeStubAssembler::ToStrongHeapObject(Node* value) {
return BitcastWordToTagged(WordAnd(BitcastTaggedToWord(value),
IntPtrConstant(~kWeakHeapObjectMask)));
}
TNode<Object> CodeStubAssembler::LoadArrayElement(
SloppyTNode<Object> object, int array_header_size, Node* index_node,
int additional_offset, ParameterMode parameter_mode,
LoadSensitivity needs_poisoning) {
CSA_SLOW_ASSERT(this, IntPtrGreaterThanOrEqual(
ParameterToIntPtr(index_node, parameter_mode),
IntPtrConstant(0)));
int32_t header_size =
FixedArray::kHeaderSize + additional_offset - kHeapObjectTag;
int32_t header_size = array_header_size + additional_offset - kHeapObjectTag;
TNode<IntPtrT> offset = ElementOffsetFromIndex(index_node, HOLEY_ELEMENTS,
parameter_mode, header_size);
return UncheckedCast<Object>(
Load(MachineType::AnyTagged(), object, offset, needs_poisoning));
}
TNode<Object> CodeStubAssembler::LoadFixedArrayElement(
SloppyTNode<Object> object, Node* index_node, int additional_offset,
ParameterMode parameter_mode, LoadSensitivity needs_poisoning) {
// This function is currently used for non-FixedArrays (e.g., PropertyArrays)
// and thus the reasonable assert IsFixedArraySubclass(object) is
// untrue. TODO(marja): Fix.
CSA_SLOW_ASSERT(this, IsNotWeakFixedArraySubclass(object));
return LoadArrayElement(object, FixedArray::kHeaderSize, index_node,
additional_offset, parameter_mode, needs_poisoning);
}
TNode<RawPtrT> CodeStubAssembler::LoadFixedTypedArrayBackingStore(
TNode<FixedTypedArrayBase> typed_array) {
// Backing store = external_pointer + base_pointer.
@ -1941,13 +1969,11 @@ TNode<Object> CodeStubAssembler::LoadFeedbackVectorSlot(
return UncheckedCast<Object>(Load(MachineType::AnyTagged(), object, offset));
}
TNode<Int32T> CodeStubAssembler::LoadAndUntagToWord32FixedArrayElement(
SloppyTNode<Object> object, Node* index_node, int additional_offset,
ParameterMode parameter_mode) {
CSA_SLOW_ASSERT(this, IsFixedArraySubclass(object));
TNode<Int32T> CodeStubAssembler::LoadAndUntagToWord32ArrayElement(
SloppyTNode<Object> object, int array_header_size, Node* index_node,
int additional_offset, ParameterMode parameter_mode) {
CSA_SLOW_ASSERT(this, MatchesParameterMode(index_node, parameter_mode));
int32_t header_size =
FixedArray::kHeaderSize + additional_offset - kHeapObjectTag;
int32_t header_size = array_header_size + additional_offset - kHeapObjectTag;
#if V8_TARGET_LITTLE_ENDIAN
if (Is64()) {
header_size += kPointerSize / 2;
@ -1962,6 +1988,15 @@ TNode<Int32T> CodeStubAssembler::LoadAndUntagToWord32FixedArrayElement(
}
}
TNode<Int32T> CodeStubAssembler::LoadAndUntagToWord32FixedArrayElement(
SloppyTNode<Object> object, Node* index_node, int additional_offset,
ParameterMode parameter_mode) {
CSA_SLOW_ASSERT(this, IsFixedArraySubclass(object));
return LoadAndUntagToWord32ArrayElement(object, FixedArray::kHeaderSize,
index_node, additional_offset,
parameter_mode);
}
Node* CodeStubAssembler::LoadFixedDoubleArrayElement(
Node* object, Node* index_node, MachineType machine_type,
int additional_offset, ParameterMode parameter_mode, Label* if_hole) {
@ -4676,6 +4711,14 @@ Node* CodeStubAssembler::IsFixedArraySubclass(Node* object) {
Int32Constant(LAST_FIXED_ARRAY_TYPE)));
}
Node* CodeStubAssembler::IsNotWeakFixedArraySubclass(Node* object) {
Node* instance_type = LoadInstanceType(object);
return Word32Or(
Int32LessThan(instance_type, Int32Constant(FIRST_WEAK_FIXED_ARRAY_TYPE)),
Int32GreaterThan(instance_type,
Int32Constant(LAST_WEAK_FIXED_ARRAY_TYPE)));
}
Node* CodeStubAssembler::IsPromiseCapability(Node* object) {
return HasInstanceType(object, PROMISE_CAPABILITY_TYPE);
}
@ -6849,6 +6892,9 @@ void CodeStubAssembler::LookupLinear(TNode<Name> unique_name,
Label* if_found,
TVariable<IntPtrT>* var_name_index,
Label* if_not_found) {
static_assert(std::is_base_of<FixedArray, Array>::value ||
std::is_base_of<TransitionArray, Array>::value,
"T must be a descendant of FixedArray or a TransitionArray");
Comment("LookupLinear");
TNode<IntPtrT> first_inclusive = IntPtrConstant(Array::ToKeyIndex(0));
TNode<IntPtrT> factor = IntPtrConstant(Array::kEntrySize);
@ -6858,8 +6904,9 @@ void CodeStubAssembler::LookupLinear(TNode<Name> unique_name,
BuildFastLoop(last_exclusive, first_inclusive,
[=](SloppyTNode<IntPtrT> name_index) {
TNode<Name> candidate_name =
CAST(LoadFixedArrayElement(array, name_index));
TNode<Name> candidate_name = CAST(
LoadArrayElement(array, Array::kHeaderSize, name_index));
CSA_ASSERT(this, IsStrongHeapObject(candidate_name));
*var_name_index = name_index;
GotoIf(WordEqual(candidate_name, unique_name), if_found);
},
@ -6877,13 +6924,13 @@ TNode<Uint32T> CodeStubAssembler::NumberOfEntries<DescriptorArray>(
template <>
TNode<Uint32T> CodeStubAssembler::NumberOfEntries<TransitionArray>(
TNode<TransitionArray> transitions) {
TNode<IntPtrT> length = LoadAndUntagFixedArrayBaseLength(transitions);
TNode<IntPtrT> length = LoadAndUntagWeakFixedArrayLength(transitions);
return Select<Uint32T>(
UintPtrLessThan(length, IntPtrConstant(TransitionArray::kFirstIndex)),
[=] { return Unsigned(Int32Constant(0)); },
[=] {
return Unsigned(LoadAndUntagToWord32FixedArrayElement(
transitions,
return Unsigned(LoadAndUntagToWord32ArrayElement(
transitions, WeakFixedArray::kHeaderSize,
IntPtrConstant(TransitionArray::kTransitionLengthIndex)));
});
}
@ -6924,9 +6971,15 @@ TNode<Uint32T> CodeStubAssembler::GetSortedKeyIndex<TransitionArray>(
template <typename Array>
TNode<Name> CodeStubAssembler::GetKey(TNode<Array> array,
TNode<Uint32T> entry_index) {
const int key_offset = DescriptorArray::ToKeyIndex(0) * kPointerSize;
return CAST(LoadFixedArrayElement(
array, EntryIndexToIndex<Array>(entry_index), key_offset));
static_assert(std::is_base_of<FixedArray, Array>::value ||
std::is_base_of<TransitionArray, Array>::value,
"T must be a descendant of FixedArray or a TransitionArray");
const int key_offset = Array::ToKeyIndex(0) * kPointerSize;
TNode<Name> key =
CAST(LoadArrayElement(array, Array::kHeaderSize,
EntryIndexToIndex<Array>(entry_index), key_offset));
CSA_ASSERT(this, IsStrongHeapObject(key));
return key;
}
template TNode<Name> CodeStubAssembler::GetKey<DescriptorArray>(

View File

@ -573,6 +573,9 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
// Load the length of a fixed array base instance.
TNode<IntPtrT> LoadAndUntagFixedArrayBaseLength(
SloppyTNode<FixedArrayBase> array);
// Load the length of a WeakFixedArray.
TNode<IntPtrT> LoadAndUntagWeakFixedArrayLength(
SloppyTNode<WeakFixedArray> array);
// Load the bit field of a Map.
TNode<Int32T> LoadMapBitField(SloppyTNode<Map> map);
// Load bit field 2 of a map.
@ -647,6 +650,15 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
void DispatchMaybeObject(Node* maybe_object, Label* if_smi, Label* if_cleared,
Label* if_weak, Label* if_strong,
Variable* extracted);
Node* IsStrongHeapObject(Node* value);
Node* ToStrongHeapObject(Node* value);
// Load an array element from a FixedArray / WeakFixedArray.
TNode<Object> LoadArrayElement(
SloppyTNode<Object> object, int array_header_size, Node* index,
int additional_offset = 0,
ParameterMode parameter_mode = INTPTR_PARAMETERS,
LoadSensitivity needs_poisoning = LoadSensitivity::kSafe);
// Load an array element from a FixedArray.
TNode<Object> LoadFixedArrayElement(
@ -679,6 +691,14 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
TNode<Object> LoadFixedArrayElement(TNode<Object> object, TNode<Smi> index) {
return LoadFixedArrayElement(object, index, 0, SMI_PARAMETERS);
}
// Load an array element from a FixedArray / WeakFixedArray, untag it and
// return it as Word32.
TNode<Int32T> LoadAndUntagToWord32ArrayElement(
SloppyTNode<Object> object, int array_header_size, Node* index,
int additional_offset = 0,
ParameterMode parameter_mode = INTPTR_PARAMETERS);
// Load an array element from a FixedArray, untag it and return it as Word32.
TNode<Int32T> LoadAndUntagToWord32FixedArrayElement(
SloppyTNode<Object> object, Node* index, int additional_offset = 0,
@ -1339,6 +1359,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Node* IsWeakCell(Node* object);
Node* IsZeroOrContext(Node* object);
Node* IsNotWeakFixedArraySubclass(Node* object);
inline Node* IsSharedFunctionInfo(Node* object) {
return IsSharedFunctionInfoMap(LoadMap(object));
}

View File

@ -227,6 +227,29 @@ Handle<T> Factory::NewFixedArrayWithMap(Heap::RootListIndex map_root_index,
map_root_index, length, *undefined_value(), pretenure));
}
template <typename T>
Handle<T> Factory::NewWeakFixedArrayWithMap(Heap::RootListIndex map_root_index,
int length,
PretenureFlag pretenure) {
static_assert(std::is_base_of<WeakFixedArray, T>::value,
"T must be a descendant of WeakFixedArray");
// Zero-length case must be handled outside.
DCHECK_LT(0, length);
HeapObject* result =
AllocateRawArray(WeakFixedArray::SizeFor(length), pretenure);
Map* map = Map::cast(isolate()->heap()->root(map_root_index));
result->set_map_after_allocation(map, SKIP_WRITE_BARRIER);
Handle<WeakFixedArray> array(WeakFixedArray::cast(result), isolate());
array->set_length(length);
MemsetPointer(array->data_start(),
HeapObjectReference::Strong(*undefined_value()), length);
return Handle<T>::cast(array);
}
template Handle<FixedArray> Factory::NewFixedArrayWithMap<FixedArray>(
Heap::RootListIndex, int, PretenureFlag);
@ -1619,8 +1642,10 @@ Handle<WeakCell> Factory::NewWeakCell(Handle<HeapObject> value) {
return cell;
}
Handle<TransitionArray> Factory::NewTransitionArray(int capacity) {
Handle<TransitionArray> array = NewFixedArrayWithMap<TransitionArray>(
Handle<TransitionArray> Factory::NewTransitionArray(int number_of_transitions,
int slack) {
int capacity = TransitionArray::LengthFor(number_of_transitions + slack);
Handle<TransitionArray> array = NewWeakFixedArrayWithMap<TransitionArray>(
Heap::kTransitionArrayMapRootIndex, capacity, TENURED);
// Transition arrays are tenured. When black allocation is on we have to
// add the transition array to the list of encountered_transition_arrays.
@ -1628,6 +1653,11 @@ Handle<TransitionArray> Factory::NewTransitionArray(int capacity) {
if (heap->incremental_marking()->black_allocation()) {
heap->mark_compact_collector()->AddTransitionArray(*array);
}
array->WeakFixedArray::Set(TransitionArray::kPrototypeTransitionsIndex,
MaybeObject::FromObject(Smi::kZero));
array->WeakFixedArray::Set(
TransitionArray::kTransitionLengthIndex,
MaybeObject::FromObject(Smi::FromInt(number_of_transitions)));
return array;
}

View File

@ -93,6 +93,13 @@ class V8_EXPORT_PRIVATE Factory {
Handle<T> NewFixedArrayWithMap(Heap::RootListIndex map_root_index, int length,
PretenureFlag pretenure = NOT_TENURED);
// Allocates a weak fixed array-like object with given map and initialized
// with undefined values.
template <typename T = WeakFixedArray>
Handle<T> NewWeakFixedArrayWithMap(Heap::RootListIndex map_root_index,
int length,
PretenureFlag pretenure = NOT_TENURED);
// Allocates a fixed array initialized with undefined values.
Handle<FixedArray> NewFixedArray(int length,
PretenureFlag pretenure = NOT_TENURED);
@ -441,7 +448,8 @@ class V8_EXPORT_PRIVATE Factory {
Handle<FeedbackCell> NewOneClosureCell(Handle<HeapObject> value);
Handle<FeedbackCell> NewManyClosuresCell(Handle<HeapObject> value);
Handle<TransitionArray> NewTransitionArray(int capacity);
Handle<TransitionArray> NewTransitionArray(int number_of_transitions,
int slack = 0);
// Allocate a tenured AllocationSite. Its payload is null.
Handle<AllocationSite> NewAllocationSite();

View File

@ -2853,14 +2853,27 @@ void Heap::RightTrimFixedArray(FixedArrayBase* object, int elements_to_trim) {
bytes_to_trim = elements_to_trim * kDoubleSize;
}
CreateFillerForArray<FixedArrayBase>(object, elements_to_trim, bytes_to_trim);
}
void Heap::RightTrimWeakFixedArray(WeakFixedArray* object,
int elements_to_trim) {
CreateFillerForArray<WeakFixedArray>(object, elements_to_trim,
elements_to_trim * kPointerSize);
}
template <typename T>
void Heap::CreateFillerForArray(T* object, int elements_to_trim,
int bytes_to_trim) {
DCHECK(object->IsFixedArrayBase() || object->IsByteArray() ||
object->IsWeakFixedArray());
// For now this trick is only applied to objects in new and paged space.
DCHECK(object->map() != fixed_cow_array_map());
if (bytes_to_trim == 0) {
// No need to create filler and update live bytes counters, just initialize
// header of the trimmed array.
object->synchronized_set_length(len - elements_to_trim);
DCHECK_EQ(elements_to_trim, 0);
// No need to create filler and update live bytes counters.
return;
}
@ -2892,7 +2905,7 @@ void Heap::RightTrimFixedArray(FixedArrayBase* object, int elements_to_trim) {
// Initialize header of the trimmed array. We are storing the new length
// using release store after creating a filler for the left-over space to
// avoid races with the sweeper thread.
object->synchronized_set_length(len - elements_to_trim);
object->synchronized_set_length(object->length() - elements_to_trim);
// Notify the heap object allocation tracker of change in object layout. The
// array may not be moved during GC, and size has to be adjusted nevertheless.

View File

@ -772,6 +772,9 @@ class Heap {
ClearFreedMemoryMode clear_memory_mode =
ClearFreedMemoryMode::kDontClearFreedMemory);
template <typename T>
void CreateFillerForArray(T* object, int elements_to_trim, int bytes_to_trim);
bool CanMoveObjectStart(HeapObject* object);
static bool IsImmovable(HeapObject* object);
@ -782,6 +785,7 @@ class Heap {
// Trim the given array from the right.
void RightTrimFixedArray(FixedArrayBase* obj, int elements_to_trim);
void RightTrimWeakFixedArray(WeakFixedArray* obj, int elements_to_trim);
// Converts the given boolean condition to JavaScript boolean value.
inline Oddball* ToBoolean(bool condition);

View File

@ -1716,7 +1716,8 @@ void MarkCompactCollector::ClearNonLiveReferences() {
{
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_MAPS);
// ClearFullMapTransitions must be called before WeakCells are cleared.
// ClearFullMapTransitions must be called before weak references are
// cleared.
ClearFullMapTransitions();
}
ClearWeakCells();
@ -1820,12 +1821,14 @@ bool MarkCompactCollector::CompactTransitionArray(
if (i != transition_index) {
Name* key = transitions->GetKey(i);
transitions->SetKey(transition_index, key);
Object** key_slot = transitions->GetKeySlot(transition_index);
HeapObjectReference** key_slot =
transitions->GetKeySlot(transition_index);
RecordSlot(transitions, key_slot, key);
Object* raw_target = transitions->GetRawTarget(i);
transitions->SetTarget(transition_index, raw_target);
Object** target_slot = transitions->GetTargetSlot(transition_index);
RecordSlot(transitions, target_slot, raw_target);
MaybeObject* raw_target = transitions->GetRawTarget(i);
transitions->SetRawTarget(transition_index, raw_target);
HeapObjectReference** target_slot =
transitions->GetTargetSlot(transition_index);
RecordSlot(transitions, target_slot, raw_target->GetHeapObject());
}
transition_index++;
}
@ -1841,7 +1844,8 @@ bool MarkCompactCollector::CompactTransitionArray(
// array disappeared during GC.
int trim = transitions->Capacity() - transition_index;
if (trim > 0) {
heap_->RightTrimFixedArray(transitions, trim * TransitionArray::kEntrySize);
heap_->RightTrimWeakFixedArray(transitions,
trim * TransitionArray::kEntrySize);
transitions->SetNumberOfTransitions(transition_index);
}
return descriptors_owner_died;

View File

@ -732,10 +732,9 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore(
const int kKeyToTargetOffset = (TransitionArray::kEntryTargetIndex -
TransitionArray::kEntryKeyIndex) *
kPointerSize;
TNode<WeakCell> transition_map_weak_cell = CAST(LoadFixedArrayElement(
transitions, var_name_index.value(), kKeyToTargetOffset));
var_transition_map =
CAST(LoadWeakCellValue(transition_map_weak_cell, slow));
var_transition_map = CAST(ToStrongHeapObject(
LoadArrayElement(transitions, WeakFixedArray::kHeaderSize,
var_name_index.value(), kKeyToTargetOffset)));
Goto(&found_handler_candidate);
}
}

View File

@ -634,7 +634,7 @@ void DescriptorArray::DescriptorArrayVerify() {
}
void TransitionArray::TransitionArrayVerify() {
FixedArrayVerify();
WeakFixedArrayVerify();
CHECK_LE(LengthFor(number_of_transitions()), length());
}

View File

@ -140,6 +140,12 @@ bool HeapObject::IsFixedArray() const {
instance_type <= LAST_FIXED_ARRAY_TYPE;
}
bool HeapObject::IsWeakFixedArray() const {
InstanceType instance_type = map()->instance_type();
return instance_type >= FIRST_WEAK_FIXED_ARRAY_TYPE &&
instance_type <= LAST_WEAK_FIXED_ARRAY_TYPE;
}
bool HeapObject::IsSloppyArgumentsElements() const {
return IsFixedArrayExact();
}
@ -2238,7 +2244,8 @@ int HeapObject::SizeFromMap(Map* map) const {
reinterpret_cast<const FeedbackMetadata*>(this)
->synchronized_slot_count());
}
if (instance_type == WEAK_FIXED_ARRAY_TYPE) {
if (instance_type >= FIRST_WEAK_FIXED_ARRAY_TYPE &&
instance_type <= LAST_WEAK_FIXED_ARRAY_TYPE) {
return WeakFixedArray::SizeFor(
reinterpret_cast<const WeakFixedArray*>(this)->synchronized_length());
}

View File

@ -815,7 +815,7 @@ void TransitionArray::TransitionArrayPrint(std::ostream& os) { // NOLINT
HeapObject::PrintHeader(os, "TransitionArray");
os << "\n - capacity: " << length();
for (int i = 0; i < length(); i++) {
os << "\n [" << i << "]: " << Brief(get(i));
os << "\n [" << i << "]: " << MaybeObjectBrief(Get(i));
if (i == kPrototypeTransitionsIndex) os << " (prototype transitions)";
if (i == kTransitionLengthIndex) os << " (number of transitions)";
}

View File

@ -10158,6 +10158,12 @@ bool FixedArray::IsEqualTo(FixedArray* other) {
}
#endif
void WeakFixedArray::Shrink(int new_length) {
DCHECK(0 <= new_length && new_length <= length());
if (new_length < length()) {
GetHeap()->RightTrimWeakFixedArray(this, length() - new_length);
}
}
// static
void FixedArrayOfWeakCells::Set(Handle<FixedArrayOfWeakCells> array, int index,

View File

@ -412,7 +412,6 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
V(DESCRIPTOR_ARRAY_TYPE) \
V(HASH_TABLE_TYPE) \
V(SCOPE_INFO_TYPE) \
V(TRANSITION_ARRAY_TYPE) \
\
V(BLOCK_CONTEXT_TYPE) \
V(CATCH_CONTEXT_TYPE) \
@ -424,6 +423,9 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
V(SCRIPT_CONTEXT_TYPE) \
V(WITH_CONTEXT_TYPE) \
\
V(WEAK_FIXED_ARRAY_TYPE) \
V(TRANSITION_ARRAY_TYPE) \
\
V(CALL_HANDLER_INFO_TYPE) \
V(CELL_TYPE) \
V(CODE_DATA_CONTAINER_TYPE) \
@ -437,7 +439,6 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
V(SMALL_ORDERED_HASH_SET_TYPE) \
V(STORE_HANDLER_TYPE) \
V(WEAK_CELL_TYPE) \
V(WEAK_FIXED_ARRAY_TYPE) \
V(WEAK_ARRAY_LIST_TYPE) \
\
V(JS_PROXY_TYPE) \
@ -782,7 +783,6 @@ enum InstanceType : uint16_t {
DESCRIPTOR_ARRAY_TYPE,
HASH_TABLE_TYPE,
SCOPE_INFO_TYPE,
TRANSITION_ARRAY_TYPE,
BLOCK_CONTEXT_TYPE, // FIRST_CONTEXT_TYPE
CATCH_CONTEXT_TYPE,
DEBUG_EVALUATE_CONTEXT_TYPE,
@ -793,6 +793,9 @@ enum InstanceType : uint16_t {
SCRIPT_CONTEXT_TYPE,
WITH_CONTEXT_TYPE, // LAST_FIXED_ARRAY_TYPE, LAST_CONTEXT_TYPE
WEAK_FIXED_ARRAY_TYPE, // FIRST_WEAK_FIXED_ARRAY_TYPE
TRANSITION_ARRAY_TYPE, // LAST_WEAK_FIXED_ARRAY_TYPE
// Misc.
CALL_HANDLER_INFO_TYPE,
CELL_TYPE,
@ -807,7 +810,6 @@ enum InstanceType : uint16_t {
SMALL_ORDERED_HASH_SET_TYPE,
STORE_HANDLER_TYPE,
WEAK_CELL_TYPE,
WEAK_FIXED_ARRAY_TYPE,
WEAK_ARRAY_LIST_TYPE,
// All the following types are subtypes of JSReceiver, which corresponds to
@ -879,6 +881,9 @@ enum InstanceType : uint16_t {
// Boundaries for testing if given HeapObject is a subclass of FixedArray.
FIRST_FIXED_ARRAY_TYPE = FIXED_ARRAY_TYPE,
LAST_FIXED_ARRAY_TYPE = WITH_CONTEXT_TYPE,
// Boundaries for testing if given HeapObject is a subclass of WeakFixedArray.
FIRST_WEAK_FIXED_ARRAY_TYPE = WEAK_FIXED_ARRAY_TYPE,
LAST_WEAK_FIXED_ARRAY_TYPE = TRANSITION_ARRAY_TYPE,
// Boundaries for testing if given HeapObject is a Context
FIRST_CONTEXT_TYPE = BLOCK_CONTEXT_TYPE,
LAST_CONTEXT_TYPE = WITH_CONTEXT_TYPE,

View File

@ -17,7 +17,6 @@ TYPE_CHECKER(ByteArray, BYTE_ARRAY_TYPE)
TYPE_CHECKER(FixedArrayExact, FIXED_ARRAY_TYPE)
TYPE_CHECKER(FixedDoubleArray, FIXED_DOUBLE_ARRAY_TYPE)
TYPE_CHECKER(FixedArrayOfWeakCells, FIXED_ARRAY_TYPE)
TYPE_CHECKER(WeakFixedArray, WEAK_FIXED_ARRAY_TYPE)
TYPE_CHECKER(WeakArrayList, WEAK_ARRAY_LIST_TYPE)
CAST_ACCESSOR(ArrayList)
@ -242,6 +241,10 @@ MaybeObject** WeakFixedArray::data_start() {
return HeapObject::RawMaybeWeakField(this, kHeaderSize);
}
MaybeObject** WeakFixedArray::RawFieldOfElementAt(int index) {
return HeapObject::RawMaybeWeakField(this, OffsetOfElementAt(index));
}
MaybeObject* WeakArrayList::Get(int index) const {
SLOW_DCHECK(index >= 0 && index < this->capacity());
return RELAXED_READ_WEAK_FIELD(this, OffsetOfElementAt(index));

View File

@ -269,6 +269,11 @@ class WeakFixedArray : public HeapObject {
// Gives access to raw memory which stores the array's data.
inline MaybeObject** data_start();
inline MaybeObject** RawFieldOfElementAt(int index);
// Shrink length and insert filler objects.
void Shrink(int new_length);
DECL_PRINTER(WeakFixedArray)
DECL_VERIFIER(WeakFixedArray)

View File

@ -1349,6 +1349,7 @@ void V8HeapExplorer::ExtractFixedArrayReferences(int entry, FixedArray* array) {
auto it = array_types_.find(array);
if (it == array_types_.end()) {
for (int i = 0, l = array->length(); i < l; ++i) {
DCHECK(!HasWeakHeapObjectTag(array->get(i)));
SetInternalReference(array, entry, i, array->get(i),
array->OffsetOfElementAt(i));
}

View File

@ -8,6 +8,8 @@
#include "src/transitions.h"
#include "src/ic/handler-configuration-inl.h"
#include "src/objects/fixed-array-inl.h"
#include "src/objects/maybe-object-inl.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
@ -23,37 +25,33 @@ TransitionArray* TransitionsAccessor::transitions() {
CAST_ACCESSOR(TransitionArray)
bool TransitionArray::HasPrototypeTransitions() {
return get(kPrototypeTransitionsIndex) != Smi::kZero;
return Get(kPrototypeTransitionsIndex) != MaybeObject::FromSmi(Smi::kZero);
}
FixedArray* TransitionArray::GetPrototypeTransitions() {
DCHECK(HasPrototypeTransitions()); // Callers must check first.
Object* prototype_transitions = get(kPrototypeTransitionsIndex);
Object* prototype_transitions =
Get(kPrototypeTransitionsIndex)->ToStrongHeapObject();
return FixedArray::cast(prototype_transitions);
}
HeapObjectReference** TransitionArray::GetKeySlot(int transition_number) {
DCHECK(transition_number < number_of_transitions());
return reinterpret_cast<HeapObjectReference**>(
RawFieldOfElementAt(ToKeyIndex(transition_number)));
}
void TransitionArray::SetPrototypeTransitions(FixedArray* transitions) {
DCHECK(transitions->IsFixedArray());
set(kPrototypeTransitionsIndex, transitions);
}
Object** TransitionArray::GetPrototypeTransitionsSlot() {
return RawFieldOfElementAt(kPrototypeTransitionsIndex);
}
Object** TransitionArray::GetKeySlot(int transition_number) {
DCHECK(transition_number < number_of_transitions());
return RawFieldOfElementAt(ToKeyIndex(transition_number));
WeakFixedArray::Set(kPrototypeTransitionsIndex,
HeapObjectReference::Strong(transitions));
}
Name* TransitionArray::GetKey(int transition_number) {
DCHECK(transition_number < number_of_transitions());
return Name::cast(get(ToKeyIndex(transition_number)));
return Name::cast(Get(ToKeyIndex(transition_number))->ToStrongHeapObject());
}
Name* TransitionsAccessor::GetKey(int transition_number) {
@ -74,12 +72,14 @@ Name* TransitionsAccessor::GetKey(int transition_number) {
void TransitionArray::SetKey(int transition_number, Name* key) {
DCHECK(transition_number < number_of_transitions());
set(ToKeyIndex(transition_number), key);
WeakFixedArray::Set(ToKeyIndex(transition_number),
HeapObjectReference::Strong(key));
}
Object** TransitionArray::GetTargetSlot(int transition_number) {
HeapObjectReference** TransitionArray::GetTargetSlot(int transition_number) {
DCHECK(transition_number < number_of_transitions());
return RawFieldOfElementAt(ToTargetIndex(transition_number));
return reinterpret_cast<HeapObjectReference**>(
RawFieldOfElementAt(ToTargetIndex(transition_number)));
}
// static
@ -93,17 +93,17 @@ PropertyDetails TransitionsAccessor::GetTargetDetails(Name* name, Map* target) {
}
// static
Map* TransitionsAccessor::GetTargetFromRaw(Object* raw) {
return Map::cast(WeakCell::cast(raw)->value());
Map* TransitionsAccessor::GetTargetFromRaw(MaybeObject* raw) {
return Map::cast(raw->ToWeakHeapObject());
}
Object* TransitionArray::GetRawTarget(int transition_number) {
MaybeObject* TransitionArray::GetRawTarget(int transition_number) {
DCHECK(transition_number < number_of_transitions());
return get(ToTargetIndex(transition_number));
return Get(ToTargetIndex(transition_number));
}
Map* TransitionArray::GetTarget(int transition_number) {
Object* raw = GetRawTarget(transition_number);
MaybeObject* raw = GetRawTarget(transition_number);
return TransitionsAccessor::GetTargetFromRaw(raw);
}
@ -121,16 +121,18 @@ Map* TransitionsAccessor::GetTarget(int transition_number) {
UNREACHABLE();
}
void TransitionArray::SetTarget(int transition_number, Object* value) {
DCHECK(!value->IsMap());
void TransitionArray::SetRawTarget(int transition_number, MaybeObject* value) {
DCHECK(transition_number < number_of_transitions());
set(ToTargetIndex(transition_number), value);
DCHECK(value->IsWeakHeapObject() && value->ToWeakHeapObject()->IsMap());
WeakFixedArray::Set(ToTargetIndex(transition_number), value);
}
bool TransitionArray::GetTargetIfExists(int transition_number, Isolate* isolate,
Map** target) {
Object* raw = GetRawTarget(transition_number);
if (raw->IsUndefined(isolate)) {
MaybeObject* raw = GetRawTarget(transition_number);
HeapObject* heap_object;
if (raw->ToStrongHeapObject(&heap_object) &&
heap_object->IsUndefined(isolate)) {
return false;
}
*target = TransitionsAccessor::GetTargetFromRaw(raw);
@ -143,6 +145,11 @@ int TransitionArray::SearchName(Name* name, int* out_insertion_index) {
out_insertion_index);
}
int TransitionArray::number_of_transitions() const {
if (length() < kFirstIndex) return 0;
return Smi::ToInt(Get(kTransitionLengthIndex)->ToSmi());
}
int TransitionArray::CompareKeys(Name* key1, uint32_t hash1, PropertyKind kind1,
PropertyAttributes attributes1, Name* key2,
uint32_t hash2, PropertyKind kind2,
@ -179,9 +186,11 @@ int TransitionArray::CompareDetails(PropertyKind kind1,
return 0;
}
void TransitionArray::Set(int transition_number, Name* key, Object* target) {
set(ToKeyIndex(transition_number), key);
set(ToTargetIndex(transition_number), target);
void TransitionArray::Set(int transition_number, Name* key,
MaybeObject* target) {
WeakFixedArray::Set(ToKeyIndex(transition_number),
MaybeObject::FromObject(key));
WeakFixedArray::Set(ToTargetIndex(transition_number), target);
}
int TransitionArray::Capacity() {
@ -191,7 +200,9 @@ int TransitionArray::Capacity() {
void TransitionArray::SetNumberOfTransitions(int number_of_transitions) {
DCHECK(number_of_transitions <= Capacity());
set(kTransitionLengthIndex, Smi::FromInt(number_of_transitions));
WeakFixedArray::Set(
kTransitionLengthIndex,
MaybeObject::FromSmi(Smi::FromInt(number_of_transitions)));
}
} // namespace internal

View File

@ -68,7 +68,8 @@ void TransitionsAccessor::Insert(Handle<Name> name, Handle<Map> target,
return;
}
// If the flag requires a full TransitionArray, allocate one.
Handle<TransitionArray> result = TransitionArray::Allocate(isolate, 0, 1);
Handle<TransitionArray> result =
isolate->factory()->NewTransitionArray(0, 1);
ReplaceTransitions(MaybeObject::FromObject(*result));
Reload();
}
@ -90,15 +91,16 @@ void TransitionsAccessor::Insert(Handle<Name> name, Handle<Map> target,
}
// Otherwise allocate a full TransitionArray with slack for a new entry.
Handle<Map> map(simple_transition);
Handle<WeakCell> weak_cell = Map::WeakCellForMap(map);
Handle<TransitionArray> result = TransitionArray::Allocate(isolate, 1, 1);
Handle<TransitionArray> result =
isolate->factory()->NewTransitionArray(1, 1);
// Reload state; allocations might have caused it to be cleared.
Reload();
simple_transition = GetSimpleTransition();
if (simple_transition != nullptr) {
DCHECK_EQ(*map, simple_transition);
if (encoding_ == kWeakRef) {
result->Set(0, GetSimpleTransitionKey(simple_transition), *weak_cell);
result->Set(0, GetSimpleTransitionKey(simple_transition),
HeapObjectReference::Weak(simple_transition));
} else {
UNREACHABLE();
}
@ -112,9 +114,6 @@ void TransitionsAccessor::Insert(Handle<Name> name, Handle<Map> target,
// At this point, we know that the map has a full TransitionArray.
DCHECK_EQ(kFullTransitionArray, encoding());
Handle<WeakCell> weak_cell_with_target = Map::WeakCellForMap(target);
Reload();
int number_of_transitions = 0;
int new_nof = 0;
int insertion_index = kNotFound;
@ -136,7 +135,7 @@ void TransitionsAccessor::Insert(Handle<Name> name, Handle<Map> target,
&insertion_index);
// If an existing entry was found, overwrite it and return.
if (index != kNotFound) {
array->SetTarget(index, *weak_cell_with_target);
array->SetRawTarget(index, HeapObjectReference::Weak(*target));
return;
}
@ -149,18 +148,18 @@ void TransitionsAccessor::Insert(Handle<Name> name, Handle<Map> target,
array->SetNumberOfTransitions(new_nof);
for (index = number_of_transitions; index > insertion_index; --index) {
array->SetKey(index, array->GetKey(index - 1));
array->SetTarget(index, array->GetRawTarget(index - 1));
array->SetRawTarget(index, array->GetRawTarget(index - 1));
}
array->SetKey(index, *name);
array->SetTarget(index, *weak_cell_with_target);
array->SetRawTarget(index, HeapObjectReference::Weak(*target));
SLOW_DCHECK(array->IsSortedNoDuplicates());
return;
}
}
// We're gonna need a bigger TransitionArray.
Handle<TransitionArray> result = TransitionArray::Allocate(
isolate, new_nof,
Handle<TransitionArray> result = isolate->factory()->NewTransitionArray(
new_nof,
Map::SlackForArraySize(number_of_transitions, kMaxNumberOfTransitions));
// The map's transition array may have shrunk during the allocation above as
@ -200,7 +199,7 @@ void TransitionsAccessor::Insert(Handle<Name> name, Handle<Map> target,
for (int i = 0; i < insertion_index; ++i) {
result->Set(i, array->GetKey(i), array->GetRawTarget(i));
}
result->Set(insertion_index, *name, *weak_cell_with_target);
result->Set(insertion_index, *name, HeapObjectReference::Weak(*target));
for (int i = insertion_index; i < number_of_transitions; ++i) {
result->Set(i + 1, array->GetKey(i), array->GetRawTarget(i));
}
@ -436,19 +435,9 @@ int TransitionsAccessor::NumberOfTransitions() {
return 0; // Make GCC happy.
}
Handle<TransitionArray> TransitionArray::Allocate(Isolate* isolate,
int number_of_transitions,
int slack) {
Handle<FixedArray> array = isolate->factory()->NewTransitionArray(
LengthFor(number_of_transitions + slack));
array->set(kPrototypeTransitionsIndex, Smi::kZero);
array->set(kTransitionLengthIndex, Smi::FromInt(number_of_transitions));
return Handle<TransitionArray>::cast(array);
}
void TransitionArray::Zap() {
MemsetPointer(data_start() + kPrototypeTransitionsIndex,
GetHeap()->the_hole_value(),
MaybeObject::FromObject(GetHeap()->the_hole_value()),
length() - kPrototypeTransitionsIndex);
SetNumberOfTransitions(0);
}
@ -481,7 +470,7 @@ void TransitionsAccessor::EnsureHasFullTransitionArray() {
if (encoding() == kFullTransitionArray) return;
int nof = encoding() == kUninitialized ? 0 : 1;
Handle<TransitionArray> result =
TransitionArray::Allocate(map_->GetIsolate(), nof);
map_->GetIsolate()->factory()->NewTransitionArray(nof);
Reload(); // Reload after possible GC.
if (nof == 1) {
if (encoding() == kUninitialized) {
@ -491,10 +480,8 @@ void TransitionsAccessor::EnsureHasFullTransitionArray() {
} else {
// Otherwise populate the new array.
Handle<Map> target(GetSimpleTransition());
Handle<WeakCell> weak_cell_with_target = Map::WeakCellForMap(target);
Reload(); // Reload after possible GC.
Name* key = GetSimpleTransitionKey(*target);
result->Set(0, key, *weak_cell_with_target);
result->Set(0, key, HeapObjectReference::Weak(*target));
}
}
ReplaceTransitions(MaybeObject::FromObject(*result));
@ -601,7 +588,7 @@ void TransitionArray::Sort() {
int length = number_of_transitions();
for (int i = 1; i < length; i++) {
Name* key = GetKey(i);
Object* target = GetRawTarget(i);
MaybeObject* target = GetRawTarget(i);
PropertyKind kind = kData;
PropertyAttributes attributes = NONE;
if (!TransitionsAccessor::IsSpecialTransition(key)) {
@ -614,7 +601,7 @@ void TransitionArray::Sort() {
int j;
for (j = i - 1; j >= 0; j--) {
Name* temp_key = GetKey(j);
Object* temp_target = GetRawTarget(j);
MaybeObject* temp_target = GetRawTarget(j);
PropertyKind temp_kind = kData;
PropertyAttributes temp_attributes = NONE;
if (!TransitionsAccessor::IsSpecialTransition(temp_key)) {
@ -630,13 +617,13 @@ void TransitionArray::Sort() {
key, key->Hash(), kind, attributes);
if (cmp > 0) {
SetKey(j + 1, temp_key);
SetTarget(j + 1, temp_target);
SetRawTarget(j + 1, temp_target);
} else {
break;
}
}
SetKey(j + 1, key);
SetTarget(j + 1, target);
SetRawTarget(j + 1, target);
}
DCHECK(IsSortedNoDuplicates());
}

View File

@ -151,7 +151,7 @@ class TransitionsAccessor {
return transition->instance_descriptors()->GetKey(descriptor);
}
static inline Map* GetTargetFromRaw(Object* raw);
static inline Map* GetTargetFromRaw(MaybeObject* raw);
void MarkNeedsReload() {
#if DEBUG
@ -193,30 +193,29 @@ class TransitionsAccessor {
// The TransitionArray class exposes a very low-level interface. Most clients
// should use TransitionsAccessors.
// TransitionArrays have the following format:
// [0] Link to next TransitionArray (for weak handling support)
// [1] Smi(0) or fixed array of prototype transitions
// [0] Link to next TransitionArray (for weak handling support) (strong ref)
// [1] Smi(0) or fixed array of prototype transitions (strong ref)
// [2] Number of transitions (can be zero after trimming)
// [3] First transition key
// [4] First transition target
// [3] First transition key (strong ref)
// [4] First transition target (weak ref)
// ...
// [3 + number of transitions * kTransitionSize]: start of slack
class TransitionArray : public FixedArray {
class TransitionArray : public WeakFixedArray {
public:
DECL_CAST(TransitionArray)
inline FixedArray* GetPrototypeTransitions();
inline Object** GetPrototypeTransitionsSlot();
inline bool HasPrototypeTransitions();
// Accessors for fetching instance transition at transition number.
inline void SetKey(int transition_number, Name* value);
inline Name* GetKey(int transition_number);
inline Object** GetKeySlot(int transition_number);
inline HeapObjectReference** GetKeySlot(int transition_number);
inline Map* GetTarget(int transition_number);
inline void SetTarget(int transition_number, Object* target);
inline Object* GetRawTarget(int transition_number);
inline Object** GetTargetSlot(int transition_number);
inline void SetRawTarget(int transition_number, MaybeObject* target);
inline MaybeObject* GetRawTarget(int transition_number);
inline HeapObjectReference** GetTargetSlot(int transition_number);
inline bool GetTargetIfExists(int transition_number, Isolate* isolate,
Map** target);
@ -267,6 +266,7 @@ class TransitionArray : public FixedArray {
}
private:
friend class Factory;
friend class MarkCompactCollector;
friend class TransitionsAccessor;
@ -300,11 +300,6 @@ class TransitionArray : public FixedArray {
return ToKeyIndex(number_of_transitions);
}
// Allocates a TransitionArray.
static Handle<TransitionArray> Allocate(Isolate* isolate,
int number_of_transitions,
int slack = 0);
// Search a transition for a given kind, property name and attributes.
int Search(PropertyKind kind, Name* name, PropertyAttributes attributes,
int* out_insertion_index = nullptr);
@ -319,10 +314,7 @@ class TransitionArray : public FixedArray {
int SearchDetails(int transition, PropertyKind kind,
PropertyAttributes attributes, int* out_insertion_index);
int number_of_transitions() const {
if (length() < kFirstIndex) return 0;
return Smi::ToInt(get(kTransitionLengthIndex));
}
inline int number_of_transitions() const;
static bool CompactPrototypeTransitionArray(FixedArray* array);
@ -348,7 +340,7 @@ class TransitionArray : public FixedArray {
PropertyKind kind2,
PropertyAttributes attributes2);
inline void Set(int transition_number, Name* key, Object* target);
inline void Set(int transition_number, Name* key, MaybeObject* target);
void Zap();

View File

@ -5497,13 +5497,14 @@ TEST(ContinuousLeftTrimFixedArrayInBlackArea) {
heap::GcAndSweep(heap, OLD_SPACE);
}
TEST(ContinuousRightTrimFixedArrayInBlackArea) {
template <typename T, typename NewFunction, typename TrimFunction>
void ContinuousRightTrimFixedArrayInBlackAreaHelper(NewFunction& new_func,
TrimFunction& trim_func) {
if (!FLAG_incremental_marking) return;
FLAG_black_allocation = true;
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Heap* heap = CcTest::heap();
Isolate* isolate = heap->isolate();
CcTest::CollectAllGarbage();
i::MarkCompactCollector* collector = heap->mark_compact_collector();
@ -5522,10 +5523,10 @@ TEST(ContinuousRightTrimFixedArrayInBlackArea) {
// Ensure that we allocate a new page, set up a bump pointer area, and
// perform the allocation in a black area.
heap::SimulateFullSpace(heap->old_space());
isolate->factory()->NewFixedArray(10, TENURED);
new_func(10, TENURED);
// Allocate the fixed array that will be trimmed later.
Handle<FixedArray> array = isolate->factory()->NewFixedArray(100, TENURED);
Handle<T> array = new_func(100, TENURED);
Address start_address = array->address();
Address end_address = start_address + array->Size();
Page* page = Page::FromAddress(start_address);
@ -5539,7 +5540,7 @@ TEST(ContinuousRightTrimFixedArrayInBlackArea) {
// Trim it once by one word to make checking for white marking color uniform.
Address previous = end_address - kPointerSize;
heap->RightTrimFixedArray(*array, 1);
trim_func(*array, 1);
HeapObject* filler = HeapObject::FromAddress(previous);
CHECK(filler->IsFiller());
CHECK(marking_state->IsImpossible(filler));
@ -5548,7 +5549,7 @@ TEST(ContinuousRightTrimFixedArrayInBlackArea) {
for (int i = 1; i <= 3; i++) {
for (int j = 0; j < 10; j++) {
previous -= kPointerSize * i;
heap->RightTrimFixedArray(*array, i);
trim_func(*array, i);
HeapObject* filler = HeapObject::FromAddress(previous);
CHECK(filler->IsFiller());
CHECK(marking_state->IsWhite(filler));
@ -5558,6 +5559,29 @@ TEST(ContinuousRightTrimFixedArrayInBlackArea) {
heap::GcAndSweep(heap, OLD_SPACE);
}
TEST(ContinuousRightTrimFixedArrayInBlackArea) {
auto new_func = [](int size, PretenureFlag tenured) {
return CcTest::i_isolate()->factory()->NewFixedArray(size, tenured);
};
auto trim_func = [](FixedArray* array, int elements_to_trim) {
CcTest::i_isolate()->heap()->RightTrimFixedArray(array, elements_to_trim);
};
ContinuousRightTrimFixedArrayInBlackAreaHelper<FixedArray>(new_func,
trim_func);
}
TEST(ContinuousRightTrimWeakFixedArrayInBlackArea) {
auto new_func = [](int size, PretenureFlag tenured) {
return CcTest::i_isolate()->factory()->NewWeakFixedArray(size, tenured);
};
auto trim_func = [](WeakFixedArray* array, int elements_to_trim) {
CcTest::i_isolate()->heap()->RightTrimWeakFixedArray(array,
elements_to_trim);
};
ContinuousRightTrimFixedArrayInBlackAreaHelper<WeakFixedArray>(new_func,
trim_func);
}
TEST(Regress618958) {
if (!FLAG_incremental_marking) return;
CcTest::InitializeVM();

View File

@ -89,30 +89,30 @@ INSTANCE_TYPES = {
185: "DESCRIPTOR_ARRAY_TYPE",
186: "HASH_TABLE_TYPE",
187: "SCOPE_INFO_TYPE",
188: "TRANSITION_ARRAY_TYPE",
189: "BLOCK_CONTEXT_TYPE",
190: "CATCH_CONTEXT_TYPE",
191: "DEBUG_EVALUATE_CONTEXT_TYPE",
192: "EVAL_CONTEXT_TYPE",
193: "FUNCTION_CONTEXT_TYPE",
194: "MODULE_CONTEXT_TYPE",
195: "NATIVE_CONTEXT_TYPE",
196: "SCRIPT_CONTEXT_TYPE",
197: "WITH_CONTEXT_TYPE",
198: "CALL_HANDLER_INFO_TYPE",
199: "CELL_TYPE",
200: "CODE_DATA_CONTAINER_TYPE",
201: "FEEDBACK_CELL_TYPE",
202: "FEEDBACK_VECTOR_TYPE",
203: "LOAD_HANDLER_TYPE",
204: "PROPERTY_ARRAY_TYPE",
205: "PROPERTY_CELL_TYPE",
206: "SHARED_FUNCTION_INFO_TYPE",
207: "SMALL_ORDERED_HASH_MAP_TYPE",
208: "SMALL_ORDERED_HASH_SET_TYPE",
209: "STORE_HANDLER_TYPE",
210: "WEAK_CELL_TYPE",
211: "WEAK_FIXED_ARRAY_TYPE",
188: "BLOCK_CONTEXT_TYPE",
189: "CATCH_CONTEXT_TYPE",
190: "DEBUG_EVALUATE_CONTEXT_TYPE",
191: "EVAL_CONTEXT_TYPE",
192: "FUNCTION_CONTEXT_TYPE",
193: "MODULE_CONTEXT_TYPE",
194: "NATIVE_CONTEXT_TYPE",
195: "SCRIPT_CONTEXT_TYPE",
196: "WITH_CONTEXT_TYPE",
197: "WEAK_FIXED_ARRAY_TYPE",
198: "TRANSITION_ARRAY_TYPE",
199: "CALL_HANDLER_INFO_TYPE",
200: "CELL_TYPE",
201: "CODE_DATA_CONTAINER_TYPE",
202: "FEEDBACK_CELL_TYPE",
203: "FEEDBACK_VECTOR_TYPE",
204: "LOAD_HANDLER_TYPE",
205: "PROPERTY_ARRAY_TYPE",
206: "PROPERTY_CELL_TYPE",
207: "SHARED_FUNCTION_INFO_TYPE",
208: "SMALL_ORDERED_HASH_MAP_TYPE",
209: "SMALL_ORDERED_HASH_SET_TYPE",
210: "STORE_HANDLER_TYPE",
211: "WEAK_CELL_TYPE",
212: "WEAK_ARRAY_LIST_TYPE",
1024: "JS_PROXY_TYPE",
1025: "JS_GLOBAL_OBJECT_TYPE",
@ -178,57 +178,57 @@ KNOWN_MAPS = {
("MAP_SPACE", 0x02781): (128, "SymbolMap"),
("MAP_SPACE", 0x027d9): (72, "OneByteStringMap"),
("MAP_SPACE", 0x02831): (187, "ScopeInfoMap"),
("MAP_SPACE", 0x02889): (206, "SharedFunctionInfoMap"),
("MAP_SPACE", 0x02889): (207, "SharedFunctionInfoMap"),
("MAP_SPACE", 0x028e1): (133, "CodeMap"),
("MAP_SPACE", 0x02939): (193, "FunctionContextMap"),
("MAP_SPACE", 0x02991): (199, "CellMap"),
("MAP_SPACE", 0x029e9): (210, "WeakCellMap"),
("MAP_SPACE", 0x02a41): (205, "GlobalPropertyCellMap"),
("MAP_SPACE", 0x02939): (192, "FunctionContextMap"),
("MAP_SPACE", 0x02991): (200, "CellMap"),
("MAP_SPACE", 0x029e9): (211, "WeakCellMap"),
("MAP_SPACE", 0x02a41): (206, "GlobalPropertyCellMap"),
("MAP_SPACE", 0x02a99): (135, "ForeignMap"),
("MAP_SPACE", 0x02af1): (188, "TransitionArrayMap"),
("MAP_SPACE", 0x02b49): (202, "FeedbackVectorMap"),
("MAP_SPACE", 0x02af1): (198, "TransitionArrayMap"),
("MAP_SPACE", 0x02b49): (203, "FeedbackVectorMap"),
("MAP_SPACE", 0x02ba1): (131, "ArgumentsMarkerMap"),
("MAP_SPACE", 0x02bf9): (131, "ExceptionMap"),
("MAP_SPACE", 0x02c51): (131, "TerminationExceptionMap"),
("MAP_SPACE", 0x02ca9): (131, "OptimizedOutMap"),
("MAP_SPACE", 0x02d01): (131, "StaleRegisterMap"),
("MAP_SPACE", 0x02d59): (195, "NativeContextMap"),
("MAP_SPACE", 0x02db1): (194, "ModuleContextMap"),
("MAP_SPACE", 0x02e09): (192, "EvalContextMap"),
("MAP_SPACE", 0x02e61): (196, "ScriptContextMap"),
("MAP_SPACE", 0x02eb9): (189, "BlockContextMap"),
("MAP_SPACE", 0x02f11): (190, "CatchContextMap"),
("MAP_SPACE", 0x02f69): (197, "WithContextMap"),
("MAP_SPACE", 0x02fc1): (191, "DebugEvaluateContextMap"),
("MAP_SPACE", 0x02d59): (194, "NativeContextMap"),
("MAP_SPACE", 0x02db1): (193, "ModuleContextMap"),
("MAP_SPACE", 0x02e09): (191, "EvalContextMap"),
("MAP_SPACE", 0x02e61): (195, "ScriptContextMap"),
("MAP_SPACE", 0x02eb9): (188, "BlockContextMap"),
("MAP_SPACE", 0x02f11): (189, "CatchContextMap"),
("MAP_SPACE", 0x02f69): (196, "WithContextMap"),
("MAP_SPACE", 0x02fc1): (190, "DebugEvaluateContextMap"),
("MAP_SPACE", 0x03019): (183, "ScriptContextTableMap"),
("MAP_SPACE", 0x03071): (151, "FeedbackMetadataArrayMap"),
("MAP_SPACE", 0x030c9): (183, "ArrayListMap"),
("MAP_SPACE", 0x03121): (130, "BigIntMap"),
("MAP_SPACE", 0x03179): (184, "BoilerplateDescriptionMap"),
("MAP_SPACE", 0x031d1): (137, "BytecodeArrayMap"),
("MAP_SPACE", 0x03229): (200, "CodeDataContainerMap"),
("MAP_SPACE", 0x03229): (201, "CodeDataContainerMap"),
("MAP_SPACE", 0x03281): (1057, "ExternalMap"),
("MAP_SPACE", 0x032d9): (150, "FixedDoubleArrayMap"),
("MAP_SPACE", 0x03331): (186, "GlobalDictionaryMap"),
("MAP_SPACE", 0x03389): (201, "ManyClosuresCellMap"),
("MAP_SPACE", 0x03389): (202, "ManyClosuresCellMap"),
("MAP_SPACE", 0x033e1): (1072, "JSMessageObjectMap"),
("MAP_SPACE", 0x03439): (183, "ModuleInfoMap"),
("MAP_SPACE", 0x03491): (134, "MutableHeapNumberMap"),
("MAP_SPACE", 0x034e9): (186, "NameDictionaryMap"),
("MAP_SPACE", 0x03541): (201, "NoClosuresCellMap"),
("MAP_SPACE", 0x03541): (202, "NoClosuresCellMap"),
("MAP_SPACE", 0x03599): (186, "NumberDictionaryMap"),
("MAP_SPACE", 0x035f1): (201, "OneClosureCellMap"),
("MAP_SPACE", 0x035f1): (202, "OneClosureCellMap"),
("MAP_SPACE", 0x03649): (186, "OrderedHashMapMap"),
("MAP_SPACE", 0x036a1): (186, "OrderedHashSetMap"),
("MAP_SPACE", 0x036f9): (204, "PropertyArrayMap"),
("MAP_SPACE", 0x03751): (198, "SideEffectCallHandlerInfoMap"),
("MAP_SPACE", 0x037a9): (198, "SideEffectFreeCallHandlerInfoMap"),
("MAP_SPACE", 0x036f9): (205, "PropertyArrayMap"),
("MAP_SPACE", 0x03751): (199, "SideEffectCallHandlerInfoMap"),
("MAP_SPACE", 0x037a9): (199, "SideEffectFreeCallHandlerInfoMap"),
("MAP_SPACE", 0x03801): (186, "SimpleNumberDictionaryMap"),
("MAP_SPACE", 0x03859): (183, "SloppyArgumentsElementsMap"),
("MAP_SPACE", 0x038b1): (207, "SmallOrderedHashMapMap"),
("MAP_SPACE", 0x03909): (208, "SmallOrderedHashSetMap"),
("MAP_SPACE", 0x038b1): (208, "SmallOrderedHashMapMap"),
("MAP_SPACE", 0x03909): (209, "SmallOrderedHashSetMap"),
("MAP_SPACE", 0x03961): (186, "StringTableMap"),
("MAP_SPACE", 0x039b9): (211, "WeakFixedArrayMap"),
("MAP_SPACE", 0x039b9): (197, "WeakFixedArrayMap"),
("MAP_SPACE", 0x03a11): (212, "WeakArrayListMap"),
("MAP_SPACE", 0x03a69): (106, "NativeSourceStringMap"),
("MAP_SPACE", 0x03ac1): (64, "StringMap"),