Commit 8516dccf authored by hpayer's avatar hpayer Committed by Commit bot

Reland concurrent sweeping of code space.

BUG=

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

Cr-Commit-Position: refs/heads/master@{#29967}
parent f7d80884
...@@ -1446,6 +1446,9 @@ Code* InnerPointerToCodeCache::GcSafeFindCodeForInnerPointer( ...@@ -1446,6 +1446,9 @@ Code* InnerPointerToCodeCache::GcSafeFindCodeForInnerPointer(
// after the inner pointer. // after the inner pointer.
Page* page = Page::FromAddress(inner_pointer); Page* page = Page::FromAddress(inner_pointer);
DCHECK_EQ(page->owner(), heap->code_space());
heap->mark_compact_collector()->SweepOrWaitUntilSweepingCompleted(page);
Address addr = page->skip_list()->StartFor(inner_pointer); Address addr = page->skip_list()->StartFor(inner_pointer);
Address top = heap->code_space()->top(); Address top = heap->code_space()->top();
......
...@@ -509,6 +509,7 @@ const char* Heap::GetSpaceName(int idx) { ...@@ -509,6 +509,7 @@ const char* Heap::GetSpaceName(int idx) {
void Heap::ClearAllICsByKind(Code::Kind kind) { void Heap::ClearAllICsByKind(Code::Kind kind) {
// TODO(mvstanton): Do not iterate the heap.
HeapObjectIterator it(code_space()); HeapObjectIterator it(code_space());
for (Object* object = it.Next(); object != NULL; object = it.Next()) { for (Object* object = it.Next(); object != NULL; object = it.Next()) {
...@@ -5180,6 +5181,11 @@ void Heap::Verify() { ...@@ -5180,6 +5181,11 @@ void Heap::Verify() {
code_space_->Verify(&no_dirty_regions_visitor); code_space_->Verify(&no_dirty_regions_visitor);
lo_space_->Verify(); lo_space_->Verify();
mark_compact_collector_.VerifyWeakEmbeddedObjectsInCode();
if (FLAG_omit_map_checks_for_leaf_maps) {
mark_compact_collector_.VerifyOmittedMapChecks();
}
} }
#endif #endif
......
...@@ -226,6 +226,7 @@ static void VerifyEvacuation(Heap* heap) { ...@@ -226,6 +226,7 @@ static void VerifyEvacuation(Heap* heap) {
void MarkCompactCollector::SetUp() { void MarkCompactCollector::SetUp() {
free_list_old_space_.Reset(new FreeList(heap_->old_space())); free_list_old_space_.Reset(new FreeList(heap_->old_space()));
free_list_code_space_.Reset(new FreeList(heap_->code_space()));
EnsureMarkingDequeIsReserved(); EnsureMarkingDequeIsReserved();
EnsureMarkingDequeIsCommitted(kMinMarkingDequeSize); EnsureMarkingDequeIsCommitted(kMinMarkingDequeSize);
} }
...@@ -368,13 +369,6 @@ void MarkCompactCollector::CollectGarbage() { ...@@ -368,13 +369,6 @@ void MarkCompactCollector::CollectGarbage() {
SweepSpaces(); SweepSpaces();
#ifdef VERIFY_HEAP
VerifyWeakEmbeddedObjectsInCode();
if (FLAG_omit_map_checks_for_leaf_maps) {
VerifyOmittedMapChecks();
}
#endif
Finish(); Finish();
if (marking_parity_ == EVEN_MARKING_PARITY) { if (marking_parity_ == EVEN_MARKING_PARITY) {
...@@ -501,9 +495,27 @@ class MarkCompactCollector::SweeperTask : public v8::Task { ...@@ -501,9 +495,27 @@ class MarkCompactCollector::SweeperTask : public v8::Task {
void MarkCompactCollector::StartSweeperThreads() { void MarkCompactCollector::StartSweeperThreads() {
DCHECK(free_list_old_space_.get()->IsEmpty()); DCHECK(free_list_old_space_.get()->IsEmpty());
DCHECK(free_list_code_space_.get()->IsEmpty());
V8::GetCurrentPlatform()->CallOnBackgroundThread( V8::GetCurrentPlatform()->CallOnBackgroundThread(
new SweeperTask(heap(), heap()->old_space()), new SweeperTask(heap(), heap()->old_space()),
v8::Platform::kShortRunningTask); v8::Platform::kShortRunningTask);
V8::GetCurrentPlatform()->CallOnBackgroundThread(
new SweeperTask(heap(), heap()->code_space()),
v8::Platform::kShortRunningTask);
}
void MarkCompactCollector::SweepOrWaitUntilSweepingCompleted(Page* page) {
PagedSpace* owner = reinterpret_cast<PagedSpace*>(page->owner());
if (!page->SweepingCompleted()) {
SweepInParallel(page, owner);
if (!page->SweepingCompleted()) {
// We were not able to sweep that page, i.e., a concurrent
// sweeper thread currently owns this page. Wait for the sweeper
// thread to be done with this page.
page->WaitUntilSweepingCompleted();
}
}
} }
...@@ -514,15 +526,19 @@ void MarkCompactCollector::EnsureSweepingCompleted() { ...@@ -514,15 +526,19 @@ void MarkCompactCollector::EnsureSweepingCompleted() {
// here. // here.
if (!heap()->concurrent_sweeping_enabled() || !IsSweepingCompleted()) { if (!heap()->concurrent_sweeping_enabled() || !IsSweepingCompleted()) {
SweepInParallel(heap()->paged_space(OLD_SPACE), 0); SweepInParallel(heap()->paged_space(OLD_SPACE), 0);
SweepInParallel(heap()->paged_space(CODE_SPACE), 0);
} }
// Wait twice for both jobs. // Wait twice for both jobs.
if (heap()->concurrent_sweeping_enabled()) { if (heap()->concurrent_sweeping_enabled()) {
pending_sweeper_jobs_semaphore_.Wait(); pending_sweeper_jobs_semaphore_.Wait();
pending_sweeper_jobs_semaphore_.Wait();
} }
ParallelSweepSpacesComplete(); ParallelSweepSpacesComplete();
sweeping_in_progress_ = false; sweeping_in_progress_ = false;
RefillFreeList(heap()->paged_space(OLD_SPACE)); RefillFreeList(heap()->paged_space(OLD_SPACE));
RefillFreeList(heap()->paged_space(CODE_SPACE));
heap()->paged_space(OLD_SPACE)->ResetUnsweptFreeBytes(); heap()->paged_space(OLD_SPACE)->ResetUnsweptFreeBytes();
heap()->paged_space(CODE_SPACE)->ResetUnsweptFreeBytes();
#ifdef VERIFY_HEAP #ifdef VERIFY_HEAP
if (FLAG_verify_heap && !evacuation()) { if (FLAG_verify_heap && !evacuation()) {
...@@ -547,6 +563,8 @@ void MarkCompactCollector::RefillFreeList(PagedSpace* space) { ...@@ -547,6 +563,8 @@ void MarkCompactCollector::RefillFreeList(PagedSpace* space) {
if (space == heap()->old_space()) { if (space == heap()->old_space()) {
free_list = free_list_old_space_.get(); free_list = free_list_old_space_.get();
} else if (space == heap()->code_space()) {
free_list = free_list_code_space_.get();
} else { } else {
// Any PagedSpace might invoke RefillFreeLists, so we need to make sure // Any PagedSpace might invoke RefillFreeLists, so we need to make sure
// to only refill them for the old space. // to only refill them for the old space.
...@@ -3479,14 +3497,17 @@ static int Sweep(PagedSpace* space, FreeList* free_list, Page* p, ...@@ -3479,14 +3497,17 @@ static int Sweep(PagedSpace* space, FreeList* free_list, Page* p,
DCHECK(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0); DCHECK(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0);
int offsets[16]; int offsets[16];
// If we use the skip list for code space pages, we have to lock the skip
// list because it could be accessed concurrently by the runtime or the
// deoptimizer.
SkipList* skip_list = p->skip_list(); SkipList* skip_list = p->skip_list();
int curr_region = -1;
if ((skip_list_mode == REBUILD_SKIP_LIST) && skip_list) { if ((skip_list_mode == REBUILD_SKIP_LIST) && skip_list) {
skip_list->Clear(); skip_list->Clear();
} }
intptr_t freed_bytes = 0; intptr_t freed_bytes = 0;
intptr_t max_freed_bytes = 0; intptr_t max_freed_bytes = 0;
int curr_region = -1;
for (MarkBitCellIterator it(p); !it.Done(); it.Advance()) { for (MarkBitCellIterator it(p); !it.Done(); it.Advance()) {
Address cell_base = it.CurrentCellBase(); Address cell_base = it.CurrentCellBase();
...@@ -4247,10 +4268,19 @@ int MarkCompactCollector::SweepInParallel(Page* page, PagedSpace* space) { ...@@ -4247,10 +4268,19 @@ int MarkCompactCollector::SweepInParallel(Page* page, PagedSpace* space) {
return 0; return 0;
} }
page->set_parallel_sweeping(MemoryChunk::SWEEPING_IN_PROGRESS); page->set_parallel_sweeping(MemoryChunk::SWEEPING_IN_PROGRESS);
FreeList* free_list = free_list_old_space_.get(); FreeList* free_list;
FreeList private_free_list(space); FreeList private_free_list(space);
max_freed = Sweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, IGNORE_SKIP_LIST, if (space->identity() == CODE_SPACE) {
IGNORE_FREE_SPACE>(space, &private_free_list, page, NULL); free_list = free_list_code_space_.get();
max_freed =
Sweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, REBUILD_SKIP_LIST,
IGNORE_FREE_SPACE>(space, &private_free_list, page, NULL);
} else {
free_list = free_list_old_space_.get();
max_freed =
Sweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, IGNORE_SKIP_LIST,
IGNORE_FREE_SPACE>(space, &private_free_list, page, NULL);
}
free_list->Concatenate(&private_free_list); free_list->Concatenate(&private_free_list);
page->mutex()->Unlock(); page->mutex()->Unlock();
} }
...@@ -4308,8 +4338,19 @@ void MarkCompactCollector::SweepSpace(PagedSpace* space, SweeperType sweeper) { ...@@ -4308,8 +4338,19 @@ void MarkCompactCollector::SweepSpace(PagedSpace* space, SweeperType sweeper) {
PrintF("Sweeping 0x%" V8PRIxPTR ".\n", PrintF("Sweeping 0x%" V8PRIxPTR ".\n",
reinterpret_cast<intptr_t>(p)); reinterpret_cast<intptr_t>(p));
} }
Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, IGNORE_SKIP_LIST, if (space->identity() == CODE_SPACE) {
IGNORE_FREE_SPACE>(space, NULL, p, NULL); if (FLAG_zap_code_space) {
Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, REBUILD_SKIP_LIST,
ZAP_FREE_SPACE>(space, NULL, p, NULL);
} else {
Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, REBUILD_SKIP_LIST,
IGNORE_FREE_SPACE>(space, NULL, p, NULL);
}
} else {
DCHECK(space->identity() == OLD_SPACE);
Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, IGNORE_SKIP_LIST,
IGNORE_FREE_SPACE>(space, NULL, p, NULL);
}
pages_swept++; pages_swept++;
parallel_sweeping_active = true; parallel_sweeping_active = true;
} else { } else {
...@@ -4326,13 +4367,17 @@ void MarkCompactCollector::SweepSpace(PagedSpace* space, SweeperType sweeper) { ...@@ -4326,13 +4367,17 @@ void MarkCompactCollector::SweepSpace(PagedSpace* space, SweeperType sweeper) {
if (FLAG_gc_verbose) { if (FLAG_gc_verbose) {
PrintF("Sweeping 0x%" V8PRIxPTR ".\n", reinterpret_cast<intptr_t>(p)); PrintF("Sweeping 0x%" V8PRIxPTR ".\n", reinterpret_cast<intptr_t>(p));
} }
if (space->identity() == CODE_SPACE && FLAG_zap_code_space) { if (space->identity() == CODE_SPACE) {
Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, REBUILD_SKIP_LIST, if (FLAG_zap_code_space) {
ZAP_FREE_SPACE>(space, NULL, p, NULL); Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, REBUILD_SKIP_LIST,
} else if (space->identity() == CODE_SPACE) { ZAP_FREE_SPACE>(space, NULL, p, NULL);
Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, REBUILD_SKIP_LIST, } else {
IGNORE_FREE_SPACE>(space, NULL, p, NULL); Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, REBUILD_SKIP_LIST,
IGNORE_FREE_SPACE>(space, NULL, p, NULL);
}
} else { } else {
DCHECK(space->identity() == OLD_SPACE ||
space->identity() == MAP_SPACE);
Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, IGNORE_SKIP_LIST, Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, IGNORE_SKIP_LIST,
IGNORE_FREE_SPACE>(space, NULL, p, NULL); IGNORE_FREE_SPACE>(space, NULL, p, NULL);
} }
...@@ -4372,21 +4417,24 @@ void MarkCompactCollector::SweepSpaces() { ...@@ -4372,21 +4417,24 @@ void MarkCompactCollector::SweepSpaces() {
// the other spaces rely on possibly non-live maps to get the sizes for // the other spaces rely on possibly non-live maps to get the sizes for
// non-live objects. // non-live objects.
{ {
GCTracer::Scope sweep_scope(heap()->tracer(), {
GCTracer::Scope::MC_SWEEP_OLDSPACE); GCTracer::Scope sweep_scope(heap()->tracer(),
{ SweepSpace(heap()->old_space(), CONCURRENT_SWEEPING); } GCTracer::Scope::MC_SWEEP_OLDSPACE);
SweepSpace(heap()->old_space(), CONCURRENT_SWEEPING);
}
{
GCTracer::Scope sweep_scope(heap()->tracer(),
GCTracer::Scope::MC_SWEEP_CODE);
SweepSpace(heap()->code_space(), CONCURRENT_SWEEPING);
}
sweeping_in_progress_ = true; sweeping_in_progress_ = true;
if (heap()->concurrent_sweeping_enabled()) { if (heap()->concurrent_sweeping_enabled()) {
StartSweeperThreads(); StartSweeperThreads();
} }
} }
RemoveDeadInvalidatedCode();
{ RemoveDeadInvalidatedCode();
GCTracer::Scope sweep_scope(heap()->tracer(),
GCTracer::Scope::MC_SWEEP_CODE);
SweepSpace(heap()->code_space(), SEQUENTIAL_SWEEPING);
}
EvacuateNewSpaceAndCandidates(); EvacuateNewSpaceAndCandidates();
...@@ -4439,6 +4487,7 @@ void MarkCompactCollector::ParallelSweepSpaceComplete(PagedSpace* space) { ...@@ -4439,6 +4487,7 @@ void MarkCompactCollector::ParallelSweepSpaceComplete(PagedSpace* space) {
void MarkCompactCollector::ParallelSweepSpacesComplete() { void MarkCompactCollector::ParallelSweepSpacesComplete() {
ParallelSweepSpaceComplete(heap()->old_space()); ParallelSweepSpaceComplete(heap()->old_space());
ParallelSweepSpaceComplete(heap()->code_space());
} }
......
...@@ -699,6 +699,8 @@ class MarkCompactCollector { ...@@ -699,6 +699,8 @@ class MarkCompactCollector {
void EnsureSweepingCompleted(); void EnsureSweepingCompleted();
void SweepOrWaitUntilSweepingCompleted(Page* page);
// If sweeper threads are not active this method will return true. If // If sweeper threads are not active this method will return true. If
// this is a latency issue we should be smarter here. Otherwise, it will // this is a latency issue we should be smarter here. Otherwise, it will
// return true if the sweeper threads are done processing the pages. // return true if the sweeper threads are done processing the pages.
...@@ -979,6 +981,7 @@ class MarkCompactCollector { ...@@ -979,6 +981,7 @@ class MarkCompactCollector {
List<Code*> invalidated_code_; List<Code*> invalidated_code_;
base::SmartPointer<FreeList> free_list_old_space_; base::SmartPointer<FreeList> free_list_old_space_;
base::SmartPointer<FreeList> free_list_code_space_;
friend class Heap; friend class Heap;
}; };
......
...@@ -75,6 +75,8 @@ bool HeapObjectIterator::AdvanceToNextPage() { ...@@ -75,6 +75,8 @@ bool HeapObjectIterator::AdvanceToNextPage() {
} }
cur_page = cur_page->next_page(); cur_page = cur_page->next_page();
if (cur_page == space_->anchor()) return false; if (cur_page == space_->anchor()) return false;
cur_page->heap()->mark_compact_collector()->SweepOrWaitUntilSweepingCompleted(
cur_page);
cur_addr_ = cur_page->area_start(); cur_addr_ = cur_page->area_start();
cur_end_ = cur_page->area_end(); cur_end_ = cur_page->area_end();
DCHECK(cur_page->WasSwept() || cur_page->SweepingCompleted()); DCHECK(cur_page->WasSwept() || cur_page->SweepingCompleted());
......
...@@ -468,16 +468,8 @@ void StoreBuffer::IteratePointersToNewSpace(ObjectSlotCallback slot_callback) { ...@@ -468,16 +468,8 @@ void StoreBuffer::IteratePointersToNewSpace(ObjectSlotCallback slot_callback) {
} }
} }
} else { } else {
if (!page->SweepingCompleted()) { heap_->mark_compact_collector()->SweepOrWaitUntilSweepingCompleted(
heap_->mark_compact_collector()->SweepInParallel(page, owner); page);
if (!page->SweepingCompleted()) {
// We were not able to sweep that page, i.e., a concurrent
// sweeper thread currently owns this page. Wait for the sweeper
// thread to be done with this page.
page->WaitUntilSweepingCompleted();
}
}
CHECK(page->owner() == heap_->old_space());
HeapObjectIterator iterator(page, NULL); HeapObjectIterator iterator(page, NULL);
for (HeapObject* heap_object = iterator.Next(); heap_object != NULL; for (HeapObject* heap_object = iterator.Next(); heap_object != NULL;
heap_object = iterator.Next()) { heap_object = iterator.Next()) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment