From ba968622acff39af93e03dec22ddc46cf74e644d Mon Sep 17 00:00:00 2001 From: hpayer Date: Wed, 26 Aug 2015 05:13:16 -0700 Subject: [PATCH] Synchronize on concurrent store buffer entries. BUG=chromium:524425 LOG=n Review URL: https://codereview.chromium.org/1313313002 Cr-Commit-Position: refs/heads/master@{#30383} --- src/heap/mark-compact.cc | 16 ++++++++++++++-- src/heap/mark-compact.h | 5 +++++ src/heap/store-buffer-inl.h | 6 ++++++ src/heap/store-buffer.h | 9 ++++++++- 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/heap/mark-compact.cc b/src/heap/mark-compact.cc index dc93a5a..738e00b 100644 --- a/src/heap/mark-compact.cc +++ b/src/heap/mark-compact.cc @@ -47,6 +47,7 @@ MarkCompactCollector::MarkCompactCollector(Heap* heap) compacting_(false), was_marked_incrementally_(false), sweeping_in_progress_(false), + parallel_compaction_in_progress_(false), pending_sweeper_jobs_semaphore_(0), pending_compaction_jobs_semaphore_(0), evacuation_(false), @@ -2690,7 +2691,11 @@ void MarkCompactCollector::AbortWeakCells() { void MarkCompactCollector::RecordMigratedSlot(Object* value, Address slot) { if (heap_->InNewSpace(value)) { - heap_->store_buffer()->Mark(slot); + if (parallel_compaction_in_progress_) { + heap_->store_buffer()->MarkSynchronized(slot); + } else { + heap_->store_buffer()->Mark(slot); + } } else if (value->IsHeapObject() && IsOnEvacuationCandidate(value)) { SlotsBuffer::AddTo(&slots_buffer_allocator_, &migration_slots_buffer_, reinterpret_cast(slot), @@ -3313,11 +3318,18 @@ void MarkCompactCollector::EvacuateLiveObjectsFromPage(Page* p) { void MarkCompactCollector::EvacuatePagesInParallel() { + parallel_compaction_in_progress_ = true; V8::GetCurrentPlatform()->CallOnBackgroundThread( new CompactionTask(heap()), v8::Platform::kShortRunningTask); } +void MarkCompactCollector::WaitUntilCompactionCompleted() { + pending_compaction_jobs_semaphore_.Wait(); + parallel_compaction_in_progress_ = false; +} + + void MarkCompactCollector::EvacuatePages() { int npages = evacuation_candidates_.length(); int abandoned_pages = 0; @@ -3626,7 +3638,7 @@ void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { EvacuationScope evacuation_scope(this); if (FLAG_parallel_compaction) { EvacuatePagesInParallel(); - pending_compaction_jobs_semaphore_.Wait(); + WaitUntilCompactionCompleted(); } else { EvacuatePages(); } diff --git a/src/heap/mark-compact.h b/src/heap/mark-compact.h index d6ff1c9..ffb54bb 100644 --- a/src/heap/mark-compact.h +++ b/src/heap/mark-compact.h @@ -707,6 +707,9 @@ class MarkCompactCollector { // True if concurrent or parallel sweeping is currently in progress. bool sweeping_in_progress_; + // True if parallel compaction is currently in progress. + bool parallel_compaction_in_progress_; + // Synchronize sweeper threads. base::Semaphore pending_sweeper_jobs_semaphore_; @@ -873,6 +876,8 @@ class MarkCompactCollector { void EvacuatePagesInParallel(); + void WaitUntilCompactionCompleted(); + void EvacuateNewSpaceAndCandidates(); void ReleaseEvacuationCandidates(); diff --git a/src/heap/store-buffer-inl.h b/src/heap/store-buffer-inl.h index 230384a..1f3dda2 100644 --- a/src/heap/store-buffer-inl.h +++ b/src/heap/store-buffer-inl.h @@ -26,6 +26,12 @@ void StoreBuffer::Mark(Address addr) { } +inline void StoreBuffer::MarkSynchronized(Address addr) { + base::LockGuard lock_guard(&mutex_); + Mark(addr); +} + + void StoreBuffer::EnterDirectlyIntoStoreBuffer(Address addr) { if (store_buffer_rebuilding_enabled_) { SLOW_DCHECK(!heap_->code_space()->Contains(addr) && diff --git a/src/heap/store-buffer.h b/src/heap/store-buffer.h index cb96fa9..37a78eb 100644 --- a/src/heap/store-buffer.h +++ b/src/heap/store-buffer.h @@ -33,9 +33,13 @@ class StoreBuffer { void SetUp(); void TearDown(); - // This is used by the mutator to enter addresses into the store buffer. + // This is used to add addresses to the store buffer non-concurrently. inline void Mark(Address addr); + // This is used to add addresses to the store buffer when multiple threads + // may operate on the store buffer. + inline void MarkSynchronized(Address addr); + // This is used by the heap traversal to enter the addresses into the store // buffer that should still be in the store buffer after GC. It enters // addresses directly into the old buffer because the GC starts by wiping the @@ -129,6 +133,9 @@ class StoreBuffer { uintptr_t* hash_set_2_; bool hash_sets_are_empty_; + // Used for synchronization of concurrent store buffer access. + base::Mutex mutex_; + void ClearFilteringHashSets(); bool SpaceAvailable(intptr_t space_needed); -- 2.7.4