From 7560b33eba7deb8e6544ba70325921ebed25d05c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marja=20H=C3=B6ltt=C3=A4?= Date: Wed, 18 Apr 2018 15:29:58 +0200 Subject: [PATCH] [in-place weak refs] Replace WeakCells in TransitionArray. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BUG=v8:7308 Change-Id: I1976cd7e542a0304f6e14744e634c62dd06a83f5 Reviewed-on: https://chromium-review.googlesource.com/1014090 Commit-Queue: Marja Hölttä Reviewed-by: Ulan Degenbaev Cr-Commit-Position: refs/heads/master@{#52672} --- src/code-stub-assembler.cc | 91 ++++++++++++++++++----- src/code-stub-assembler.h | 22 ++++++ src/heap/factory.cc | 34 ++++++++- src/heap/factory.h | 10 ++- src/heap/heap.cc | 21 +++++- src/heap/heap.h | 4 + src/heap/mark-compact.cc | 18 +++-- src/ic/keyed-store-generic.cc | 7 +- src/objects-debug.cc | 2 +- src/objects-inl.h | 9 ++- src/objects-printer.cc | 2 +- src/objects.cc | 6 ++ src/objects.h | 13 +++- src/objects/fixed-array-inl.h | 5 +- src/objects/fixed-array.h | 5 ++ src/profiler/heap-snapshot-generator.cc | 1 + src/transitions-inl.h | 75 +++++++++++-------- src/transitions.cc | 51 +++++-------- src/transitions.h | 34 ++++----- test/cctest/heap/test-heap.cc | 36 +++++++-- tools/v8heapconst.py | 98 ++++++++++++------------- 21 files changed, 359 insertions(+), 185 deletions(-) diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc index e0700a03db..db0024ee5c 100644 --- a/src/code-stub-assembler.cc +++ b/src/code-stub-assembler.cc @@ -1434,6 +1434,7 @@ TNode CodeStubAssembler::LoadFastJSArrayLength( TNode CodeStubAssembler::LoadFixedArrayBaseLength( SloppyTNode array) { + CSA_SLOW_ASSERT(this, IsNotWeakFixedArraySubclass(array)); return CAST(LoadObjectField(array, FixedArrayBase::kLengthOffset)); } @@ -1442,6 +1443,11 @@ TNode CodeStubAssembler::LoadAndUntagFixedArrayBaseLength( return LoadAndUntagObjectField(array, FixedArrayBase::kLengthOffset); } +TNode CodeStubAssembler::LoadAndUntagWeakFixedArrayLength( + SloppyTNode array) { + return LoadAndUntagObjectField(array, WeakFixedArray::kLengthOffset); +} + TNode CodeStubAssembler::LoadMapBitField(SloppyTNode map) { CSA_SLOW_ASSERT(this, IsMap(map)); return UncheckedCast( @@ -1706,20 +1712,42 @@ void CodeStubAssembler::DispatchMaybeObject(Node* maybe_object, Label* if_smi, Goto(if_strong); } -TNode CodeStubAssembler::LoadFixedArrayElement( - SloppyTNode 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 CodeStubAssembler::LoadArrayElement( + SloppyTNode 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 offset = ElementOffsetFromIndex(index_node, HOLEY_ELEMENTS, parameter_mode, header_size); return UncheckedCast( Load(MachineType::AnyTagged(), object, offset, needs_poisoning)); } +TNode CodeStubAssembler::LoadFixedArrayElement( + SloppyTNode 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 CodeStubAssembler::LoadFixedTypedArrayBackingStore( TNode typed_array) { // Backing store = external_pointer + base_pointer. @@ -1941,13 +1969,11 @@ TNode CodeStubAssembler::LoadFeedbackVectorSlot( return UncheckedCast(Load(MachineType::AnyTagged(), object, offset)); } -TNode CodeStubAssembler::LoadAndUntagToWord32FixedArrayElement( - SloppyTNode object, Node* index_node, int additional_offset, - ParameterMode parameter_mode) { - CSA_SLOW_ASSERT(this, IsFixedArraySubclass(object)); +TNode CodeStubAssembler::LoadAndUntagToWord32ArrayElement( + SloppyTNode 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 CodeStubAssembler::LoadAndUntagToWord32FixedArrayElement( } } +TNode CodeStubAssembler::LoadAndUntagToWord32FixedArrayElement( + SloppyTNode 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 unique_name, Label* if_found, TVariable* var_name_index, Label* if_not_found) { + static_assert(std::is_base_of::value || + std::is_base_of::value, + "T must be a descendant of FixedArray or a TransitionArray"); Comment("LookupLinear"); TNode first_inclusive = IntPtrConstant(Array::ToKeyIndex(0)); TNode factor = IntPtrConstant(Array::kEntrySize); @@ -6858,8 +6904,9 @@ void CodeStubAssembler::LookupLinear(TNode unique_name, BuildFastLoop(last_exclusive, first_inclusive, [=](SloppyTNode name_index) { - TNode candidate_name = - CAST(LoadFixedArrayElement(array, name_index)); + TNode 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 CodeStubAssembler::NumberOfEntries( template <> TNode CodeStubAssembler::NumberOfEntries( TNode transitions) { - TNode length = LoadAndUntagFixedArrayBaseLength(transitions); + TNode length = LoadAndUntagWeakFixedArrayLength(transitions); return Select( 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 CodeStubAssembler::GetSortedKeyIndex( template TNode CodeStubAssembler::GetKey(TNode array, TNode entry_index) { - const int key_offset = DescriptorArray::ToKeyIndex(0) * kPointerSize; - return CAST(LoadFixedArrayElement( - array, EntryIndexToIndex(entry_index), key_offset)); + static_assert(std::is_base_of::value || + std::is_base_of::value, + "T must be a descendant of FixedArray or a TransitionArray"); + const int key_offset = Array::ToKeyIndex(0) * kPointerSize; + TNode key = + CAST(LoadArrayElement(array, Array::kHeaderSize, + EntryIndexToIndex(entry_index), key_offset)); + CSA_ASSERT(this, IsStrongHeapObject(key)); + return key; } template TNode CodeStubAssembler::GetKey( diff --git a/src/code-stub-assembler.h b/src/code-stub-assembler.h index 816b47a44f..c556beb20a 100644 --- a/src/code-stub-assembler.h +++ b/src/code-stub-assembler.h @@ -573,6 +573,9 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { // Load the length of a fixed array base instance. TNode LoadAndUntagFixedArrayBaseLength( SloppyTNode array); + // Load the length of a WeakFixedArray. + TNode LoadAndUntagWeakFixedArrayLength( + SloppyTNode array); // Load the bit field of a Map. TNode LoadMapBitField(SloppyTNode 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 LoadArrayElement( + SloppyTNode 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 LoadFixedArrayElement( @@ -679,6 +691,14 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { TNode LoadFixedArrayElement(TNode object, TNode index) { return LoadFixedArrayElement(object, index, 0, SMI_PARAMETERS); } + + // Load an array element from a FixedArray / WeakFixedArray, untag it and + // return it as Word32. + TNode LoadAndUntagToWord32ArrayElement( + SloppyTNode 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 LoadAndUntagToWord32FixedArrayElement( SloppyTNode 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)); } diff --git a/src/heap/factory.cc b/src/heap/factory.cc index 66da832fbd..b408ebb83d 100644 --- a/src/heap/factory.cc +++ b/src/heap/factory.cc @@ -227,6 +227,29 @@ Handle Factory::NewFixedArrayWithMap(Heap::RootListIndex map_root_index, map_root_index, length, *undefined_value(), pretenure)); } +template +Handle Factory::NewWeakFixedArrayWithMap(Heap::RootListIndex map_root_index, + int length, + PretenureFlag pretenure) { + static_assert(std::is_base_of::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 array(WeakFixedArray::cast(result), isolate()); + array->set_length(length); + MemsetPointer(array->data_start(), + HeapObjectReference::Strong(*undefined_value()), length); + + return Handle::cast(array); +} + template Handle Factory::NewFixedArrayWithMap( Heap::RootListIndex, int, PretenureFlag); @@ -1619,8 +1642,10 @@ Handle Factory::NewWeakCell(Handle value) { return cell; } -Handle Factory::NewTransitionArray(int capacity) { - Handle array = NewFixedArrayWithMap( +Handle Factory::NewTransitionArray(int number_of_transitions, + int slack) { + int capacity = TransitionArray::LengthFor(number_of_transitions + slack); + Handle array = NewWeakFixedArrayWithMap( 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 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; } diff --git a/src/heap/factory.h b/src/heap/factory.h index fc4f96e89f..01502abc41 100644 --- a/src/heap/factory.h +++ b/src/heap/factory.h @@ -93,6 +93,13 @@ class V8_EXPORT_PRIVATE Factory { Handle 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 + Handle NewWeakFixedArrayWithMap(Heap::RootListIndex map_root_index, + int length, + PretenureFlag pretenure = NOT_TENURED); + // Allocates a fixed array initialized with undefined values. Handle NewFixedArray(int length, PretenureFlag pretenure = NOT_TENURED); @@ -441,7 +448,8 @@ class V8_EXPORT_PRIVATE Factory { Handle NewOneClosureCell(Handle value); Handle NewManyClosuresCell(Handle value); - Handle NewTransitionArray(int capacity); + Handle NewTransitionArray(int number_of_transitions, + int slack = 0); // Allocate a tenured AllocationSite. Its payload is null. Handle NewAllocationSite(); diff --git a/src/heap/heap.cc b/src/heap/heap.cc index 862a9e514e..2efba232d5 100644 --- a/src/heap/heap.cc +++ b/src/heap/heap.cc @@ -2853,14 +2853,27 @@ void Heap::RightTrimFixedArray(FixedArrayBase* object, int elements_to_trim) { bytes_to_trim = elements_to_trim * kDoubleSize; } + CreateFillerForArray(object, elements_to_trim, bytes_to_trim); +} + +void Heap::RightTrimWeakFixedArray(WeakFixedArray* object, + int elements_to_trim) { + CreateFillerForArray(object, elements_to_trim, + elements_to_trim * kPointerSize); +} + +template +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. diff --git a/src/heap/heap.h b/src/heap/heap.h index b7c2ebe28f..f497847347 100644 --- a/src/heap/heap.h +++ b/src/heap/heap.h @@ -772,6 +772,9 @@ class Heap { ClearFreedMemoryMode clear_memory_mode = ClearFreedMemoryMode::kDontClearFreedMemory); + template + 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); diff --git a/src/heap/mark-compact.cc b/src/heap/mark-compact.cc index 9e8271d832..3354311a46 100644 --- a/src/heap/mark-compact.cc +++ b/src/heap/mark-compact.cc @@ -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; diff --git a/src/ic/keyed-store-generic.cc b/src/ic/keyed-store-generic.cc index 94facc8ee4..b18620508b 100644 --- a/src/ic/keyed-store-generic.cc +++ b/src/ic/keyed-store-generic.cc @@ -732,10 +732,9 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore( const int kKeyToTargetOffset = (TransitionArray::kEntryTargetIndex - TransitionArray::kEntryKeyIndex) * kPointerSize; - TNode 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); } } diff --git a/src/objects-debug.cc b/src/objects-debug.cc index 97c5855a87..2e6d24501c 100644 --- a/src/objects-debug.cc +++ b/src/objects-debug.cc @@ -634,7 +634,7 @@ void DescriptorArray::DescriptorArrayVerify() { } void TransitionArray::TransitionArrayVerify() { - FixedArrayVerify(); + WeakFixedArrayVerify(); CHECK_LE(LengthFor(number_of_transitions()), length()); } diff --git a/src/objects-inl.h b/src/objects-inl.h index b6ee98fae5..556631de25 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -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(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(this)->synchronized_length()); } diff --git a/src/objects-printer.cc b/src/objects-printer.cc index 5bcd3fd987..8572622497 100644 --- a/src/objects-printer.cc +++ b/src/objects-printer.cc @@ -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)"; } diff --git a/src/objects.cc b/src/objects.cc index 700d30c17e..9233bd1596 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -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 array, int index, diff --git a/src/objects.h b/src/objects.h index 73bb9cc8dc..ad613e403b 100644 --- a/src/objects.h +++ b/src/objects.h @@ -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, diff --git a/src/objects/fixed-array-inl.h b/src/objects/fixed-array-inl.h index 8d09395aab..db8e729822 100644 --- a/src/objects/fixed-array-inl.h +++ b/src/objects/fixed-array-inl.h @@ -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)); diff --git a/src/objects/fixed-array.h b/src/objects/fixed-array.h index 3b2f0b7f17..1be971b9b7 100644 --- a/src/objects/fixed-array.h +++ b/src/objects/fixed-array.h @@ -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) diff --git a/src/profiler/heap-snapshot-generator.cc b/src/profiler/heap-snapshot-generator.cc index a7eb4fb3fd..c09a7a0bfe 100644 --- a/src/profiler/heap-snapshot-generator.cc +++ b/src/profiler/heap-snapshot-generator.cc @@ -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)); } diff --git a/src/transitions-inl.h b/src/transitions-inl.h index 8261b3684b..eb9ddba492 100644 --- a/src/transitions-inl.h +++ b/src/transitions-inl.h @@ -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( + 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( + 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 diff --git a/src/transitions.cc b/src/transitions.cc index f4154a8e34..e10374efaf 100644 --- a/src/transitions.cc +++ b/src/transitions.cc @@ -68,7 +68,8 @@ void TransitionsAccessor::Insert(Handle name, Handle target, return; } // If the flag requires a full TransitionArray, allocate one. - Handle result = TransitionArray::Allocate(isolate, 0, 1); + Handle result = + isolate->factory()->NewTransitionArray(0, 1); ReplaceTransitions(MaybeObject::FromObject(*result)); Reload(); } @@ -90,15 +91,16 @@ void TransitionsAccessor::Insert(Handle name, Handle target, } // Otherwise allocate a full TransitionArray with slack for a new entry. Handle map(simple_transition); - Handle weak_cell = Map::WeakCellForMap(map); - Handle result = TransitionArray::Allocate(isolate, 1, 1); + Handle 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, Handle target, // At this point, we know that the map has a full TransitionArray. DCHECK_EQ(kFullTransitionArray, encoding()); - Handle 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, Handle 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, Handle 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 result = TransitionArray::Allocate( - isolate, new_nof, + Handle 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, Handle 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::Allocate(Isolate* isolate, - int number_of_transitions, - int slack) { - Handle array = isolate->factory()->NewTransitionArray( - LengthFor(number_of_transitions + slack)); - array->set(kPrototypeTransitionsIndex, Smi::kZero); - array->set(kTransitionLengthIndex, Smi::FromInt(number_of_transitions)); - return Handle::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 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 target(GetSimpleTransition()); - Handle 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()); } diff --git a/src/transitions.h b/src/transitions.h index 5b88352351..99f4fbbb72 100644 --- a/src/transitions.h +++ b/src/transitions.h @@ -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 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(); diff --git a/test/cctest/heap/test-heap.cc b/test/cctest/heap/test-heap.cc index 0c6866c564..5d916e7e7c 100644 --- a/test/cctest/heap/test-heap.cc +++ b/test/cctest/heap/test-heap.cc @@ -5497,13 +5497,14 @@ TEST(ContinuousLeftTrimFixedArrayInBlackArea) { heap::GcAndSweep(heap, OLD_SPACE); } -TEST(ContinuousRightTrimFixedArrayInBlackArea) { +template +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 array = isolate->factory()->NewFixedArray(100, TENURED); + Handle 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(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(new_func, + trim_func); +} + TEST(Regress618958) { if (!FLAG_incremental_marking) return; CcTest::InitializeVM(); diff --git a/tools/v8heapconst.py b/tools/v8heapconst.py index 69ab6098bd..fbeabd51cb 100644 --- a/tools/v8heapconst.py +++ b/tools/v8heapconst.py @@ -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"),