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 |