OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/heap/mark-compact.h" | 5 #include "src/heap/mark-compact.h" |
6 | 6 |
7 #include "src/base/atomicops.h" | 7 #include "src/base/atomicops.h" |
8 #include "src/base/bits.h" | 8 #include "src/base/bits.h" |
9 #include "src/base/sys-info.h" | 9 #include "src/base/sys-info.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
533 new SweeperTask(heap(), heap()->code_space()), | 533 new SweeperTask(heap(), heap()->code_space()), |
534 v8::Platform::kShortRunningTask); | 534 v8::Platform::kShortRunningTask); |
535 V8::GetCurrentPlatform()->CallOnBackgroundThread( | 535 V8::GetCurrentPlatform()->CallOnBackgroundThread( |
536 new SweeperTask(heap(), heap()->map_space()), | 536 new SweeperTask(heap(), heap()->map_space()), |
537 v8::Platform::kShortRunningTask); | 537 v8::Platform::kShortRunningTask); |
538 } | 538 } |
539 | 539 |
540 | 540 |
541 void MarkCompactCollector::SweepOrWaitUntilSweepingCompleted(Page* page) { | 541 void MarkCompactCollector::SweepOrWaitUntilSweepingCompleted(Page* page) { |
542 PagedSpace* owner = reinterpret_cast<PagedSpace*>(page->owner()); | 542 PagedSpace* owner = reinterpret_cast<PagedSpace*>(page->owner()); |
543 if (!page->SweepingCompleted()) { | 543 if (!page->SweepingDone()) { |
544 SweepInParallel(page, owner); | 544 SweepInParallel(page, owner); |
545 if (!page->SweepingCompleted()) { | 545 if (!page->SweepingDone()) { |
546 // We were not able to sweep that page, i.e., a concurrent | 546 // We were not able to sweep that page, i.e., a concurrent |
547 // sweeper thread currently owns this page. Wait for the sweeper | 547 // sweeper thread currently owns this page. Wait for the sweeper |
548 // thread to be done with this page. | 548 // thread to be done with this page. |
549 page->WaitUntilSweepingCompleted(); | 549 page->WaitUntilSweepingCompleted(); |
550 } | 550 } |
551 } | 551 } |
552 } | 552 } |
553 | 553 |
554 | 554 |
555 void MarkCompactCollector::SweepAndRefill(CompactionSpace* space) { | 555 void MarkCompactCollector::SweepAndRefill(CompactionSpace* space) { |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
714 PageIterator it(space); | 714 PageIterator it(space); |
715 while (it.has_next()) { | 715 while (it.has_next()) { |
716 Page* p = it.next(); | 716 Page* p = it.next(); |
717 if (p->NeverEvacuate()) continue; | 717 if (p->NeverEvacuate()) continue; |
718 if (p->IsFlagSet(Page::POPULAR_PAGE)) { | 718 if (p->IsFlagSet(Page::POPULAR_PAGE)) { |
719 // This page had slots buffer overflow on previous GC, skip it. | 719 // This page had slots buffer overflow on previous GC, skip it. |
720 p->ClearFlag(Page::POPULAR_PAGE); | 720 p->ClearFlag(Page::POPULAR_PAGE); |
721 continue; | 721 continue; |
722 } | 722 } |
723 // Invariant: Evacuation candidates are just created when marking is | 723 // Invariant: Evacuation candidates are just created when marking is |
724 // started. At the end of a GC all evacuation candidates are cleared and | 724 // started. This means that sweeping has finished. Furthermore, at the end |
725 // their slot buffers are released. | 725 // of a GC all evacuation candidates are cleared and their slot buffers are |
| 726 // released. |
726 CHECK(!p->IsEvacuationCandidate()); | 727 CHECK(!p->IsEvacuationCandidate()); |
727 CHECK(p->slots_buffer() == NULL); | 728 CHECK(p->slots_buffer() == nullptr); |
| 729 CHECK(p->SweepingDone()); |
728 DCHECK(p->area_size() == area_size); | 730 DCHECK(p->area_size() == area_size); |
729 int live_bytes = | 731 pages.push_back(std::make_pair(p->LiveBytesFromFreeList(), p)); |
730 p->WasSwept() ? p->LiveBytesFromFreeList() : p->LiveBytes(); | |
731 pages.push_back(std::make_pair(live_bytes, p)); | |
732 } | 732 } |
733 | 733 |
734 int candidate_count = 0; | 734 int candidate_count = 0; |
735 int total_live_bytes = 0; | 735 int total_live_bytes = 0; |
736 | 736 |
737 const bool reduce_memory = heap()->ShouldReduceMemory(); | 737 const bool reduce_memory = heap()->ShouldReduceMemory(); |
738 if (FLAG_manual_evacuation_candidates_selection) { | 738 if (FLAG_manual_evacuation_candidates_selection) { |
739 for (size_t i = 0; i < pages.size(); i++) { | 739 for (size_t i = 0; i < pages.size(); i++) { |
740 Page* p = pages[i].second; | 740 Page* p = pages[i].second; |
741 if (p->IsFlagSet(MemoryChunk::FORCE_EVACUATION_CANDIDATE_FOR_TESTING)) { | 741 if (p->IsFlagSet(MemoryChunk::FORCE_EVACUATION_CANDIDATE_FOR_TESTING)) { |
(...skipping 2475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3217 // might have stale store buffer entries that become "valid" again | 3217 // might have stale store buffer entries that become "valid" again |
3218 // after reusing the memory. Note that all existing store buffer | 3218 // after reusing the memory. Note that all existing store buffer |
3219 // entries of such pages are filtered before rescanning. | 3219 // entries of such pages are filtered before rescanning. |
3220 DCHECK(p->IsEvacuationCandidate()); | 3220 DCHECK(p->IsEvacuationCandidate()); |
3221 p->SetFlag(Page::COMPACTION_WAS_ABORTED); | 3221 p->SetFlag(Page::COMPACTION_WAS_ABORTED); |
3222 p->set_scan_on_scavenge(true); | 3222 p->set_scan_on_scavenge(true); |
3223 abandoned_pages++; | 3223 abandoned_pages++; |
3224 break; | 3224 break; |
3225 case MemoryChunk::kCompactingFinalize: | 3225 case MemoryChunk::kCompactingFinalize: |
3226 DCHECK(p->IsEvacuationCandidate()); | 3226 DCHECK(p->IsEvacuationCandidate()); |
3227 p->SetWasSwept(); | 3227 DCHECK(p->SweepingDone()); |
3228 p->Unlink(); | 3228 p->Unlink(); |
3229 break; | 3229 break; |
3230 case MemoryChunk::kCompactingDone: | 3230 case MemoryChunk::kCompactingDone: |
3231 DCHECK(p->IsFlagSet(Page::POPULAR_PAGE)); | 3231 DCHECK(p->IsFlagSet(Page::POPULAR_PAGE)); |
3232 DCHECK(p->IsFlagSet(Page::RESCAN_ON_EVACUATION)); | 3232 DCHECK(p->IsFlagSet(Page::RESCAN_ON_EVACUATION)); |
3233 break; | 3233 break; |
3234 default: | 3234 default: |
3235 // We should not observe kCompactingInProgress, or kCompactingDone. | 3235 // We should not observe kCompactingInProgress, or kCompactingDone. |
3236 UNREACHABLE(); | 3236 UNREACHABLE(); |
3237 } | 3237 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3283 | 3283 |
3284 void MarkCompactCollector::EvacuatePages( | 3284 void MarkCompactCollector::EvacuatePages( |
3285 CompactionSpaceCollection* compaction_spaces, | 3285 CompactionSpaceCollection* compaction_spaces, |
3286 SlotsBuffer** evacuation_slots_buffer) { | 3286 SlotsBuffer** evacuation_slots_buffer) { |
3287 EvacuateOldSpaceVisitor visitor(heap(), compaction_spaces, | 3287 EvacuateOldSpaceVisitor visitor(heap(), compaction_spaces, |
3288 evacuation_slots_buffer); | 3288 evacuation_slots_buffer); |
3289 for (int i = 0; i < evacuation_candidates_.length(); i++) { | 3289 for (int i = 0; i < evacuation_candidates_.length(); i++) { |
3290 Page* p = evacuation_candidates_[i]; | 3290 Page* p = evacuation_candidates_[i]; |
3291 DCHECK(p->IsEvacuationCandidate() || | 3291 DCHECK(p->IsEvacuationCandidate() || |
3292 p->IsFlagSet(Page::RESCAN_ON_EVACUATION)); | 3292 p->IsFlagSet(Page::RESCAN_ON_EVACUATION)); |
3293 DCHECK(static_cast<int>(p->parallel_sweeping_state().Value()) == | 3293 DCHECK(p->SweepingDone()); |
3294 MemoryChunk::kSweepingDone); | |
3295 if (p->parallel_compaction_state().TrySetValue( | 3294 if (p->parallel_compaction_state().TrySetValue( |
3296 MemoryChunk::kCompactingDone, MemoryChunk::kCompactingInProgress)) { | 3295 MemoryChunk::kCompactingDone, MemoryChunk::kCompactingInProgress)) { |
3297 if (p->IsEvacuationCandidate()) { | 3296 if (p->IsEvacuationCandidate()) { |
3298 DCHECK_EQ(p->parallel_compaction_state().Value(), | 3297 DCHECK_EQ(p->parallel_compaction_state().Value(), |
3299 MemoryChunk::kCompactingInProgress); | 3298 MemoryChunk::kCompactingInProgress); |
3300 double start = heap()->MonotonicallyIncreasingTimeInMs(); | 3299 double start = heap()->MonotonicallyIncreasingTimeInMs(); |
3301 intptr_t live_bytes = p->LiveBytes(); | 3300 intptr_t live_bytes = p->LiveBytes(); |
3302 AlwaysAllocateScope always_allocate(isolate()); | 3301 AlwaysAllocateScope always_allocate(isolate()); |
3303 if (VisitLiveObjects(p, &visitor, kClearMarkbits)) { | 3302 if (VisitLiveObjects(p, &visitor, kClearMarkbits)) { |
3304 p->parallel_compaction_state().SetValue( | 3303 p->parallel_compaction_state().SetValue( |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3358 // Sweeps a page. After sweeping the page can be iterated. | 3357 // Sweeps a page. After sweeping the page can be iterated. |
3359 // Slots in live objects pointing into evacuation candidates are updated | 3358 // Slots in live objects pointing into evacuation candidates are updated |
3360 // if requested. | 3359 // if requested. |
3361 // Returns the size of the biggest continuous freed memory chunk in bytes. | 3360 // Returns the size of the biggest continuous freed memory chunk in bytes. |
3362 template <SweepingMode sweeping_mode, | 3361 template <SweepingMode sweeping_mode, |
3363 MarkCompactCollector::SweepingParallelism parallelism, | 3362 MarkCompactCollector::SweepingParallelism parallelism, |
3364 SkipListRebuildingMode skip_list_mode, | 3363 SkipListRebuildingMode skip_list_mode, |
3365 FreeSpaceTreatmentMode free_space_mode> | 3364 FreeSpaceTreatmentMode free_space_mode> |
3366 static int Sweep(PagedSpace* space, FreeList* free_list, Page* p, | 3365 static int Sweep(PagedSpace* space, FreeList* free_list, Page* p, |
3367 ObjectVisitor* v) { | 3366 ObjectVisitor* v) { |
3368 DCHECK(!p->IsEvacuationCandidate() && !p->WasSwept()); | 3367 DCHECK(!p->IsEvacuationCandidate() && !p->SweepingDone()); |
3369 DCHECK_EQ(skip_list_mode == REBUILD_SKIP_LIST, | 3368 DCHECK_EQ(skip_list_mode == REBUILD_SKIP_LIST, |
3370 space->identity() == CODE_SPACE); | 3369 space->identity() == CODE_SPACE); |
3371 DCHECK((p->skip_list() == NULL) || (skip_list_mode == REBUILD_SKIP_LIST)); | 3370 DCHECK((p->skip_list() == NULL) || (skip_list_mode == REBUILD_SKIP_LIST)); |
3372 DCHECK(parallelism == MarkCompactCollector::SWEEP_ON_MAIN_THREAD || | 3371 DCHECK(parallelism == MarkCompactCollector::SWEEP_ON_MAIN_THREAD || |
3373 sweeping_mode == SWEEP_ONLY); | 3372 sweeping_mode == SWEEP_ONLY); |
3374 | 3373 |
3375 Address free_start = p->area_start(); | 3374 Address free_start = p->area_start(); |
3376 DCHECK(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0); | 3375 DCHECK(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0); |
3377 | 3376 |
3378 // If we use the skip list for code space pages, we have to lock the skip | 3377 // If we use the skip list for code space pages, we have to lock the skip |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3421 Bitmap::Clear(p); | 3420 Bitmap::Clear(p); |
3422 | 3421 |
3423 if (free_start != p->area_end()) { | 3422 if (free_start != p->area_end()) { |
3424 int size = static_cast<int>(p->area_end() - free_start); | 3423 int size = static_cast<int>(p->area_end() - free_start); |
3425 if (free_space_mode == ZAP_FREE_SPACE) { | 3424 if (free_space_mode == ZAP_FREE_SPACE) { |
3426 memset(free_start, 0xcc, size); | 3425 memset(free_start, 0xcc, size); |
3427 } | 3426 } |
3428 freed_bytes = Free<parallelism>(space, free_list, free_start, size); | 3427 freed_bytes = Free<parallelism>(space, free_list, free_start, size); |
3429 max_freed_bytes = Max(freed_bytes, max_freed_bytes); | 3428 max_freed_bytes = Max(freed_bytes, max_freed_bytes); |
3430 } | 3429 } |
3431 | 3430 p->concurrent_sweeping_state().SetValue(Page::kSweepingDone); |
3432 if (parallelism == MarkCompactCollector::SWEEP_IN_PARALLEL) { | |
3433 // When concurrent sweeping is active, the page will be marked after | |
3434 // sweeping by the main thread. | |
3435 p->parallel_sweeping_state().SetValue(MemoryChunk::kSweepingFinalize); | |
3436 } else { | |
3437 p->SetWasSwept(); | |
3438 } | |
3439 return FreeList::GuaranteedAllocatable(static_cast<int>(max_freed_bytes)); | 3431 return FreeList::GuaranteedAllocatable(static_cast<int>(max_freed_bytes)); |
3440 } | 3432 } |
3441 | 3433 |
3442 | 3434 |
3443 void MarkCompactCollector::InvalidateCode(Code* code) { | 3435 void MarkCompactCollector::InvalidateCode(Code* code) { |
3444 if (heap_->incremental_marking()->IsCompacting() && | 3436 if (heap_->incremental_marking()->IsCompacting() && |
3445 !ShouldSkipEvacuationSlotRecording(code)) { | 3437 !ShouldSkipEvacuationSlotRecording(code)) { |
3446 DCHECK(compacting_); | 3438 DCHECK(compacting_); |
3447 | 3439 |
3448 // If the object is white than no slots were recorded on it yet. | 3440 // If the object is white than no slots were recorded on it yet. |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3547 } | 3539 } |
3548 } | 3540 } |
3549 | 3541 |
3550 | 3542 |
3551 void MarkCompactCollector::SweepAbortedPages() { | 3543 void MarkCompactCollector::SweepAbortedPages() { |
3552 // Second pass on aborted pages. | 3544 // Second pass on aborted pages. |
3553 for (int i = 0; i < evacuation_candidates_.length(); i++) { | 3545 for (int i = 0; i < evacuation_candidates_.length(); i++) { |
3554 Page* p = evacuation_candidates_[i]; | 3546 Page* p = evacuation_candidates_[i]; |
3555 if (p->IsFlagSet(Page::COMPACTION_WAS_ABORTED)) { | 3547 if (p->IsFlagSet(Page::COMPACTION_WAS_ABORTED)) { |
3556 p->ClearFlag(MemoryChunk::COMPACTION_WAS_ABORTED); | 3548 p->ClearFlag(MemoryChunk::COMPACTION_WAS_ABORTED); |
| 3549 p->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); |
3557 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); | 3550 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); |
3558 switch (space->identity()) { | 3551 switch (space->identity()) { |
3559 case OLD_SPACE: | 3552 case OLD_SPACE: |
3560 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, IGNORE_SKIP_LIST, | 3553 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, IGNORE_SKIP_LIST, |
3561 IGNORE_FREE_SPACE>(space, nullptr, p, nullptr); | 3554 IGNORE_FREE_SPACE>(space, nullptr, p, nullptr); |
3562 break; | 3555 break; |
3563 case CODE_SPACE: | 3556 case CODE_SPACE: |
3564 if (FLAG_zap_code_space) { | 3557 if (FLAG_zap_code_space) { |
3565 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, REBUILD_SKIP_LIST, | 3558 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, REBUILD_SKIP_LIST, |
3566 ZAP_FREE_SPACE>(space, NULL, p, nullptr); | 3559 ZAP_FREE_SPACE>(space, NULL, p, nullptr); |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3709 } | 3702 } |
3710 } | 3703 } |
3711 | 3704 |
3712 if (p->IsFlagSet(Page::RESCAN_ON_EVACUATION)) { | 3705 if (p->IsFlagSet(Page::RESCAN_ON_EVACUATION)) { |
3713 if (FLAG_gc_verbose) { | 3706 if (FLAG_gc_verbose) { |
3714 PrintF("Sweeping 0x%" V8PRIxPTR " during evacuation.\n", | 3707 PrintF("Sweeping 0x%" V8PRIxPTR " during evacuation.\n", |
3715 reinterpret_cast<intptr_t>(p)); | 3708 reinterpret_cast<intptr_t>(p)); |
3716 } | 3709 } |
3717 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); | 3710 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); |
3718 p->ClearFlag(MemoryChunk::RESCAN_ON_EVACUATION); | 3711 p->ClearFlag(MemoryChunk::RESCAN_ON_EVACUATION); |
| 3712 p->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); |
3719 | 3713 |
3720 switch (space->identity()) { | 3714 switch (space->identity()) { |
3721 case OLD_SPACE: | 3715 case OLD_SPACE: |
3722 Sweep<SWEEP_AND_VISIT_LIVE_OBJECTS, SWEEP_ON_MAIN_THREAD, | 3716 Sweep<SWEEP_AND_VISIT_LIVE_OBJECTS, SWEEP_ON_MAIN_THREAD, |
3723 IGNORE_SKIP_LIST, IGNORE_FREE_SPACE>(space, NULL, p, | 3717 IGNORE_SKIP_LIST, IGNORE_FREE_SPACE>(space, NULL, p, |
3724 &updating_visitor); | 3718 &updating_visitor); |
3725 break; | 3719 break; |
3726 case CODE_SPACE: | 3720 case CODE_SPACE: |
3727 if (FLAG_zap_code_space) { | 3721 if (FLAG_zap_code_space) { |
3728 Sweep<SWEEP_AND_VISIT_LIVE_OBJECTS, SWEEP_ON_MAIN_THREAD, | 3722 Sweep<SWEEP_AND_VISIT_LIVE_OBJECTS, SWEEP_ON_MAIN_THREAD, |
(...skipping 30 matching lines...) Expand all Loading... |
3759 | 3753 |
3760 void MarkCompactCollector::ReleaseEvacuationCandidates() { | 3754 void MarkCompactCollector::ReleaseEvacuationCandidates() { |
3761 int npages = evacuation_candidates_.length(); | 3755 int npages = evacuation_candidates_.length(); |
3762 for (int i = 0; i < npages; i++) { | 3756 for (int i = 0; i < npages; i++) { |
3763 Page* p = evacuation_candidates_[i]; | 3757 Page* p = evacuation_candidates_[i]; |
3764 if (!p->IsEvacuationCandidate()) continue; | 3758 if (!p->IsEvacuationCandidate()) continue; |
3765 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); | 3759 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); |
3766 space->Free(p->area_start(), p->area_size()); | 3760 space->Free(p->area_start(), p->area_size()); |
3767 p->set_scan_on_scavenge(false); | 3761 p->set_scan_on_scavenge(false); |
3768 p->ResetLiveBytes(); | 3762 p->ResetLiveBytes(); |
3769 CHECK(p->WasSwept()); | 3763 CHECK(p->SweepingDone()); |
3770 space->ReleasePage(p); | 3764 space->ReleasePage(p, true); |
3771 } | 3765 } |
3772 evacuation_candidates_.Rewind(0); | 3766 evacuation_candidates_.Rewind(0); |
3773 compacting_ = false; | 3767 compacting_ = false; |
3774 heap()->FilterStoreBufferEntriesOnAboutToBeFreedPages(); | 3768 heap()->FilterStoreBufferEntriesOnAboutToBeFreedPages(); |
3775 heap()->FreeQueuedChunks(); | 3769 heap()->FreeQueuedChunks(); |
3776 } | 3770 } |
3777 | 3771 |
3778 | 3772 |
3779 int MarkCompactCollector::SweepInParallel(PagedSpace* space, | 3773 int MarkCompactCollector::SweepInParallel(PagedSpace* space, |
3780 int required_freed_bytes, | 3774 int required_freed_bytes, |
(...skipping 14 matching lines...) Expand all Loading... |
3795 } | 3789 } |
3796 } | 3790 } |
3797 return max_freed_overall; | 3791 return max_freed_overall; |
3798 } | 3792 } |
3799 | 3793 |
3800 | 3794 |
3801 int MarkCompactCollector::SweepInParallel(Page* page, PagedSpace* space) { | 3795 int MarkCompactCollector::SweepInParallel(Page* page, PagedSpace* space) { |
3802 int max_freed = 0; | 3796 int max_freed = 0; |
3803 if (page->TryLock()) { | 3797 if (page->TryLock()) { |
3804 // If this page was already swept in the meantime, we can return here. | 3798 // If this page was already swept in the meantime, we can return here. |
3805 if (page->parallel_sweeping_state().Value() != | 3799 if (page->concurrent_sweeping_state().Value() != Page::kSweepingPending) { |
3806 MemoryChunk::kSweepingPending) { | |
3807 page->mutex()->Unlock(); | 3800 page->mutex()->Unlock(); |
3808 return 0; | 3801 return 0; |
3809 } | 3802 } |
3810 page->parallel_sweeping_state().SetValue(MemoryChunk::kSweepingInProgress); | 3803 page->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); |
3811 FreeList* free_list; | 3804 FreeList* free_list; |
3812 FreeList private_free_list(space); | 3805 FreeList private_free_list(space); |
3813 if (space->identity() == OLD_SPACE) { | 3806 if (space->identity() == OLD_SPACE) { |
3814 free_list = free_list_old_space_.get(); | 3807 free_list = free_list_old_space_.get(); |
3815 max_freed = | 3808 max_freed = |
3816 Sweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, IGNORE_SKIP_LIST, | 3809 Sweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, IGNORE_SKIP_LIST, |
3817 IGNORE_FREE_SPACE>(space, &private_free_list, page, NULL); | 3810 IGNORE_FREE_SPACE>(space, &private_free_list, page, NULL); |
3818 } else if (space->identity() == CODE_SPACE) { | 3811 } else if (space->identity() == CODE_SPACE) { |
3819 free_list = free_list_code_space_.get(); | 3812 free_list = free_list_code_space_.get(); |
3820 max_freed = | 3813 max_freed = |
3821 Sweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, REBUILD_SKIP_LIST, | 3814 Sweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, REBUILD_SKIP_LIST, |
3822 IGNORE_FREE_SPACE>(space, &private_free_list, page, NULL); | 3815 IGNORE_FREE_SPACE>(space, &private_free_list, page, NULL); |
3823 } else { | 3816 } else { |
3824 free_list = free_list_map_space_.get(); | 3817 free_list = free_list_map_space_.get(); |
3825 max_freed = | 3818 max_freed = |
3826 Sweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, IGNORE_SKIP_LIST, | 3819 Sweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, IGNORE_SKIP_LIST, |
3827 IGNORE_FREE_SPACE>(space, &private_free_list, page, NULL); | 3820 IGNORE_FREE_SPACE>(space, &private_free_list, page, NULL); |
3828 } | 3821 } |
3829 free_list->Concatenate(&private_free_list); | 3822 free_list->Concatenate(&private_free_list); |
| 3823 page->concurrent_sweeping_state().SetValue(Page::kSweepingDone); |
3830 page->mutex()->Unlock(); | 3824 page->mutex()->Unlock(); |
3831 } | 3825 } |
3832 return max_freed; | 3826 return max_freed; |
3833 } | 3827 } |
3834 | 3828 |
3835 | 3829 |
3836 void MarkCompactCollector::StartSweepSpace(PagedSpace* space) { | 3830 void MarkCompactCollector::StartSweepSpace(PagedSpace* space) { |
3837 space->ClearStats(); | 3831 space->ClearStats(); |
3838 | 3832 |
3839 PageIterator it(space); | 3833 PageIterator it(space); |
3840 | 3834 |
3841 int will_be_swept = 0; | 3835 int will_be_swept = 0; |
3842 bool unused_page_present = false; | 3836 bool unused_page_present = false; |
3843 | 3837 |
3844 while (it.has_next()) { | 3838 while (it.has_next()) { |
3845 Page* p = it.next(); | 3839 Page* p = it.next(); |
3846 DCHECK(p->parallel_sweeping_state().Value() == MemoryChunk::kSweepingDone); | 3840 DCHECK(p->SweepingDone()); |
3847 | |
3848 // Clear sweeping flags indicating that marking bits are still intact. | |
3849 p->ClearWasSwept(); | |
3850 | 3841 |
3851 if (p->IsFlagSet(Page::RESCAN_ON_EVACUATION) || | 3842 if (p->IsFlagSet(Page::RESCAN_ON_EVACUATION) || |
3852 p->IsEvacuationCandidate()) { | 3843 p->IsEvacuationCandidate()) { |
3853 // Will be processed in EvacuateNewSpaceAndCandidates. | 3844 // Will be processed in EvacuateNewSpaceAndCandidates. |
3854 DCHECK(evacuation_candidates_.length() > 0); | 3845 DCHECK(evacuation_candidates_.length() > 0); |
3855 continue; | 3846 continue; |
3856 } | 3847 } |
3857 | 3848 |
3858 if (p->IsFlagSet(Page::NEVER_ALLOCATE_ON_PAGE)) { | 3849 if (p->IsFlagSet(Page::NEVER_ALLOCATE_ON_PAGE)) { |
3859 // We need to sweep the page to get it into an iterable state again. Note | 3850 // We need to sweep the page to get it into an iterable state again. Note |
3860 // that this adds unusable memory into the free list that is later on | 3851 // that this adds unusable memory into the free list that is later on |
3861 // (in the free list) dropped again. Since we only use the flag for | 3852 // (in the free list) dropped again. Since we only use the flag for |
3862 // testing this is fine. | 3853 // testing this is fine. |
| 3854 p->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); |
3863 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, IGNORE_SKIP_LIST, | 3855 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, IGNORE_SKIP_LIST, |
3864 IGNORE_FREE_SPACE>(space, nullptr, p, nullptr); | 3856 IGNORE_FREE_SPACE>(space, nullptr, p, nullptr); |
3865 continue; | 3857 continue; |
3866 } | 3858 } |
3867 | 3859 |
3868 // One unused page is kept, all further are released before sweeping them. | 3860 // One unused page is kept, all further are released before sweeping them. |
3869 if (p->LiveBytes() == 0) { | 3861 if (p->LiveBytes() == 0) { |
3870 if (unused_page_present) { | 3862 if (unused_page_present) { |
3871 if (FLAG_gc_verbose) { | 3863 if (FLAG_gc_verbose) { |
3872 PrintIsolate(isolate(), "sweeping: released page: %p", p); | 3864 PrintIsolate(isolate(), "sweeping: released page: %p", p); |
3873 } | 3865 } |
3874 space->ReleasePage(p); | 3866 space->ReleasePage(p, false); |
3875 continue; | 3867 continue; |
3876 } | 3868 } |
3877 unused_page_present = true; | 3869 unused_page_present = true; |
3878 } | 3870 } |
3879 | 3871 |
| 3872 p->concurrent_sweeping_state().SetValue(Page::kSweepingPending); |
3880 sweeping_list(space).push_back(p); | 3873 sweeping_list(space).push_back(p); |
3881 p->parallel_sweeping_state().SetValue(MemoryChunk::kSweepingPending); | |
3882 int to_sweep = p->area_size() - p->LiveBytes(); | 3874 int to_sweep = p->area_size() - p->LiveBytes(); |
3883 space->accounting_stats_.ShrinkSpace(to_sweep); | 3875 space->accounting_stats_.ShrinkSpace(to_sweep); |
3884 will_be_swept++; | 3876 will_be_swept++; |
3885 } | 3877 } |
3886 | 3878 |
3887 if (FLAG_gc_verbose) { | 3879 if (FLAG_gc_verbose) { |
3888 PrintIsolate(isolate(), "sweeping: space=%s initialized_for_sweeping=%d", | 3880 PrintIsolate(isolate(), "sweeping: space=%s initialized_for_sweeping=%d", |
3889 AllocationSpaceName(space->identity()), will_be_swept); | 3881 AllocationSpaceName(space->identity()), will_be_swept); |
3890 } | 3882 } |
3891 std::sort(sweeping_list(space).begin(), sweeping_list(space).end(), | 3883 std::sort(sweeping_list(space).begin(), sweeping_list(space).end(), |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3933 // buffer entries are already filter out. We can just release the memory. | 3925 // buffer entries are already filter out. We can just release the memory. |
3934 heap()->FreeQueuedChunks(); | 3926 heap()->FreeQueuedChunks(); |
3935 | 3927 |
3936 if (FLAG_print_cumulative_gc_stat) { | 3928 if (FLAG_print_cumulative_gc_stat) { |
3937 heap_->tracer()->AddSweepingTime(heap_->MonotonicallyIncreasingTimeInMs() - | 3929 heap_->tracer()->AddSweepingTime(heap_->MonotonicallyIncreasingTimeInMs() - |
3938 start_time); | 3930 start_time); |
3939 } | 3931 } |
3940 } | 3932 } |
3941 | 3933 |
3942 | 3934 |
3943 void MarkCompactCollector::ParallelSweepSpaceComplete(PagedSpace* space) { | |
3944 for (Page* p : sweeping_list(space)) { | |
3945 if (p->parallel_sweeping_state().Value() == | |
3946 MemoryChunk::kSweepingFinalize) { | |
3947 p->parallel_sweeping_state().SetValue(MemoryChunk::kSweepingDone); | |
3948 p->SetWasSwept(); | |
3949 } | |
3950 DCHECK(p->parallel_sweeping_state().Value() == MemoryChunk::kSweepingDone); | |
3951 } | |
3952 } | |
3953 | |
3954 | |
3955 void MarkCompactCollector::ParallelSweepSpacesComplete() { | 3935 void MarkCompactCollector::ParallelSweepSpacesComplete() { |
3956 ParallelSweepSpaceComplete(heap()->old_space()); | |
3957 ParallelSweepSpaceComplete(heap()->code_space()); | |
3958 ParallelSweepSpaceComplete(heap()->map_space()); | |
3959 sweeping_list(heap()->old_space()).clear(); | 3936 sweeping_list(heap()->old_space()).clear(); |
3960 sweeping_list(heap()->code_space()).clear(); | 3937 sweeping_list(heap()->code_space()).clear(); |
3961 sweeping_list(heap()->map_space()).clear(); | 3938 sweeping_list(heap()->map_space()).clear(); |
3962 } | 3939 } |
3963 | 3940 |
3964 | 3941 |
3965 // TODO(1466) ReportDeleteIfNeeded is not called currently. | 3942 // TODO(1466) ReportDeleteIfNeeded is not called currently. |
3966 // Our profiling tools do not expect intersections between | 3943 // Our profiling tools do not expect intersections between |
3967 // code objects. We should either reenable it or change our tools. | 3944 // code objects. We should either reenable it or change our tools. |
3968 void MarkCompactCollector::ReportDeleteIfNeeded(HeapObject* obj, | 3945 void MarkCompactCollector::ReportDeleteIfNeeded(HeapObject* obj, |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4029 MarkBit mark_bit = Marking::MarkBitFrom(host); | 4006 MarkBit mark_bit = Marking::MarkBitFrom(host); |
4030 if (Marking::IsBlack(mark_bit)) { | 4007 if (Marking::IsBlack(mark_bit)) { |
4031 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); | 4008 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); |
4032 RecordRelocSlot(&rinfo, target); | 4009 RecordRelocSlot(&rinfo, target); |
4033 } | 4010 } |
4034 } | 4011 } |
4035 } | 4012 } |
4036 | 4013 |
4037 } // namespace internal | 4014 } // namespace internal |
4038 } // namespace v8 | 4015 } // namespace v8 |
OLD | NEW |