From ce916ff99a34a8e303d0afac9e0421025dd906f0 Mon Sep 17 00:00:00 2001 From: "hpayer@chromium.org" Date: Thu, 10 Jul 2014 12:07:28 +0000 Subject: [PATCH] Allow main thread to contribute to the sweeping phase. 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 | 57 ++++++++++++++++++++++++++++++++------------------- src/mark-compact.h | 11 ++++++---- src/spaces.cc | 19 +++++++++++++---- src/spaces.h | 6 ++++-- src/sweeper-thread.cc | 4 ++-- 5 files changed, 64 insertions(+), 33 deletions(-) diff --git a/src/mark-compact.cc b/src/mark-compact.cc index 9192c58..dbb1174 100644 --- a/src/mark-compact.cc +++ b/src/mark-compact.cc @@ -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(space, NULL, p); + SweepConservatively(space, NULL, p); break; case OLD_POINTER_SPACE: SweepPreciselyFree(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( + SweepConservatively( 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(space, free_list, p->area_start(), - static_cast(size)); + freed_bytes = Free(space, free_list, p->area_start(), + static_cast(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(space, free_list, p->area_start(), - static_cast(size)); + freed_bytes = Free(space, free_list, p->area_start(), + static_cast(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(space, free_list, free_start, - static_cast(free_end - free_start)); + freed_bytes = Free(space, free_list, free_start, + static_cast(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(space, free_list, free_start, - static_cast(p->area_end() - free_start)); + freed_bytes = Free(space, free_list, free_start, + static_cast(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(space, &private_free_list, p); + max_freed = SweepConservatively( + 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(p)); } - SweepConservatively(space, NULL, p); + SweepConservatively(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(p)); } - SweepConservatively(space, NULL, p); + SweepConservatively(space, NULL, p); pages_swept++; parallel_sweeping_active = true; } else { diff --git a/src/mark-compact.h b/src/mark-compact.h index 6b7c09b..bcbc056 100644 --- a/src/mark-compact.h +++ b/src/mark-compact.h @@ -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 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(); diff --git a/src/spaces.cc b/src/spaces.cc index 12613c7..7fb99f8 100644 --- a/src/spaces.cc +++ b/src/spaces.cc @@ -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); } diff --git a/src/spaces.h b/src/spaces.h index 71b7054..8553598 100644 --- a/src/spaces.h +++ b/src/spaces.h @@ -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); diff --git a/src/sweeper-thread.cc b/src/sweeper-thread.cc index 9ce5ec4..fee3e92 100644 --- a/src/sweeper-thread.cc +++ b/src/sweeper-thread.cc @@ -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(); } } -- 2.7.4