Synchronize on concurrent store buffer entries.
authorhpayer <hpayer@chromium.org>
Wed, 26 Aug 2015 12:13:16 +0000 (05:13 -0700)
committerCommit bot <commit-bot@chromium.org>
Wed, 26 Aug 2015 12:13:27 +0000 (12:13 +0000)
BUG=chromium:524425
LOG=n

Review URL: https://codereview.chromium.org/1313313002

Cr-Commit-Position: refs/heads/master@{#30383}

src/heap/mark-compact.cc
src/heap/mark-compact.h
src/heap/store-buffer-inl.h
src/heap/store-buffer.h

index dc93a5a..738e00b 100644 (file)
@@ -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<Object**>(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();
     }
index d6ff1c9..ffb54bb 100644 (file)
@@ -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();
index 230384a..1f3dda2 100644 (file)
@@ -26,6 +26,12 @@ void StoreBuffer::Mark(Address addr) {
 }
 
 
+inline void StoreBuffer::MarkSynchronized(Address addr) {
+  base::LockGuard<base::Mutex> lock_guard(&mutex_);
+  Mark(addr);
+}
+
+
 void StoreBuffer::EnterDirectlyIntoStoreBuffer(Address addr) {
   if (store_buffer_rebuilding_enabled_) {
     SLOW_DCHECK(!heap_->code_space()->Contains(addr) &&
index cb96fa9..37a78eb 100644 (file)
@@ -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);