Allow main thread to contribute to the sweeping phase.
authorhpayer@chromium.org <hpayer@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 10 Jul 2014 12:07:28 +0000 (12:07 +0000)
committerhpayer@chromium.org <hpayer@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 10 Jul 2014 12:07:28 +0000 (12:07 +0000)
BUG=
R=jarin@chromium.org

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22318 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/mark-compact.cc
src/mark-compact.h
src/spaces.cc
src/spaces.h
src/sweeper-thread.cc

index 9192c58..dbb1174 100644 (file)
@@ -559,7 +559,7 @@ class MarkCompactCollector::SweeperTask : public v8::Task {
  private:
   // v8::Task overrides.
   virtual void Run() V8_OVERRIDE {
-    heap_->mark_compact_collector()->SweepInParallel(space_);
+    heap_->mark_compact_collector()->SweepInParallel(space_, 0);
     heap_->mark_compact_collector()->pending_sweeper_jobs_semaphore_.Signal();
   }
 
@@ -3544,7 +3544,7 @@ void MarkCompactCollector::EvacuateNewSpaceAndCandidates() {
 
         switch (space->identity()) {
           case OLD_DATA_SPACE:
-            SweepConservatively<SWEEP_SEQUENTIALLY>(space, NULL, p);
+            SweepConservatively<SWEEP_ON_MAIN_THREAD>(space, NULL, p);
             break;
           case OLD_POINTER_SPACE:
             SweepPrecisely<SWEEP_AND_VISIT_LIVE_OBJECTS,
@@ -3939,7 +3939,7 @@ static intptr_t Free(PagedSpace* space,
                      FreeList* free_list,
                      Address start,
                      int size) {
-  if (mode == MarkCompactCollector::SWEEP_SEQUENTIALLY) {
+  if (mode == MarkCompactCollector::SWEEP_ON_MAIN_THREAD) {
     return space->Free(start, size);
   } else {
     return size - free_list->Free(start, size);
@@ -3948,9 +3948,9 @@ static intptr_t Free(PagedSpace* space,
 
 
 // Force instantiation of templatized SweepConservatively method for
-// SWEEP_SEQUENTIALLY mode.
+// SWEEP_ON_MAIN_THREAD mode.
 template intptr_t MarkCompactCollector::
-    SweepConservatively<MarkCompactCollector::SWEEP_SEQUENTIALLY>(
+    SweepConservatively<MarkCompactCollector::SWEEP_ON_MAIN_THREAD>(
         PagedSpace*, FreeList*, Page*);
 
 
@@ -3975,16 +3975,19 @@ intptr_t MarkCompactCollector::SweepConservatively(PagedSpace* space,
   ASSERT(!p->IsEvacuationCandidate() && !p->WasSwept());
   ASSERT((mode == MarkCompactCollector::SWEEP_IN_PARALLEL &&
          free_list != NULL) ||
-         (mode == MarkCompactCollector::SWEEP_SEQUENTIALLY &&
+         (mode == MarkCompactCollector::SWEEP_ON_MAIN_THREAD &&
          free_list == NULL));
 
   // When parallel sweeping is active, the page will be marked after
   // sweeping by the main thread.
-  if (mode != MarkCompactCollector::SWEEP_IN_PARALLEL) {
+  if (mode == MarkCompactCollector::SWEEP_IN_PARALLEL) {
+    p->set_parallel_sweeping(MemoryChunk::PARALLEL_SWEEPING_FINALIZE);
+  } else {
     p->MarkSweptConservatively();
   }
 
   intptr_t freed_bytes = 0;
+  intptr_t max_freed_bytes = 0;
   size_t size = 0;
 
   // Skip over all the dead objects at the start of the page and mark them free.
@@ -3999,8 +4002,9 @@ intptr_t MarkCompactCollector::SweepConservatively(PagedSpace* space,
 
   if (it.Done()) {
     size = p->area_end() - p->area_start();
-    freed_bytes += Free<mode>(space, free_list, p->area_start(),
-                              static_cast<int>(size));
+    freed_bytes = Free<mode>(space, free_list, p->area_start(),
+                             static_cast<int>(size));
+    max_freed_bytes = Max(freed_bytes, max_freed_bytes);
     ASSERT_EQ(0, p->LiveBytes());
     return freed_bytes;
   }
@@ -4010,8 +4014,9 @@ intptr_t MarkCompactCollector::SweepConservatively(PagedSpace* space,
   Address free_end = StartOfLiveObject(cell_base, *cell);
   // Free the first free space.
   size = free_end - p->area_start();
-  freed_bytes += Free<mode>(space, free_list, p->area_start(),
-                            static_cast<int>(size));
+  freed_bytes = Free<mode>(space, free_list, p->area_start(),
+                           static_cast<int>(size));
+  max_freed_bytes = Max(freed_bytes, max_freed_bytes);
 
   // The start of the current free area is represented in undigested form by
   // the address of the last 32-word section that contained a live object and
@@ -4036,8 +4041,9 @@ intptr_t MarkCompactCollector::SweepConservatively(PagedSpace* space,
           // so now we need to find the start of the first live object at the
           // end of the free space.
           free_end = StartOfLiveObject(cell_base, *cell);
-          freed_bytes += Free<mode>(space, free_list, free_start,
-                                    static_cast<int>(free_end - free_start));
+          freed_bytes = Free<mode>(space, free_list, free_start,
+                                   static_cast<int>(free_end - free_start));
+          max_freed_bytes = Max(freed_bytes, max_freed_bytes);
         }
       }
       // Update our undigested record of where the current free area started.
@@ -4051,31 +4057,40 @@ intptr_t MarkCompactCollector::SweepConservatively(PagedSpace* space,
   // Handle the free space at the end of the page.
   if (cell_base - free_start > 32 * kPointerSize) {
     free_start = DigestFreeStart(free_start, free_start_cell);
-    freed_bytes += Free<mode>(space, free_list, free_start,
-                              static_cast<int>(p->area_end() - free_start));
+    freed_bytes = Free<mode>(space, free_list, free_start,
+                             static_cast<int>(p->area_end() - free_start));
+    max_freed_bytes = Max(freed_bytes, max_freed_bytes);
   }
 
   p->ResetLiveBytes();
-  return freed_bytes;
+  return max_freed_bytes;
 }
 
 
-void MarkCompactCollector::SweepInParallel(PagedSpace* space) {
+int MarkCompactCollector::SweepInParallel(PagedSpace* space,
+                                          int required_freed_bytes) {
   PageIterator it(space);
   FreeList* free_list = space == heap()->old_pointer_space()
                             ? free_list_old_pointer_space_.get()
                             : free_list_old_data_space_.get();
   FreeList private_free_list(space);
+  int max_freed = 0;
+  int max_freed_overall = 0;
   while (it.has_next()) {
     Page* p = it.next();
 
     if (p->TryParallelSweeping()) {
-      SweepConservatively<SWEEP_IN_PARALLEL>(space, &private_free_list, p);
+      max_freed = SweepConservatively<SWEEP_IN_PARALLEL>(
+          space, &private_free_list, p);
       free_list->Concatenate(&private_free_list);
-      p->set_parallel_sweeping(MemoryChunk::PARALLEL_SWEEPING_FINALIZE);
+      if (required_freed_bytes > 0 && max_freed >= required_freed_bytes) {
+        return max_freed;
+      }
+      max_freed_overall = Max(max_freed, max_freed_overall);
     }
     if (p == space->end_of_unswept_pages()) break;
   }
+  return max_freed_overall;
 }
 
 
@@ -4131,7 +4146,7 @@ void MarkCompactCollector::SweepSpace(PagedSpace* space, SweeperType sweeper) {
           PrintF("Sweeping 0x%" V8PRIxPTR " conservatively.\n",
                  reinterpret_cast<intptr_t>(p));
         }
-        SweepConservatively<SWEEP_SEQUENTIALLY>(space, NULL, p);
+        SweepConservatively<SWEEP_ON_MAIN_THREAD>(space, NULL, p);
         pages_swept++;
         break;
       }
@@ -4142,7 +4157,7 @@ void MarkCompactCollector::SweepSpace(PagedSpace* space, SweeperType sweeper) {
             PrintF("Sweeping 0x%" V8PRIxPTR " conservatively.\n",
                    reinterpret_cast<intptr_t>(p));
           }
-          SweepConservatively<SWEEP_SEQUENTIALLY>(space, NULL, p);
+          SweepConservatively<SWEEP_ON_MAIN_THREAD>(space, NULL, p);
           pages_swept++;
           parallel_sweeping_active = true;
         } else {
index 6b7c09b..bcbc056 100644 (file)
@@ -577,7 +577,7 @@ class MarkCompactCollector {
   };
 
   enum SweepingParallelism {
-    SWEEP_SEQUENTIALLY,
+    SWEEP_ON_MAIN_THREAD,
     SWEEP_IN_PARALLEL
   };
 
@@ -590,7 +590,7 @@ class MarkCompactCollector {
 #endif
 
   // Sweep a single page from the given space conservatively.
-  // Return a number of reclaimed bytes.
+  // Returns the size of the biggest continuous freed memory chunk in bytes.
   template<SweepingParallelism type>
   static intptr_t SweepConservatively(PagedSpace* space,
                                       FreeList* free_list,
@@ -659,8 +659,11 @@ class MarkCompactCollector {
 
   MarkingParity marking_parity() { return marking_parity_; }
 
-  // Concurrent and parallel sweeping support.
-  void SweepInParallel(PagedSpace* space);
+  // Concurrent and parallel sweeping support. If required_freed_bytes was set
+  // to a value larger than 0, then sweeping returns after a block of at least
+  // required_freed_bytes was freed. If required_freed_bytes was set to zero
+  // then the whole given space is swept.
+  int SweepInParallel(PagedSpace* space, int required_freed_bytes);
 
   void WaitUntilSweepingCompleted();
 
index 12613c7..7fb99f8 100644 (file)
@@ -2581,12 +2581,23 @@ void PagedSpace::EvictEvacuationCandidatesFromFreeLists() {
 }
 
 
-HeapObject* PagedSpace::WaitForSweeperThreadsAndRetryAllocation(
+HeapObject* PagedSpace::EnsureSweepingProgress(
     int size_in_bytes) {
   MarkCompactCollector* collector = heap()->mark_compact_collector();
 
-  // If sweeper threads are still running, wait for them.
   if (collector->IsConcurrentSweepingInProgress(this)) {
+    // If sweeping is still in progress try to sweep pages on the main thread.
+    int free_chunk =
+        collector->SweepInParallel(this, size_in_bytes);
+    if (free_chunk >= size_in_bytes) {
+      HeapObject* object = free_list_.Allocate(size_in_bytes);
+      // We should be able to allocate an object here since we just freed that
+      // much memory.
+      ASSERT(object != NULL);
+      if (object != NULL) return object;
+    }
+
+    // Wait for the sweeper threads here and complete the sweeping phase.
     collector->WaitUntilSweepingCompleted();
 
     // After waiting for the sweeper threads, there may be new free-list
@@ -2617,7 +2628,7 @@ HeapObject* PagedSpace::SlowAllocateRaw(int size_in_bytes) {
       && heap()->OldGenerationAllocationLimitReached()) {
     // If sweeper threads are active, wait for them at that point and steal
     // elements form their free-lists.
-    HeapObject* object = WaitForSweeperThreadsAndRetryAllocation(size_in_bytes);
+    HeapObject* object = EnsureSweepingProgress(size_in_bytes);
     if (object != NULL) return object;
   }
 
@@ -2630,7 +2641,7 @@ HeapObject* PagedSpace::SlowAllocateRaw(int size_in_bytes) {
   // If sweeper threads are active, wait for them at that point and steal
   // elements form their free-lists. Allocation may still fail their which
   // would indicate that there is not enough memory for the given allocation.
-  return WaitForSweeperThreadsAndRetryAllocation(size_in_bytes);
+  return EnsureSweepingProgress(size_in_bytes);
 }
 
 
index 71b7054..8553598 100644 (file)
@@ -2014,8 +2014,10 @@ class PagedSpace : public Space {
   // address denoted by top in allocation_info_.
   inline HeapObject* AllocateLinearly(int size_in_bytes);
 
-  MUST_USE_RESULT HeapObject*
-      WaitForSweeperThreadsAndRetryAllocation(int size_in_bytes);
+  // If sweeping is still in progress try to sweep unswept pages. If that is
+  // not successful, wait for the sweeper threads and re-try free-list
+  // allocation.
+  MUST_USE_RESULT HeapObject* EnsureSweepingProgress(int size_in_bytes);
 
   // Slow path of AllocateRaw.  This function is space-dependent.
   MUST_USE_RESULT HeapObject* SlowAllocateRaw(int size_in_bytes);
index 9ce5ec4..fee3e92 100644 (file)
@@ -41,8 +41,8 @@ void SweeperThread::Run() {
       return;
     }
 
-    collector_->SweepInParallel(heap_->old_data_space());
-    collector_->SweepInParallel(heap_->old_pointer_space());
+    collector_->SweepInParallel(heap_->old_data_space(), 0);
+    collector_->SweepInParallel(heap_->old_pointer_space(), 0);
     end_sweeping_semaphore_.Signal();
   }
 }