| 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 527 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 538 Page* MarkCompactCollector::Sweeper::GetSweptPageSafe(PagedSpace* space) { | 538 Page* MarkCompactCollector::Sweeper::GetSweptPageSafe(PagedSpace* space) { |
| 539 base::LockGuard<base::Mutex> guard(&mutex_); | 539 base::LockGuard<base::Mutex> guard(&mutex_); |
| 540 SweptList& list = swept_list_[space->identity()]; | 540 SweptList& list = swept_list_[space->identity()]; |
| 541 if (list.length() > 0) { | 541 if (list.length() > 0) { |
| 542 return list.RemoveLast(); | 542 return list.RemoveLast(); |
| 543 } | 543 } |
| 544 return nullptr; | 544 return nullptr; |
| 545 } | 545 } |
| 546 | 546 |
| 547 void MarkCompactCollector::Sweeper::EnsureCompleted() { | 547 void MarkCompactCollector::Sweeper::EnsureCompleted() { |
| 548 DCHECK(sweeping_in_progress_ == true); | 548 if (!sweeping_in_progress_) return; |
| 549 | 549 |
| 550 // If sweeping is not completed or not running at all, we try to complete it | 550 // If sweeping is not completed or not running at all, we try to complete it |
| 551 // here. | 551 // here. |
| 552 if (!FLAG_concurrent_sweeping || !IsSweepingCompleted()) { | 552 if (!FLAG_concurrent_sweeping || !IsSweepingCompleted()) { |
| 553 ForAllSweepingSpaces( | 553 ForAllSweepingSpaces( |
| 554 [this](AllocationSpace space) { ParallelSweepSpace(space, 0); }); | 554 [this](AllocationSpace space) { ParallelSweepSpace(space, 0); }); |
| 555 } | 555 } |
| 556 | 556 |
| 557 if (FLAG_concurrent_sweeping) { | 557 if (FLAG_concurrent_sweeping) { |
| 558 while (num_sweeping_tasks_ > 0) { | 558 while (num_sweeping_tasks_ > 0) { |
| 559 pending_sweeper_tasks_semaphore_.Wait(); | 559 pending_sweeper_tasks_semaphore_.Wait(); |
| 560 num_sweeping_tasks_--; | 560 num_sweeping_tasks_--; |
| 561 } | 561 } |
| 562 } | 562 } |
| 563 | 563 |
| 564 DCHECK(sweeping_list_[NEW_SPACE].empty()); | 564 ForAllSweepingSpaces( |
| 565 ForAllSweepingSpaces([this](AllocationSpace space) { | 565 [this](AllocationSpace space) { DCHECK(sweeping_list_[space].empty()); }); |
| 566 DCHECK_NULL(tmp_late_sweeping_list_[space]); | 566 late_pages_ = false; |
| 567 sweeping_list_[space].clear(); | |
| 568 if (late_sweeping_list_[space] != nullptr) { | |
| 569 delete late_sweeping_list_[space]; | |
| 570 } | |
| 571 }); | |
| 572 | |
| 573 sweeping_in_progress_ = false; | 567 sweeping_in_progress_ = false; |
| 574 } | 568 } |
| 575 | 569 |
| 576 void MarkCompactCollector::EnsureSweepingCompleted() { | 570 void MarkCompactCollector::EnsureSweepingCompleted() { |
| 577 DCHECK(sweeper().sweeping_in_progress() == true); | 571 if (!sweeper().sweeping_in_progress()) return; |
| 578 | 572 |
| 579 sweeper().EnsureCompleted(); | 573 sweeper().EnsureCompleted(); |
| 580 heap()->old_space()->RefillFreeList(); | 574 heap()->old_space()->RefillFreeList(); |
| 581 heap()->code_space()->RefillFreeList(); | 575 heap()->code_space()->RefillFreeList(); |
| 582 heap()->map_space()->RefillFreeList(); | 576 heap()->map_space()->RefillFreeList(); |
| 583 | 577 |
| 584 #ifdef VERIFY_HEAP | 578 #ifdef VERIFY_HEAP |
| 585 if (FLAG_verify_heap && !evacuation()) { | 579 if (FLAG_verify_heap && !evacuation()) { |
| 586 VerifyEvacuation(heap_); | 580 VerifyEvacuation(heap_); |
| 587 } | 581 } |
| (...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 883 if (!was_marked_incrementally_ && FLAG_verify_heap) { | 877 if (!was_marked_incrementally_ && FLAG_verify_heap) { |
| 884 VerifyMarkbitsAreClean(); | 878 VerifyMarkbitsAreClean(); |
| 885 } | 879 } |
| 886 #endif | 880 #endif |
| 887 } | 881 } |
| 888 | 882 |
| 889 | 883 |
| 890 void MarkCompactCollector::Finish() { | 884 void MarkCompactCollector::Finish() { |
| 891 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_FINISH); | 885 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_FINISH); |
| 892 | 886 |
| 887 if (sweeper().contains_late_pages() && FLAG_concurrent_sweeping) { |
| 888 // If we added some more pages during MC, we need to start at least one |
| 889 // more task as all other tasks might already be finished. |
| 890 sweeper().StartSweepingHelper(OLD_SPACE); |
| 891 } |
| 892 |
| 893 // The hashing of weak_object_to_code_table is no longer valid. | 893 // The hashing of weak_object_to_code_table is no longer valid. |
| 894 heap()->weak_object_to_code_table()->Rehash( | 894 heap()->weak_object_to_code_table()->Rehash( |
| 895 heap()->isolate()->factory()->undefined_value()); | 895 heap()->isolate()->factory()->undefined_value()); |
| 896 | 896 |
| 897 // Clear the marking state of live large objects. | 897 // Clear the marking state of live large objects. |
| 898 heap_->lo_space()->ClearMarkingStateOfLiveObjects(); | 898 heap_->lo_space()->ClearMarkingStateOfLiveObjects(); |
| 899 | 899 |
| 900 #ifdef DEBUG | 900 #ifdef DEBUG |
| 901 DCHECK(state_ == SWEEP_SPACES || state_ == RELOCATE_OBJECTS); | 901 DCHECK(state_ == SWEEP_SPACES || state_ == RELOCATE_OBJECTS); |
| 902 state_ = IDLE; | 902 state_ = IDLE; |
| (...skipping 2775 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3678 evacuation_candidates_.Rewind(0); | 3678 evacuation_candidates_.Rewind(0); |
| 3679 compacting_ = false; | 3679 compacting_ = false; |
| 3680 heap()->FreeQueuedChunks(); | 3680 heap()->FreeQueuedChunks(); |
| 3681 } | 3681 } |
| 3682 | 3682 |
| 3683 int MarkCompactCollector::Sweeper::ParallelSweepSpace(AllocationSpace identity, | 3683 int MarkCompactCollector::Sweeper::ParallelSweepSpace(AllocationSpace identity, |
| 3684 int required_freed_bytes, | 3684 int required_freed_bytes, |
| 3685 int max_pages) { | 3685 int max_pages) { |
| 3686 int max_freed = 0; | 3686 int max_freed = 0; |
| 3687 int pages_freed = 0; | 3687 int pages_freed = 0; |
| 3688 ParallelSweepList(sweeping_list_[identity], identity, required_freed_bytes, | 3688 Page* page = nullptr; |
| 3689 max_pages, &max_freed, &pages_freed); | 3689 while ((page = GetSweepingPageSafe(identity)) != nullptr) { |
| 3690 if ((required_freed_bytes) > 0 && (max_freed >= required_freed_bytes)) | 3690 int freed = ParallelSweepPage(page, heap_->paged_space(identity)); |
| 3691 return max_freed; | 3691 pages_freed += 1; |
| 3692 if ((max_pages > 0) && (pages_freed >= max_pages)) return max_freed; | 3692 DCHECK_GE(freed, 0); |
| 3693 SweepingList* late_list = GetLateSweepingListSafe(identity); | 3693 max_freed = Max(max_freed, freed); |
| 3694 if (late_list != nullptr) { | 3694 if ((required_freed_bytes) > 0 && (max_freed >= required_freed_bytes)) |
| 3695 ParallelSweepList(*late_list, identity, required_freed_bytes, max_pages, | 3695 return max_freed; |
| 3696 &max_freed, &pages_freed); | 3696 if ((max_pages > 0) && (pages_freed >= max_pages)) return max_freed; |
| 3697 } | 3697 } |
| 3698 return max_freed; | 3698 return max_freed; |
| 3699 } | 3699 } |
| 3700 | 3700 |
| 3701 void MarkCompactCollector::Sweeper::ParallelSweepList( | |
| 3702 SweepingList& list, AllocationSpace out_space, int required_freed_bytes, | |
| 3703 int max_pages, int* max_freed, int* pages_freed) { | |
| 3704 for (Page* p : list) { | |
| 3705 int freed = ParallelSweepPage(p, heap_->paged_space(out_space)); | |
| 3706 *pages_freed += 1; | |
| 3707 DCHECK_GE(freed, 0); | |
| 3708 *max_freed = Max(*max_freed, freed); | |
| 3709 if ((required_freed_bytes) > 0 && (*max_freed >= required_freed_bytes)) | |
| 3710 return; | |
| 3711 if ((max_pages > 0) && (*pages_freed >= max_pages)) return; | |
| 3712 } | |
| 3713 } | |
| 3714 | |
| 3715 int MarkCompactCollector::Sweeper::ParallelSweepPage(Page* page, | 3701 int MarkCompactCollector::Sweeper::ParallelSweepPage(Page* page, |
| 3716 PagedSpace* space) { | 3702 PagedSpace* space) { |
| 3717 int max_freed = 0; | 3703 int max_freed = 0; |
| 3718 if (page->mutex()->TryLock()) { | 3704 if (page->mutex()->TryLock()) { |
| 3719 // If this page was already swept in the meantime, we can return here. | 3705 // If this page was already swept in the meantime, we can return here. |
| 3720 if (page->concurrent_sweeping_state().Value() != Page::kSweepingPending) { | 3706 if (page->concurrent_sweeping_state().Value() != Page::kSweepingPending) { |
| 3721 page->mutex()->Unlock(); | 3707 page->mutex()->Unlock(); |
| 3722 return 0; | 3708 return 0; |
| 3723 } | 3709 } |
| 3724 page->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); | 3710 page->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 3745 void MarkCompactCollector::Sweeper::AddPage(AllocationSpace space, Page* page) { | 3731 void MarkCompactCollector::Sweeper::AddPage(AllocationSpace space, Page* page) { |
| 3746 DCHECK(!sweeping_in_progress_); | 3732 DCHECK(!sweeping_in_progress_); |
| 3747 PrepareToBeSweptPage(space, page); | 3733 PrepareToBeSweptPage(space, page); |
| 3748 sweeping_list_[space].push_back(page); | 3734 sweeping_list_[space].push_back(page); |
| 3749 } | 3735 } |
| 3750 | 3736 |
| 3751 void MarkCompactCollector::Sweeper::AddLatePage(AllocationSpace space, | 3737 void MarkCompactCollector::Sweeper::AddLatePage(AllocationSpace space, |
| 3752 Page* page) { | 3738 Page* page) { |
| 3753 DCHECK(sweeping_in_progress_); | 3739 DCHECK(sweeping_in_progress_); |
| 3754 PrepareToBeSweptPage(space, page); | 3740 PrepareToBeSweptPage(space, page); |
| 3755 if (tmp_late_sweeping_list_[space] == nullptr) { | 3741 late_pages_ = true; |
| 3756 tmp_late_sweeping_list_[space] = new SweepingList(); | 3742 AddSweepingPageSafe(space, page); |
| 3757 } | |
| 3758 tmp_late_sweeping_list_[space]->push_back(page); | |
| 3759 } | 3743 } |
| 3760 | 3744 |
| 3761 void MarkCompactCollector::Sweeper::PrepareToBeSweptPage(AllocationSpace space, | 3745 void MarkCompactCollector::Sweeper::PrepareToBeSweptPage(AllocationSpace space, |
| 3762 Page* page) { | 3746 Page* page) { |
| 3763 page->concurrent_sweeping_state().SetValue(Page::kSweepingPending); | 3747 page->concurrent_sweeping_state().SetValue(Page::kSweepingPending); |
| 3764 int to_sweep = page->area_size() - page->LiveBytes(); | 3748 int to_sweep = page->area_size() - page->LiveBytes(); |
| 3765 heap_->paged_space(space)->accounting_stats_.ShrinkSpace(to_sweep); | 3749 heap_->paged_space(space)->accounting_stats_.ShrinkSpace(to_sweep); |
| 3766 } | 3750 } |
| 3767 | 3751 |
| 3768 void MarkCompactCollector::Sweeper::CommitLateList(AllocationSpace space) { | 3752 Page* MarkCompactCollector::Sweeper::GetSweepingPageSafe( |
| 3769 DCHECK(sweeping_in_progress_); | 3753 AllocationSpace space) { |
| 3770 base::LockGuard<base::Mutex> guard(&mutex_); | 3754 base::LockGuard<base::Mutex> guard(&mutex_); |
| 3771 DCHECK_NULL(late_sweeping_list_[space]); | 3755 Page* page = nullptr; |
| 3772 late_sweeping_list_[space] = tmp_late_sweeping_list_[space]; | 3756 if (!sweeping_list_[space].empty()) { |
| 3757 page = sweeping_list_[space].front(); |
| 3758 sweeping_list_[space].pop_front(); |
| 3759 } |
| 3760 return page; |
| 3773 } | 3761 } |
| 3774 | 3762 |
| 3775 MarkCompactCollector::Sweeper::SweepingList* | 3763 void MarkCompactCollector::Sweeper::AddSweepingPageSafe(AllocationSpace space, |
| 3776 MarkCompactCollector::Sweeper::GetLateSweepingListSafe(AllocationSpace space) { | 3764 Page* page) { |
| 3777 base::LockGuard<base::Mutex> guard(&mutex_); | 3765 base::LockGuard<base::Mutex> guard(&mutex_); |
| 3778 return late_sweeping_list_[space]; | 3766 sweeping_list_[space].push_back(page); |
| 3779 } | 3767 } |
| 3780 | 3768 |
| 3781 void MarkCompactCollector::StartSweepSpace(PagedSpace* space) { | 3769 void MarkCompactCollector::StartSweepSpace(PagedSpace* space) { |
| 3782 space->ClearStats(); | 3770 space->ClearStats(); |
| 3783 | 3771 |
| 3784 PageIterator it(space); | 3772 PageIterator it(space); |
| 3785 | 3773 |
| 3786 int will_be_swept = 0; | 3774 int will_be_swept = 0; |
| 3787 bool unused_page_present = false; | 3775 bool unused_page_present = false; |
| 3788 | 3776 |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3908 MarkBit mark_bit = Marking::MarkBitFrom(host); | 3896 MarkBit mark_bit = Marking::MarkBitFrom(host); |
| 3909 if (Marking::IsBlack(mark_bit)) { | 3897 if (Marking::IsBlack(mark_bit)) { |
| 3910 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); | 3898 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); |
| 3911 RecordRelocSlot(host, &rinfo, target); | 3899 RecordRelocSlot(host, &rinfo, target); |
| 3912 } | 3900 } |
| 3913 } | 3901 } |
| 3914 } | 3902 } |
| 3915 | 3903 |
| 3916 } // namespace internal | 3904 } // namespace internal |
| 3917 } // namespace v8 | 3905 } // namespace v8 |
| OLD | NEW |