[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( TNode<Smi> CodeStubAssembler::LoadFixedArrayBaseLength(
SloppyTNode<FixedArrayBase> array) { SloppyTNode<FixedArrayBase> array) {
CSA_SLOW_ASSERT(this, IsNotWeakFixedArraySubclass(array));
return CAST(LoadObjectField(array, FixedArrayBase::kLengthOffset)); return CAST(LoadObjectField(array, FixedArrayBase::kLengthOffset));
} }
@ -1442,6 +1443,11 @@ TNode<IntPtrT> CodeStubAssembler::LoadAndUntagFixedArrayBaseLength(
return LoadAndUntagObjectField(array, FixedArrayBase::kLengthOffset); return LoadAndUntagObjectField(array, FixedArrayBase::kLengthOffset);
} }
TNode<IntPtrT> CodeStubAssembler::LoadAndUntagWeakFixedArrayLength(
SloppyTNode<WeakFixedArray> array) {
return LoadAndUntagObjectField(array, WeakFixedArray::kLengthOffset);
}
TNode<Int32T> CodeStubAssembler::LoadMapBitField(SloppyTNode<Map> map) { TNode<Int32T> CodeStubAssembler::LoadMapBitField(SloppyTNode<Map> map) {
CSA_SLOW_ASSERT(this, IsMap(map)); CSA_SLOW_ASSERT(this, IsMap(map));
return UncheckedCast<Int32T>( return UncheckedCast<Int32T>(
@ -1706,20 +1712,42 @@ void CodeStubAssembler::DispatchMaybeObject(Node* maybe_object, Label* if_smi,
Goto(if_strong); Goto(if_strong);
} }
TNode<Object> CodeStubAssembler::LoadFixedArrayElement( Node* CodeStubAssembler::IsStrongHeapObject(Node* value) {
SloppyTNode<Object> object, Node* index_node, int additional_offset, return WordEqual(
ParameterMode parameter_mode, LoadSensitivity needs_poisoning) { 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( CSA_SLOW_ASSERT(this, IntPtrGreaterThanOrEqual(
ParameterToIntPtr(index_node, parameter_mode), ParameterToIntPtr(index_node, parameter_mode),
IntPtrConstant(0))); IntPtrConstant(0)));
int32_t header_size = int32_t header_size = array_header_size + additional_offset - kHeapObjectTag;
FixedArray::kHeaderSize + additional_offset - kHeapObjectTag;
TNode<IntPtrT> offset = ElementOffsetFromIndex(index_node, HOLEY_ELEMENTS, TNode<IntPtrT> offset = ElementOffsetFromIndex(index_node, HOLEY_ELEMENTS,
parameter_mode, header_size); parameter_mode, header_size);
return UncheckedCast<Object>( return UncheckedCast<Object>(
Load(MachineType::AnyTagged(), object, offset, needs_poisoning)); 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<RawPtrT> CodeStubAssembler::LoadFixedTypedArrayBackingStore(
TNode<FixedTypedArrayBase> typed_array) { TNode<FixedTypedArrayBase> typed_array) {
// Backing store = external_pointer + base_pointer. // Backing store = external_pointer + base_pointer.
@ -1941,13 +1969,11 @@ TNode<Object> CodeStubAssembler::LoadFeedbackVectorSlot(
return UncheckedCast<Object>(Load(MachineType::AnyTagged(), object, offset)); return UncheckedCast<Object>(Load(MachineType::AnyTagged(), object, offset));
} }
TNode<Int32T> CodeStubAssembler::LoadAndUntagToWord32FixedArrayElement( TNode<Int32T> CodeStubAssembler::LoadAndUntagToWord32ArrayElement(
SloppyTNode<Object> object, Node* index_node, int additional_offset, SloppyTNode<Object> object, int array_header_size, Node* index_node,
ParameterMode parameter_mode) { int additional_offset, ParameterMode parameter_mode) {
CSA_SLOW_ASSERT(this, IsFixedArraySubclass(object));
CSA_SLOW_ASSERT(this, MatchesParameterMode(index_node, parameter_mode)); CSA_SLOW_ASSERT(this, MatchesParameterMode(index_node, parameter_mode));
int32_t header_size = int32_t header_size = array_header_size + additional_offset - kHeapObjectTag;
FixedArray::kHeaderSize + additional_offset - kHeapObjectTag;
#if V8_TARGET_LITTLE_ENDIAN #if V8_TARGET_LITTLE_ENDIAN
if (Is64()) { if (Is64()) {
header_size += kPointerSize / 2; 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* CodeStubAssembler::LoadFixedDoubleArrayElement(
Node* object, Node* index_node, MachineType machine_type, Node* object, Node* index_node, MachineType machine_type,
int additional_offset, ParameterMode parameter_mode, Label* if_hole) { int additional_offset, ParameterMode parameter_mode, Label* if_hole) {
@ -4676,6 +4711,14 @@ Node* CodeStubAssembler::IsFixedArraySubclass(Node* object) {
Int32Constant(LAST_FIXED_ARRAY_TYPE))); 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) { Node* CodeStubAssembler::IsPromiseCapability(Node* object) {
return HasInstanceType(object, PROMISE_CAPABILITY_TYPE); return HasInstanceType(object, PROMISE_CAPABILITY_TYPE);
} }
@ -6849,6 +6892,9 @@ void CodeStubAssembler::LookupLinear(TNode<Name> unique_name,
Label* if_found, Label* if_found,
TVariable<IntPtrT>* var_name_index, TVariable<IntPtrT>* var_name_index,
Label* if_not_found) { 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"); Comment("LookupLinear");
TNode<IntPtrT> first_inclusive = IntPtrConstant(Array::ToKeyIndex(0)); TNode<IntPtrT> first_inclusive = IntPtrConstant(Array::ToKeyIndex(0));
TNode<IntPtrT> factor = IntPtrConstant(Array::kEntrySize); TNode<IntPtrT> factor = IntPtrConstant(Array::kEntrySize);
@ -6858,8 +6904,9 @@ void CodeStubAssembler::LookupLinear(TNode<Name> unique_name,
BuildFastLoop(last_exclusive, first_inclusive, BuildFastLoop(last_exclusive, first_inclusive,
[=](SloppyTNode<IntPtrT> name_index) { [=](SloppyTNode<IntPtrT> name_index) {
TNode<Name> candidate_name = TNode<Name> candidate_name = CAST(
CAST(LoadFixedArrayElement(array, name_index)); LoadArrayElement(array, Array::kHeaderSize, name_index));
CSA_ASSERT(this, IsStrongHeapObject(candidate_name));
*var_name_index = name_index; *var_name_index = name_index;
GotoIf(WordEqual(candidate_name, unique_name), if_found); GotoIf(WordEqual(candidate_name, unique_name), if_found);
}, },
@ -6877,13 +6924,13 @@ TNode<Uint32T> CodeStubAssembler::NumberOfEntries<DescriptorArray>(
template <> template <>
TNode<Uint32T> CodeStubAssembler::NumberOfEntries<TransitionArray>( TNode<Uint32T> CodeStubAssembler::NumberOfEntries<TransitionArray>(
TNode<TransitionArray> transitions) { TNode<TransitionArray> transitions) {
TNode<IntPtrT> length = LoadAndUntagFixedArrayBaseLength(transitions); TNode<IntPtrT> length = LoadAndUntagWeakFixedArrayLength(transitions);
return Select<Uint32T>( return Select<Uint32T>(
UintPtrLessThan(length, IntPtrConstant(TransitionArray::kFirstIndex)), UintPtrLessThan(length, IntPtrConstant(TransitionArray::kFirstIndex)),
[=] { return Unsigned(Int32Constant(0)); }, [=] { return Unsigned(Int32Constant(0)); },
[=] { [=] {
return Unsigned(LoadAndUntagToWord32FixedArrayElement( return Unsigned(LoadAndUntagToWord32ArrayElement(
transitions, transitions, WeakFixedArray::kHeaderSize,
IntPtrConstant(TransitionArray::kTransitionLengthIndex))); IntPtrConstant(TransitionArray::kTransitionLengthIndex)));
}); });
} }
@ -6924,9 +6971,15 @@ TNode<Uint32T> CodeStubAssembler::GetSortedKeyIndex<TransitionArray>(
template <typename Array> template <typename Array>
TNode<Name> CodeStubAssembler::GetKey(TNode<Array> array, TNode<Name> CodeStubAssembler::GetKey(TNode<Array> array,
TNode<Uint32T> entry_index) { TNode<Uint32T> entry_index) {
const int key_offset = DescriptorArray::ToKeyIndex(0) * kPointerSize; static_assert(std::is_base_of<FixedArray, Array>::value ||
return CAST(LoadFixedArrayElement( std::is_base_of<TransitionArray, Array>::value,
array, EntryIndexToIndex<Array>(entry_index), key_offset)); "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>( 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. // Load the length of a fixed array base instance.
TNode<IntPtrT> LoadAndUntagFixedArrayBaseLength( TNode<IntPtrT> LoadAndUntagFixedArrayBaseLength(
SloppyTNode<FixedArrayBase> array); SloppyTNode<FixedArrayBase> array);
// Load the length of a WeakFixedArray.
TNode<IntPtrT> LoadAndUntagWeakFixedArrayLength(
SloppyTNode<WeakFixedArray> array);
// Load the bit field of a Map. // Load the bit field of a Map.
TNode<Int32T> LoadMapBitField(SloppyTNode<Map> map); TNode<Int32T> LoadMapBitField(SloppyTNode<Map> map);
// Load bit field 2 of a 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, void DispatchMaybeObject(Node* maybe_object, Label* if_smi, Label* if_cleared,
Label* if_weak, Label* if_strong, Label* if_weak, Label* if_strong,
Variable* extracted); 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. // Load an array element from a FixedArray.
TNode<Object> LoadFixedArrayElement( TNode<Object> LoadFixedArrayElement(
@ -679,6 +691,14 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
TNode<Object> LoadFixedArrayElement(TNode<Object> object, TNode<Smi> index) { TNode<Object> LoadFixedArrayElement(TNode<Object> object, TNode<Smi> index) {
return LoadFixedArrayElement(object, index, 0, SMI_PARAMETERS); 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. // Load an array element from a FixedArray, untag it and return it as Word32.
TNode<Int32T> LoadAndUntagToWord32FixedArrayElement( TNode<Int32T> LoadAndUntagToWord32FixedArrayElement(
SloppyTNode<Object> object, Node* index, int additional_offset = 0, 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* IsWeakCell(Node* object);
Node* IsZeroOrContext(Node* object); Node* IsZeroOrContext(Node* object);
Node* IsNotWeakFixedArraySubclass(Node* object);
inline Node* IsSharedFunctionInfo(Node* object) { inline Node* IsSharedFunctionInfo(Node* object) {
return IsSharedFunctionInfoMap(LoadMap(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)); 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>( template Handle<FixedArray> Factory::NewFixedArrayWithMap<FixedArray>(
Heap::RootListIndex, int, PretenureFlag); Heap::RootListIndex, int, PretenureFlag);
@ -1619,8 +1642,10 @@ Handle<WeakCell> Factory::NewWeakCell(Handle<HeapObject> value) {
return cell; return cell;
} }
Handle<TransitionArray> Factory::NewTransitionArray(int capacity) { Handle<TransitionArray> Factory::NewTransitionArray(int number_of_transitions,
Handle<TransitionArray> array = NewFixedArrayWithMap<TransitionArray>( int slack) {
int capacity = TransitionArray::LengthFor(number_of_transitions + slack);
Handle<TransitionArray> array = NewWeakFixedArrayWithMap<TransitionArray>(
Heap::kTransitionArrayMapRootIndex, capacity, TENURED); Heap::kTransitionArrayMapRootIndex, capacity, TENURED);
// Transition arrays are tenured. When black allocation is on we have to // Transition arrays are tenured. When black allocation is on we have to
// add the transition array to the list of encountered_transition_arrays. // 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()) { if (heap->incremental_marking()->black_allocation()) {
heap->mark_compact_collector()->AddTransitionArray(*array); 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; return array;
} }

View File

@ -93,6 +93,13 @@ class V8_EXPORT_PRIVATE Factory {
Handle<T> NewFixedArrayWithMap(Heap::RootListIndex map_root_index, int length, Handle<T> NewFixedArrayWithMap(Heap::RootListIndex map_root_index, int length,
PretenureFlag pretenure = NOT_TENURED); 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. // Allocates a fixed array initialized with undefined values.
Handle<FixedArray> NewFixedArray(int length, Handle<FixedArray> NewFixedArray(int length,
PretenureFlag pretenure = NOT_TENURED); PretenureFlag pretenure = NOT_TENURED);
@ -441,7 +448,8 @@ class V8_EXPORT_PRIVATE Factory {
Handle<FeedbackCell> NewOneClosureCell(Handle<HeapObject> value); Handle<FeedbackCell> NewOneClosureCell(Handle<HeapObject> value);
Handle<FeedbackCell> NewManyClosuresCell(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. // Allocate a tenured AllocationSite. Its payload is null.
Handle<AllocationSite> NewAllocationSite(); 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; 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. // For now this trick is only applied to objects in new and paged space.
DCHECK(object->map() != fixed_cow_array_map()); DCHECK(object->map() != fixed_cow_array_map());
if (bytes_to_trim == 0) { if (bytes_to_trim == 0) {
// No need to create filler and update live bytes counters, just initialize DCHECK_EQ(elements_to_trim, 0);
// header of the trimmed array. // No need to create filler and update live bytes counters.
object->synchronized_set_length(len - elements_to_trim);
return; 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 // 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 // using release store after creating a filler for the left-over space to
// avoid races with the sweeper thread. // 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 // 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. // 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 clear_memory_mode =
ClearFreedMemoryMode::kDontClearFreedMemory); ClearFreedMemoryMode::kDontClearFreedMemory);
template <typename T>
void CreateFillerForArray(T* object, int elements_to_trim, int bytes_to_trim);
bool CanMoveObjectStart(HeapObject* object); bool CanMoveObjectStart(HeapObject* object);
static bool IsImmovable(HeapObject* object); static bool IsImmovable(HeapObject* object);
@ -782,6 +785,7 @@ class Heap {
// Trim the given array from the right. // Trim the given array from the right.
void RightTrimFixedArray(FixedArrayBase* obj, int elements_to_trim); 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. // Converts the given boolean condition to JavaScript boolean value.
inline Oddball* ToBoolean(bool condition); inline Oddball* ToBoolean(bool condition);

View File

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

View File

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

View File

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

View File

@ -140,6 +140,12 @@ bool HeapObject::IsFixedArray() const {
instance_type <= LAST_FIXED_ARRAY_TYPE; 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 { bool HeapObject::IsSloppyArgumentsElements() const {
return IsFixedArrayExact(); return IsFixedArrayExact();
} }
@ -2238,7 +2244,8 @@ int HeapObject::SizeFromMap(Map* map) const {
reinterpret_cast<const FeedbackMetadata*>(this) reinterpret_cast<const FeedbackMetadata*>(this)
->synchronized_slot_count()); ->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( return WeakFixedArray::SizeFor(
reinterpret_cast<const WeakFixedArray*>(this)->synchronized_length()); reinterpret_cast<const WeakFixedArray*>(this)->synchronized_length());
} }

View File

@ -815,7 +815,7 @@ void TransitionArray::TransitionArrayPrint(std::ostream& os) { // NOLINT
HeapObject::PrintHeader(os, "TransitionArray"); HeapObject::PrintHeader(os, "TransitionArray");
os << "\n - capacity: " << length(); os << "\n - capacity: " << length();
for (int i = 0; i < length(); i++) { 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 == kPrototypeTransitionsIndex) os << " (prototype transitions)";
if (i == kTransitionLengthIndex) os << " (number of transitions)"; if (i == kTransitionLengthIndex) os << " (number of transitions)";
} }

View File

@ -10158,6 +10158,12 @@ bool FixedArray::IsEqualTo(FixedArray* other) {
} }
#endif #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 // static
void FixedArrayOfWeakCells::Set(Handle<FixedArrayOfWeakCells> array, int index, 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(DESCRIPTOR_ARRAY_TYPE) \
V(HASH_TABLE_TYPE) \ V(HASH_TABLE_TYPE) \
V(SCOPE_INFO_TYPE) \ V(SCOPE_INFO_TYPE) \
V(TRANSITION_ARRAY_TYPE) \
\ \
V(BLOCK_CONTEXT_TYPE) \ V(BLOCK_CONTEXT_TYPE) \
V(CATCH_CONTEXT_TYPE) \ V(CATCH_CONTEXT_TYPE) \
@ -424,6 +423,9 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
V(SCRIPT_CONTEXT_TYPE) \ V(SCRIPT_CONTEXT_TYPE) \
V(WITH_CONTEXT_TYPE) \ V(WITH_CONTEXT_TYPE) \
\ \
V(WEAK_FIXED_ARRAY_TYPE) \
V(TRANSITION_ARRAY_TYPE) \
\
V(CALL_HANDLER_INFO_TYPE) \ V(CALL_HANDLER_INFO_TYPE) \
V(CELL_TYPE) \ V(CELL_TYPE) \
V(CODE_DATA_CONTAINER_TYPE) \ V(CODE_DATA_CONTAINER_TYPE) \
@ -437,7 +439,6 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
V(SMALL_ORDERED_HASH_SET_TYPE) \ V(SMALL_ORDERED_HASH_SET_TYPE) \
V(STORE_HANDLER_TYPE) \ V(STORE_HANDLER_TYPE) \
V(WEAK_CELL_TYPE) \ V(WEAK_CELL_TYPE) \
V(WEAK_FIXED_ARRAY_TYPE) \
V(WEAK_ARRAY_LIST_TYPE) \ V(WEAK_ARRAY_LIST_TYPE) \
\ \
V(JS_PROXY_TYPE) \ V(JS_PROXY_TYPE) \
@ -782,7 +783,6 @@ enum InstanceType : uint16_t {
DESCRIPTOR_ARRAY_TYPE, DESCRIPTOR_ARRAY_TYPE,
HASH_TABLE_TYPE, HASH_TABLE_TYPE,
SCOPE_INFO_TYPE, SCOPE_INFO_TYPE,
TRANSITION_ARRAY_TYPE,
BLOCK_CONTEXT_TYPE, // FIRST_CONTEXT_TYPE BLOCK_CONTEXT_TYPE, // FIRST_CONTEXT_TYPE
CATCH_CONTEXT_TYPE, CATCH_CONTEXT_TYPE,
DEBUG_EVALUATE_CONTEXT_TYPE, DEBUG_EVALUATE_CONTEXT_TYPE,
@ -793,6 +793,9 @@ enum InstanceType : uint16_t {
SCRIPT_CONTEXT_TYPE, SCRIPT_CONTEXT_TYPE,
WITH_CONTEXT_TYPE, // LAST_FIXED_ARRAY_TYPE, LAST_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. // Misc.
CALL_HANDLER_INFO_TYPE, CALL_HANDLER_INFO_TYPE,
CELL_TYPE, CELL_TYPE,
@ -807,7 +810,6 @@ enum InstanceType : uint16_t {
SMALL_ORDERED_HASH_SET_TYPE, SMALL_ORDERED_HASH_SET_TYPE,
STORE_HANDLER_TYPE, STORE_HANDLER_TYPE,
WEAK_CELL_TYPE, WEAK_CELL_TYPE,
WEAK_FIXED_ARRAY_TYPE,
WEAK_ARRAY_LIST_TYPE, WEAK_ARRAY_LIST_TYPE,
// All the following types are subtypes of JSReceiver, which corresponds to // 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. // Boundaries for testing if given HeapObject is a subclass of FixedArray.
FIRST_FIXED_ARRAY_TYPE = FIXED_ARRAY_TYPE, FIRST_FIXED_ARRAY_TYPE = FIXED_ARRAY_TYPE,
LAST_FIXED_ARRAY_TYPE = WITH_CONTEXT_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 // Boundaries for testing if given HeapObject is a Context
FIRST_CONTEXT_TYPE = BLOCK_CONTEXT_TYPE, FIRST_CONTEXT_TYPE = BLOCK_CONTEXT_TYPE,
LAST_CONTEXT_TYPE = WITH_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(FixedArrayExact, FIXED_ARRAY_TYPE)
TYPE_CHECKER(FixedDoubleArray, FIXED_DOUBLE_ARRAY_TYPE) TYPE_CHECKER(FixedDoubleArray, FIXED_DOUBLE_ARRAY_TYPE)
TYPE_CHECKER(FixedArrayOfWeakCells, FIXED_ARRAY_TYPE) TYPE_CHECKER(FixedArrayOfWeakCells, FIXED_ARRAY_TYPE)
TYPE_CHECKER(WeakFixedArray, WEAK_FIXED_ARRAY_TYPE)
TYPE_CHECKER(WeakArrayList, WEAK_ARRAY_LIST_TYPE) TYPE_CHECKER(WeakArrayList, WEAK_ARRAY_LIST_TYPE)
CAST_ACCESSOR(ArrayList) CAST_ACCESSOR(ArrayList)
@ -242,6 +241,10 @@ MaybeObject** WeakFixedArray::data_start() {
return HeapObject::RawMaybeWeakField(this, kHeaderSize); return HeapObject::RawMaybeWeakField(this, kHeaderSize);
} }
MaybeObject** WeakFixedArray::RawFieldOfElementAt(int index) {
return HeapObject::RawMaybeWeakField(this, OffsetOfElementAt(index));
}
MaybeObject* WeakArrayList::Get(int index) const { MaybeObject* WeakArrayList::Get(int index) const {
SLOW_DCHECK(index >= 0 && index < this->capacity()); SLOW_DCHECK(index >= 0 && index < this->capacity());
return RELAXED_READ_WEAK_FIELD(this, OffsetOfElementAt(index)); 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. // Gives access to raw memory which stores the array's data.
inline MaybeObject** data_start(); inline MaybeObject** data_start();
inline MaybeObject** RawFieldOfElementAt(int index);
// Shrink length and insert filler objects.
void Shrink(int new_length);
DECL_PRINTER(WeakFixedArray) DECL_PRINTER(WeakFixedArray)
DECL_VERIFIER(WeakFixedArray) DECL_VERIFIER(WeakFixedArray)

View File

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

View File

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

View File

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

View File

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

View File

@ -5497,13 +5497,14 @@ TEST(ContinuousLeftTrimFixedArrayInBlackArea) {
heap::GcAndSweep(heap, OLD_SPACE); 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; if (!FLAG_incremental_marking) return;
FLAG_black_allocation = true; FLAG_black_allocation = true;
CcTest::InitializeVM(); CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate()); v8::HandleScope scope(CcTest::isolate());
Heap* heap = CcTest::heap(); Heap* heap = CcTest::heap();
Isolate* isolate = heap->isolate();
CcTest::CollectAllGarbage(); CcTest::CollectAllGarbage();
i::MarkCompactCollector* collector = heap->mark_compact_collector(); 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 // Ensure that we allocate a new page, set up a bump pointer area, and
// perform the allocation in a black area. // perform the allocation in a black area.
heap::SimulateFullSpace(heap->old_space()); heap::SimulateFullSpace(heap->old_space());
isolate->factory()->NewFixedArray(10, TENURED); new_func(10, TENURED);
// Allocate the fixed array that will be trimmed later. // 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 start_address = array->address();
Address end_address = start_address + array->Size(); Address end_address = start_address + array->Size();
Page* page = Page::FromAddress(start_address); 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. // Trim it once by one word to make checking for white marking color uniform.
Address previous = end_address - kPointerSize; Address previous = end_address - kPointerSize;
heap->RightTrimFixedArray(*array, 1); trim_func(*array, 1);
HeapObject* filler = HeapObject::FromAddress(previous); HeapObject* filler = HeapObject::FromAddress(previous);
CHECK(filler->IsFiller()); CHECK(filler->IsFiller());
CHECK(marking_state->IsImpossible(filler)); CHECK(marking_state->IsImpossible(filler));
@ -5548,7 +5549,7 @@ TEST(ContinuousRightTrimFixedArrayInBlackArea) {
for (int i = 1; i <= 3; i++) { for (int i = 1; i <= 3; i++) {
for (int j = 0; j < 10; j++) { for (int j = 0; j < 10; j++) {
previous -= kPointerSize * i; previous -= kPointerSize * i;
heap->RightTrimFixedArray(*array, i); trim_func(*array, i);
HeapObject* filler = HeapObject::FromAddress(previous); HeapObject* filler = HeapObject::FromAddress(previous);
CHECK(filler->IsFiller()); CHECK(filler->IsFiller());
CHECK(marking_state->IsWhite(filler)); CHECK(marking_state->IsWhite(filler));
@ -5558,6 +5559,29 @@ TEST(ContinuousRightTrimFixedArrayInBlackArea) {
heap::GcAndSweep(heap, OLD_SPACE); 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) { TEST(Regress618958) {
if (!FLAG_incremental_marking) return; if (!FLAG_incremental_marking) return;
CcTest::InitializeVM(); CcTest::InitializeVM();

View File

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