diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-12 14:27:29 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-13 09:35:20 +0000 |
commit | c30a6232df03e1efbd9f3b226777b07e087a1122 (patch) | |
tree | e992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/v8/src/heap/memory-chunk.cc | |
parent | 7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff) | |
download | qtwebengine-chromium-85-based.tar.gz |
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/v8/src/heap/memory-chunk.cc')
-rw-r--r-- | chromium/v8/src/heap/memory-chunk.cc | 307 |
1 files changed, 299 insertions, 8 deletions
diff --git a/chromium/v8/src/heap/memory-chunk.cc b/chromium/v8/src/heap/memory-chunk.cc index 865e6f1a72b..4e10719fc3c 100644 --- a/chromium/v8/src/heap/memory-chunk.cc +++ b/chromium/v8/src/heap/memory-chunk.cc @@ -4,8 +4,13 @@ #include "src/heap/memory-chunk.h" +#include "src/base/platform/platform.h" +#include "src/heap/array-buffer-tracker.h" +#include "src/heap/code-object-registry.h" +#include "src/heap/memory-allocator.h" #include "src/heap/memory-chunk-inl.h" #include "src/heap/spaces.h" +#include "src/objects/heap-object.h" namespace v8 { namespace internal { @@ -77,14 +82,6 @@ size_t MemoryChunkLayout::AllocatableMemoryInMemoryChunk( return AllocatableMemoryInDataPage(); } -#ifdef THREAD_SANITIZER -void MemoryChunk::SynchronizedHeapLoad() { - CHECK(reinterpret_cast<Heap*>(base::Acquire_Load( - reinterpret_cast<base::AtomicWord*>(&heap_))) != nullptr || - InReadOnlySpace()); -} -#endif - void MemoryChunk::InitializationMemoryFence() { base::SeqCst_MemoryFence(); #ifdef THREAD_SANITIZER @@ -153,5 +150,299 @@ void MemoryChunk::SetReadAndWritable() { } } +namespace { + +PageAllocator::Permission DefaultWritableCodePermissions() { + return FLAG_jitless ? PageAllocator::kReadWrite + : PageAllocator::kReadWriteExecute; +} + +} // namespace + +MemoryChunk* MemoryChunk::Initialize(BasicMemoryChunk* basic_chunk, Heap* heap, + Executability executable) { + MemoryChunk* chunk = static_cast<MemoryChunk*>(basic_chunk); + + base::AsAtomicPointer::Release_Store(&chunk->slot_set_[OLD_TO_NEW], nullptr); + base::AsAtomicPointer::Release_Store(&chunk->slot_set_[OLD_TO_OLD], nullptr); + base::AsAtomicPointer::Release_Store(&chunk->sweeping_slot_set_, nullptr); + base::AsAtomicPointer::Release_Store(&chunk->typed_slot_set_[OLD_TO_NEW], + nullptr); + base::AsAtomicPointer::Release_Store(&chunk->typed_slot_set_[OLD_TO_OLD], + nullptr); + chunk->invalidated_slots_[OLD_TO_NEW] = nullptr; + chunk->invalidated_slots_[OLD_TO_OLD] = nullptr; + chunk->progress_bar_ = 0; + chunk->set_concurrent_sweeping_state(ConcurrentSweepingState::kDone); + chunk->page_protection_change_mutex_ = new base::Mutex(); + chunk->write_unprotect_counter_ = 0; + chunk->mutex_ = new base::Mutex(); + chunk->young_generation_bitmap_ = nullptr; + chunk->local_tracker_ = nullptr; + + chunk->external_backing_store_bytes_[ExternalBackingStoreType::kArrayBuffer] = + 0; + chunk->external_backing_store_bytes_ + [ExternalBackingStoreType::kExternalString] = 0; + + chunk->categories_ = nullptr; + + heap->incremental_marking()->non_atomic_marking_state()->SetLiveBytes(chunk, + 0); + if (executable == EXECUTABLE) { + chunk->SetFlag(IS_EXECUTABLE); + if (heap->write_protect_code_memory()) { + chunk->write_unprotect_counter_ = + heap->code_space_memory_modification_scope_depth(); + } else { + size_t page_size = MemoryAllocator::GetCommitPageSize(); + DCHECK(IsAligned(chunk->area_start(), page_size)); + size_t area_size = + RoundUp(chunk->area_end() - chunk->area_start(), page_size); + CHECK(chunk->reservation_.SetPermissions( + chunk->area_start(), area_size, DefaultWritableCodePermissions())); + } + } + + if (chunk->owner()->identity() == CODE_SPACE) { + chunk->code_object_registry_ = new CodeObjectRegistry(); + } else { + chunk->code_object_registry_ = nullptr; + } + + chunk->possibly_empty_buckets_.Initialize(); + + return chunk; +} + +size_t MemoryChunk::CommittedPhysicalMemory() { + if (!base::OS::HasLazyCommits() || owner_identity() == LO_SPACE) + return size(); + return high_water_mark_; +} + +void MemoryChunk::SetOldGenerationPageFlags(bool is_marking) { + if (is_marking) { + SetFlag(MemoryChunk::POINTERS_TO_HERE_ARE_INTERESTING); + SetFlag(MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING); + SetFlag(MemoryChunk::INCREMENTAL_MARKING); + } else { + ClearFlag(MemoryChunk::POINTERS_TO_HERE_ARE_INTERESTING); + SetFlag(MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING); + ClearFlag(MemoryChunk::INCREMENTAL_MARKING); + } +} + +void MemoryChunk::SetYoungGenerationPageFlags(bool is_marking) { + SetFlag(MemoryChunk::POINTERS_TO_HERE_ARE_INTERESTING); + if (is_marking) { + SetFlag(MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING); + SetFlag(MemoryChunk::INCREMENTAL_MARKING); + } else { + ClearFlag(MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING); + ClearFlag(MemoryChunk::INCREMENTAL_MARKING); + } +} +// ----------------------------------------------------------------------------- +// MemoryChunk implementation + +void MemoryChunk::ReleaseAllocatedMemoryNeededForWritableChunk() { + if (mutex_ != nullptr) { + delete mutex_; + mutex_ = nullptr; + } + if (page_protection_change_mutex_ != nullptr) { + delete page_protection_change_mutex_; + page_protection_change_mutex_ = nullptr; + } + if (code_object_registry_ != nullptr) { + delete code_object_registry_; + code_object_registry_ = nullptr; + } + + possibly_empty_buckets_.Release(); + ReleaseSlotSet<OLD_TO_NEW>(); + ReleaseSweepingSlotSet(); + ReleaseSlotSet<OLD_TO_OLD>(); + ReleaseTypedSlotSet<OLD_TO_NEW>(); + ReleaseTypedSlotSet<OLD_TO_OLD>(); + ReleaseInvalidatedSlots<OLD_TO_NEW>(); + ReleaseInvalidatedSlots<OLD_TO_OLD>(); + + if (local_tracker_ != nullptr) ReleaseLocalTracker(); + if (young_generation_bitmap_ != nullptr) ReleaseYoungGenerationBitmap(); + + if (!IsLargePage()) { + Page* page = static_cast<Page*>(this); + page->ReleaseFreeListCategories(); + } +} + +void MemoryChunk::ReleaseAllAllocatedMemory() { + ReleaseAllocatedMemoryNeededForWritableChunk(); + if (marking_bitmap_ != nullptr) ReleaseMarkingBitmap(); +} + +template V8_EXPORT_PRIVATE SlotSet* MemoryChunk::AllocateSlotSet<OLD_TO_NEW>(); +template V8_EXPORT_PRIVATE SlotSet* MemoryChunk::AllocateSlotSet<OLD_TO_OLD>(); + +template <RememberedSetType type> +SlotSet* MemoryChunk::AllocateSlotSet() { + return AllocateSlotSet(&slot_set_[type]); +} + +SlotSet* MemoryChunk::AllocateSweepingSlotSet() { + return AllocateSlotSet(&sweeping_slot_set_); +} + +SlotSet* MemoryChunk::AllocateSlotSet(SlotSet** slot_set) { + SlotSet* new_slot_set = SlotSet::Allocate(buckets()); + SlotSet* old_slot_set = base::AsAtomicPointer::AcquireRelease_CompareAndSwap( + slot_set, nullptr, new_slot_set); + if (old_slot_set != nullptr) { + SlotSet::Delete(new_slot_set, buckets()); + new_slot_set = old_slot_set; + } + DCHECK(new_slot_set); + return new_slot_set; +} + +template void MemoryChunk::ReleaseSlotSet<OLD_TO_NEW>(); +template void MemoryChunk::ReleaseSlotSet<OLD_TO_OLD>(); + +template <RememberedSetType type> +void MemoryChunk::ReleaseSlotSet() { + ReleaseSlotSet(&slot_set_[type]); +} + +void MemoryChunk::ReleaseSweepingSlotSet() { + ReleaseSlotSet(&sweeping_slot_set_); +} + +void MemoryChunk::ReleaseSlotSet(SlotSet** slot_set) { + if (*slot_set) { + SlotSet::Delete(*slot_set, buckets()); + *slot_set = nullptr; + } +} + +template TypedSlotSet* MemoryChunk::AllocateTypedSlotSet<OLD_TO_NEW>(); +template TypedSlotSet* MemoryChunk::AllocateTypedSlotSet<OLD_TO_OLD>(); + +template <RememberedSetType type> +TypedSlotSet* MemoryChunk::AllocateTypedSlotSet() { + TypedSlotSet* typed_slot_set = new TypedSlotSet(address()); + TypedSlotSet* old_value = base::AsAtomicPointer::Release_CompareAndSwap( + &typed_slot_set_[type], nullptr, typed_slot_set); + if (old_value != nullptr) { + delete typed_slot_set; + typed_slot_set = old_value; + } + DCHECK(typed_slot_set); + return typed_slot_set; +} + +template void MemoryChunk::ReleaseTypedSlotSet<OLD_TO_NEW>(); +template void MemoryChunk::ReleaseTypedSlotSet<OLD_TO_OLD>(); + +template <RememberedSetType type> +void MemoryChunk::ReleaseTypedSlotSet() { + TypedSlotSet* typed_slot_set = typed_slot_set_[type]; + if (typed_slot_set) { + typed_slot_set_[type] = nullptr; + delete typed_slot_set; + } +} + +template InvalidatedSlots* MemoryChunk::AllocateInvalidatedSlots<OLD_TO_NEW>(); +template InvalidatedSlots* MemoryChunk::AllocateInvalidatedSlots<OLD_TO_OLD>(); + +template <RememberedSetType type> +InvalidatedSlots* MemoryChunk::AllocateInvalidatedSlots() { + DCHECK_NULL(invalidated_slots_[type]); + invalidated_slots_[type] = new InvalidatedSlots(); + return invalidated_slots_[type]; +} + +template void MemoryChunk::ReleaseInvalidatedSlots<OLD_TO_NEW>(); +template void MemoryChunk::ReleaseInvalidatedSlots<OLD_TO_OLD>(); + +template <RememberedSetType type> +void MemoryChunk::ReleaseInvalidatedSlots() { + if (invalidated_slots_[type]) { + delete invalidated_slots_[type]; + invalidated_slots_[type] = nullptr; + } +} + +template V8_EXPORT_PRIVATE void +MemoryChunk::RegisterObjectWithInvalidatedSlots<OLD_TO_NEW>(HeapObject object); +template V8_EXPORT_PRIVATE void +MemoryChunk::RegisterObjectWithInvalidatedSlots<OLD_TO_OLD>(HeapObject object); + +template <RememberedSetType type> +void MemoryChunk::RegisterObjectWithInvalidatedSlots(HeapObject object) { + bool skip_slot_recording; + + if (type == OLD_TO_NEW) { + skip_slot_recording = InYoungGeneration(); + } else { + skip_slot_recording = ShouldSkipEvacuationSlotRecording(); + } + + if (skip_slot_recording) { + return; + } + + if (invalidated_slots<type>() == nullptr) { + AllocateInvalidatedSlots<type>(); + } + + invalidated_slots<type>()->insert(object); +} + +void MemoryChunk::InvalidateRecordedSlots(HeapObject object) { + if (V8_DISABLE_WRITE_BARRIERS_BOOL) return; + if (heap()->incremental_marking()->IsCompacting()) { + // We cannot check slot_set_[OLD_TO_OLD] here, since the + // concurrent markers might insert slots concurrently. + RegisterObjectWithInvalidatedSlots<OLD_TO_OLD>(object); + } + + if (!FLAG_always_promote_young_mc || slot_set_[OLD_TO_NEW] != nullptr) + RegisterObjectWithInvalidatedSlots<OLD_TO_NEW>(object); +} + +template bool MemoryChunk::RegisteredObjectWithInvalidatedSlots<OLD_TO_NEW>( + HeapObject object); +template bool MemoryChunk::RegisteredObjectWithInvalidatedSlots<OLD_TO_OLD>( + HeapObject object); + +template <RememberedSetType type> +bool MemoryChunk::RegisteredObjectWithInvalidatedSlots(HeapObject object) { + if (invalidated_slots<type>() == nullptr) { + return false; + } + return invalidated_slots<type>()->find(object) != + invalidated_slots<type>()->end(); +} + +void MemoryChunk::ReleaseLocalTracker() { + DCHECK_NOT_NULL(local_tracker_); + delete local_tracker_; + local_tracker_ = nullptr; +} + +void MemoryChunk::AllocateYoungGenerationBitmap() { + DCHECK_NULL(young_generation_bitmap_); + young_generation_bitmap_ = static_cast<Bitmap*>(calloc(1, Bitmap::kSize)); +} + +void MemoryChunk::ReleaseYoungGenerationBitmap() { + DCHECK_NOT_NULL(young_generation_bitmap_); + free(young_generation_bitmap_); + young_generation_bitmap_ = nullptr; +} + } // namespace internal } // namespace v8 |