Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(668)

Side by Side Diff: src/heap/mark-compact.cc

Issue 1863983002: 🏄 [heap] Add page evacuation mode for new->old (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Cleanup Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 state_(IDLE), 53 state_(IDLE),
54 #endif 54 #endif
55 marking_parity_(ODD_MARKING_PARITY), 55 marking_parity_(ODD_MARKING_PARITY),
56 was_marked_incrementally_(false), 56 was_marked_incrementally_(false),
57 evacuation_(false), 57 evacuation_(false),
58 heap_(heap), 58 heap_(heap),
59 marking_deque_memory_(NULL), 59 marking_deque_memory_(NULL),
60 marking_deque_memory_committed_(0), 60 marking_deque_memory_committed_(0),
61 code_flusher_(nullptr), 61 code_flusher_(nullptr),
62 have_code_to_deoptimize_(false), 62 have_code_to_deoptimize_(false),
63 sweeping_list_shared_(nullptr),
63 compacting_(false), 64 compacting_(false),
64 sweeping_in_progress_(false), 65 sweeping_in_progress_(false),
65 pending_sweeper_tasks_semaphore_(0), 66 pending_sweeper_tasks_semaphore_(0),
66 pending_compaction_tasks_semaphore_(0) { 67 pending_compaction_tasks_semaphore_(0) {
67 } 68 }
68 69
69 #ifdef VERIFY_HEAP 70 #ifdef VERIFY_HEAP
70 class VerifyMarkingVisitor : public ObjectVisitor { 71 class VerifyMarkingVisitor : public ObjectVisitor {
71 public: 72 public:
72 explicit VerifyMarkingVisitor(Heap* heap) : heap_(heap) {} 73 explicit VerifyMarkingVisitor(Heap* heap) : heap_(heap) {}
(...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after
474 DCHECK_LE(space_to_start_, LAST_PAGED_SPACE); 475 DCHECK_LE(space_to_start_, LAST_PAGED_SPACE);
475 const int offset = space_to_start_ - FIRST_PAGED_SPACE; 476 const int offset = space_to_start_ - FIRST_PAGED_SPACE;
476 const int num_spaces = LAST_PAGED_SPACE - FIRST_PAGED_SPACE + 1; 477 const int num_spaces = LAST_PAGED_SPACE - FIRST_PAGED_SPACE + 1;
477 for (int i = 0; i < num_spaces; i++) { 478 for (int i = 0; i < num_spaces; i++) {
478 const int space_id = FIRST_PAGED_SPACE + ((i + offset) % num_spaces); 479 const int space_id = FIRST_PAGED_SPACE + ((i + offset) % num_spaces);
479 DCHECK_GE(space_id, FIRST_PAGED_SPACE); 480 DCHECK_GE(space_id, FIRST_PAGED_SPACE);
480 DCHECK_LE(space_id, LAST_PAGED_SPACE); 481 DCHECK_LE(space_id, LAST_PAGED_SPACE);
481 heap_->mark_compact_collector()->SweepInParallel( 482 heap_->mark_compact_collector()->SweepInParallel(
482 heap_->paged_space(space_id), 0); 483 heap_->paged_space(space_id), 0);
483 } 484 }
485 std::vector<Page*>* shared_sweeping_list = nullptr;
486 {
487 base::LockGuard<base::Mutex> guard(
488 heap_->mark_compact_collector()->swept_pages_mutex());
489 shared_sweeping_list =
490 heap_->mark_compact_collector()->sweeping_list_shared_;
491 }
492 if (shared_sweeping_list != nullptr) {
493 heap_->mark_compact_collector()->SweepInParallel(*shared_sweeping_list,
494 heap_->old_space(), 0);
495 }
484 heap_->mark_compact_collector()->pending_sweeper_tasks_semaphore_.Signal(); 496 heap_->mark_compact_collector()->pending_sweeper_tasks_semaphore_.Signal();
485 } 497 }
486 498
487 Heap* heap_; 499 Heap* heap_;
488 AllocationSpace space_to_start_; 500 AllocationSpace space_to_start_;
489 501
490 DISALLOW_COPY_AND_ASSIGN(SweeperTask); 502 DISALLOW_COPY_AND_ASSIGN(SweeperTask);
491 }; 503 };
492 504
493 505
494 void MarkCompactCollector::StartSweeperThreads() { 506 void MarkCompactCollector::StartSweeperThreads() {
495 V8::GetCurrentPlatform()->CallOnBackgroundThread( 507 V8::GetCurrentPlatform()->CallOnBackgroundThread(
496 new SweeperTask(heap(), OLD_SPACE), v8::Platform::kShortRunningTask); 508 new SweeperTask(heap(), OLD_SPACE), v8::Platform::kShortRunningTask);
497 V8::GetCurrentPlatform()->CallOnBackgroundThread( 509 V8::GetCurrentPlatform()->CallOnBackgroundThread(
498 new SweeperTask(heap(), CODE_SPACE), v8::Platform::kShortRunningTask); 510 new SweeperTask(heap(), CODE_SPACE), v8::Platform::kShortRunningTask);
499 V8::GetCurrentPlatform()->CallOnBackgroundThread(
500 new SweeperTask(heap(), MAP_SPACE), v8::Platform::kShortRunningTask);
501 } 511 }
502 512
503 513
504 void MarkCompactCollector::SweepOrWaitUntilSweepingCompleted(Page* page) { 514 void MarkCompactCollector::SweepOrWaitUntilSweepingCompleted(Page* page) {
505 PagedSpace* owner = reinterpret_cast<PagedSpace*>(page->owner()); 515 PagedSpace* owner = reinterpret_cast<PagedSpace*>(page->owner());
506 if (!page->SweepingDone()) { 516 if (!page->SweepingDone()) {
507 SweepInParallel(page, owner); 517 SweepInParallel(page, owner);
508 if (!page->SweepingDone()) { 518 if (!page->SweepingDone()) {
509 // We were not able to sweep that page, i.e., a concurrent 519 // We were not able to sweep that page, i.e., a concurrent
510 // sweeper thread currently owns this page. Wait for the sweeper 520 // sweeper thread currently owns this page. Wait for the sweeper
(...skipping 1247 matching lines...) Expand 10 before | Expand all | Expand 10 after
1758 return allocation; 1768 return allocation;
1759 } 1769 }
1760 1770
1761 LocalAllocationBuffer buffer_; 1771 LocalAllocationBuffer buffer_;
1762 AllocationSpace space_to_allocate_; 1772 AllocationSpace space_to_allocate_;
1763 intptr_t promoted_size_; 1773 intptr_t promoted_size_;
1764 intptr_t semispace_copied_size_; 1774 intptr_t semispace_copied_size_;
1765 HashMap* local_pretenuring_feedback_; 1775 HashMap* local_pretenuring_feedback_;
1766 }; 1776 };
1767 1777
1778 class MarkCompactCollector::EvacuateNewSpacePageVisitor final
1779 : public MarkCompactCollector::HeapObjectVisitor {
1780 public:
1781 EvacuateNewSpacePageVisitor() : promoted_size_(0) {}
1782
1783 static void MoveToOldSpace(NewSpacePage* page, PagedSpace* owner) {
1784 page->heap()->new_space()->ReplaceWithEmptyPage(page);
Hannes Payer (out of office) 2016/04/08 10:42:40 Why don't we take care of the new space size at th
Michael Lippautz 2016/04/08 11:30:00 As discussed offline: Let's keep it for now. We ca
1785 Page* new_page = Page::Convert(page, owner);
1786 new_page->SetFlag(Page::FAST_EVACUATION);
1787 }
1788
1789 bool Visit(HeapObject* object) {
1790 promoted_size_ += object->Size();
1791 if (V8_UNLIKELY(object->IsJSArrayBuffer())) {
1792 object->GetHeap()->array_buffer_tracker()->Promote(
1793 JSArrayBuffer::cast(object));
1794 }
1795 RecordMigratedSlotVisitor visitor;
1796 object->IterateBodyFast(&visitor);
1797 return true;
1798 }
1799
1800 intptr_t promoted_size() { return promoted_size_; }
1801
1802 private:
1803 intptr_t promoted_size_;
1804 };
1768 1805
1769 class MarkCompactCollector::EvacuateOldSpaceVisitor final 1806 class MarkCompactCollector::EvacuateOldSpaceVisitor final
1770 : public MarkCompactCollector::EvacuateVisitorBase { 1807 : public MarkCompactCollector::EvacuateVisitorBase {
1771 public: 1808 public:
1772 EvacuateOldSpaceVisitor(Heap* heap, 1809 EvacuateOldSpaceVisitor(Heap* heap,
1773 CompactionSpaceCollection* compaction_spaces) 1810 CompactionSpaceCollection* compaction_spaces)
1774 : EvacuateVisitorBase(heap, compaction_spaces) {} 1811 : EvacuateVisitorBase(heap, compaction_spaces) {}
1775 1812
1776 bool Visit(HeapObject* object) override { 1813 bool Visit(HeapObject* object) override {
1777 CompactionSpace* target_space = compaction_spaces_->Get( 1814 CompactionSpace* target_space = compaction_spaces_->Get(
(...skipping 1145 matching lines...) Expand 10 before | Expand all | Expand 10 after
2923 newspace_evacuation_candidates_.Add(it.next()); 2960 newspace_evacuation_candidates_.Add(it.next());
2924 } 2961 }
2925 new_space->Flip(); 2962 new_space->Flip();
2926 new_space->ResetAllocationInfo(); 2963 new_space->ResetAllocationInfo();
2927 } 2964 }
2928 2965
2929 void MarkCompactCollector::EvacuateNewSpaceEpilogue() { 2966 void MarkCompactCollector::EvacuateNewSpaceEpilogue() {
2930 newspace_evacuation_candidates_.Rewind(0); 2967 newspace_evacuation_candidates_.Rewind(0);
2931 } 2968 }
2932 2969
2933
2934 class MarkCompactCollector::Evacuator : public Malloced { 2970 class MarkCompactCollector::Evacuator : public Malloced {
2935 public: 2971 public:
2972 // NewSpacePages with more live bytes than this threshold qualify for fast
2973 // evacuation.
2974 static int FastEvacuationThreshold() {
2975 return FLAG_page_evacuation_threshold * NewSpacePage::kAllocatableMemory /
2976 100;
2977 }
2978
2936 explicit Evacuator(MarkCompactCollector* collector) 2979 explicit Evacuator(MarkCompactCollector* collector)
2937 : collector_(collector), 2980 : collector_(collector),
2938 compaction_spaces_(collector->heap()), 2981 compaction_spaces_(collector->heap()),
2939 local_pretenuring_feedback_(HashMap::PointersMatch, 2982 local_pretenuring_feedback_(HashMap::PointersMatch,
2940 kInitialLocalPretenuringFeedbackCapacity), 2983 kInitialLocalPretenuringFeedbackCapacity),
2941 new_space_visitor_(collector->heap(), &compaction_spaces_, 2984 evac_new_space_visitor_(collector->heap(), &compaction_spaces_,
2942 &local_pretenuring_feedback_), 2985 &local_pretenuring_feedback_),
2943 old_space_visitor_(collector->heap(), &compaction_spaces_), 2986 evac_new_space_page_visitor_(),
2987 evac_old_space_visitor_(collector->heap(), &compaction_spaces_),
2944 duration_(0.0), 2988 duration_(0.0),
2945 bytes_compacted_(0) {} 2989 bytes_compacted_(0) {}
2946 2990
2947 inline bool EvacuatePage(MemoryChunk* chunk); 2991 inline bool EvacuatePage(MemoryChunk* chunk);
2948 2992
2949 // Merge back locally cached info sequentially. Note that this method needs 2993 // Merge back locally cached info sequentially. Note that this method needs
2950 // to be called from the main thread. 2994 // to be called from the main thread.
2951 inline void Finalize(); 2995 inline void Finalize();
2952 2996
2953 CompactionSpaceCollection* compaction_spaces() { return &compaction_spaces_; } 2997 CompactionSpaceCollection* compaction_spaces() { return &compaction_spaces_; }
2954 2998
2955 private: 2999 private:
2956 static const int kInitialLocalPretenuringFeedbackCapacity = 256; 3000 static const int kInitialLocalPretenuringFeedbackCapacity = 256;
2957 3001
2958 Heap* heap() { return collector_->heap(); } 3002 Heap* heap() { return collector_->heap(); }
2959 3003
2960 void ReportCompactionProgress(double duration, intptr_t bytes_compacted) { 3004 void ReportCompactionProgress(double duration, intptr_t bytes_compacted) {
2961 duration_ += duration; 3005 duration_ += duration;
2962 bytes_compacted_ += bytes_compacted; 3006 bytes_compacted_ += bytes_compacted;
2963 } 3007 }
2964 3008
3009 template <IterationMode mode>
2965 inline bool EvacuateSinglePage(MemoryChunk* p, HeapObjectVisitor* visitor); 3010 inline bool EvacuateSinglePage(MemoryChunk* p, HeapObjectVisitor* visitor);
2966 3011
2967 MarkCompactCollector* collector_; 3012 MarkCompactCollector* collector_;
2968 3013
2969 // Locally cached collector data. 3014 // Locally cached collector data.
2970 CompactionSpaceCollection compaction_spaces_; 3015 CompactionSpaceCollection compaction_spaces_;
2971 HashMap local_pretenuring_feedback_; 3016 HashMap local_pretenuring_feedback_;
2972 3017
2973 // Visitors for the corresponding spaces. 3018 // Visitors for the corresponding spaces.
2974 EvacuateNewSpaceVisitor new_space_visitor_; 3019 EvacuateNewSpaceVisitor evac_new_space_visitor_;
2975 EvacuateOldSpaceVisitor old_space_visitor_; 3020 EvacuateNewSpacePageVisitor evac_new_space_page_visitor_;
3021 EvacuateOldSpaceVisitor evac_old_space_visitor_;
2976 3022
2977 // Book keeping info. 3023 // Book keeping info.
2978 double duration_; 3024 double duration_;
2979 intptr_t bytes_compacted_; 3025 intptr_t bytes_compacted_;
2980 }; 3026 };
2981 3027
3028 template <MarkCompactCollector::IterationMode mode>
2982 bool MarkCompactCollector::Evacuator::EvacuateSinglePage( 3029 bool MarkCompactCollector::Evacuator::EvacuateSinglePage(
2983 MemoryChunk* p, HeapObjectVisitor* visitor) { 3030 MemoryChunk* p, HeapObjectVisitor* visitor) {
2984 bool success = false; 3031 bool success = false;
2985 DCHECK(p->IsEvacuationCandidate() || p->InNewSpace()); 3032 DCHECK(p->IsEvacuationCandidate() || p->InNewSpace() ||
3033 p->IsFlagSet(Page::FAST_EVACUATION));
2986 int saved_live_bytes = p->LiveBytes(); 3034 int saved_live_bytes = p->LiveBytes();
2987 double evacuation_time; 3035 double evacuation_time;
2988 { 3036 {
2989 AlwaysAllocateScope always_allocate(heap()->isolate()); 3037 AlwaysAllocateScope always_allocate(heap()->isolate());
2990 TimedScope timed_scope(&evacuation_time); 3038 TimedScope timed_scope(&evacuation_time);
2991 success = collector_->VisitLiveObjects(p, visitor, kClearMarkbits); 3039 success = collector_->VisitLiveObjects(p, visitor, mode);
2992 } 3040 }
2993 if (FLAG_trace_evacuation) { 3041 if (FLAG_trace_evacuation) {
2994 PrintIsolate(heap()->isolate(), 3042 PrintIsolate(
2995 "evacuation[%p]: page=%p new_space=%d executable=%d " 3043 heap()->isolate(),
2996 "live_bytes=%d time=%f\n", 3044 "evacuation[%p]: page=%p page_evacuation=%d new_space=%d executable=%d "
2997 this, p, p->InNewSpace(), 3045 "live_bytes=%d time=%f\n",
2998 p->IsFlagSet(MemoryChunk::IS_EXECUTABLE), saved_live_bytes, 3046 this, p, mode == kKeepMarking, p->InNewSpace(),
2999 evacuation_time); 3047 p->IsFlagSet(MemoryChunk::IS_EXECUTABLE), saved_live_bytes,
3048 evacuation_time);
3000 } 3049 }
3001 if (success) { 3050 if (success) {
3002 ReportCompactionProgress(evacuation_time, saved_live_bytes); 3051 ReportCompactionProgress(evacuation_time, saved_live_bytes);
3003 } 3052 }
3004 return success; 3053 return success;
3005 } 3054 }
3006 3055
3007 bool MarkCompactCollector::Evacuator::EvacuatePage(MemoryChunk* chunk) { 3056 bool MarkCompactCollector::Evacuator::EvacuatePage(MemoryChunk* chunk) {
3008 bool success = false; 3057 bool success = false;
3009 if (chunk->InNewSpace()) { 3058 if (chunk->InNewSpace()) {
3010 DCHECK_EQ(chunk->concurrent_sweeping_state().Value(), 3059 DCHECK_EQ(chunk->concurrent_sweeping_state().Value(),
3011 NewSpacePage::kSweepingDone); 3060 NewSpacePage::kSweepingDone);
3012 success = EvacuateSinglePage(chunk, &new_space_visitor_); 3061 success =
3062 EvacuateSinglePage<kClearMarkbits>(chunk, &evac_new_space_visitor_);
3013 DCHECK(success); 3063 DCHECK(success);
3014 USE(success); 3064 USE(success);
3015 } else { 3065 } else {
3016 DCHECK(chunk->IsEvacuationCandidate());
3017 DCHECK_EQ(chunk->concurrent_sweeping_state().Value(), Page::kSweepingDone); 3066 DCHECK_EQ(chunk->concurrent_sweeping_state().Value(), Page::kSweepingDone);
3018 success = EvacuateSinglePage(chunk, &old_space_visitor_); 3067 if (chunk->IsFlagSet(MemoryChunk::FAST_EVACUATION)) {
3068 success = EvacuateSinglePage<kKeepMarking>(chunk,
3069 &evac_new_space_page_visitor_);
3070 } else {
3071 DCHECK(chunk->IsEvacuationCandidate());
3072 success =
3073 EvacuateSinglePage<kClearMarkbits>(chunk, &evac_old_space_visitor_);
3074 }
3019 } 3075 }
3020 return success; 3076 return success;
3021 } 3077 }
3022 3078
3023 void MarkCompactCollector::Evacuator::Finalize() { 3079 void MarkCompactCollector::Evacuator::Finalize() {
3024 heap()->old_space()->MergeCompactionSpace(compaction_spaces_.Get(OLD_SPACE)); 3080 heap()->old_space()->MergeCompactionSpace(compaction_spaces_.Get(OLD_SPACE));
3025 heap()->code_space()->MergeCompactionSpace( 3081 heap()->code_space()->MergeCompactionSpace(
3026 compaction_spaces_.Get(CODE_SPACE)); 3082 compaction_spaces_.Get(CODE_SPACE));
3027 heap()->tracer()->AddCompactionEvent(duration_, bytes_compacted_); 3083 heap()->tracer()->AddCompactionEvent(duration_, bytes_compacted_);
3028 heap()->IncrementPromotedObjectsSize(new_space_visitor_.promoted_size()); 3084 heap()->IncrementPromotedObjectsSize(
3085 evac_new_space_visitor_.promoted_size() +
3086 evac_new_space_page_visitor_.promoted_size());
3029 heap()->IncrementSemiSpaceCopiedObjectSize( 3087 heap()->IncrementSemiSpaceCopiedObjectSize(
3030 new_space_visitor_.semispace_copied_size()); 3088 evac_new_space_visitor_.semispace_copied_size());
3031 heap()->IncrementYoungSurvivorsCounter( 3089 heap()->IncrementYoungSurvivorsCounter(
3032 new_space_visitor_.promoted_size() + 3090 evac_new_space_visitor_.promoted_size() +
3033 new_space_visitor_.semispace_copied_size()); 3091 evac_new_space_visitor_.semispace_copied_size() +
3092 evac_new_space_page_visitor_.promoted_size());
3034 heap()->MergeAllocationSitePretenuringFeedback(local_pretenuring_feedback_); 3093 heap()->MergeAllocationSitePretenuringFeedback(local_pretenuring_feedback_);
3035 } 3094 }
3036 3095
3037 int MarkCompactCollector::NumberOfParallelCompactionTasks(int pages, 3096 int MarkCompactCollector::NumberOfParallelCompactionTasks(int pages,
3038 intptr_t live_bytes) { 3097 intptr_t live_bytes) {
3039 if (!FLAG_parallel_compaction) return 1; 3098 if (!FLAG_parallel_compaction) return 1;
3040 // Compute the number of needed tasks based on a target compaction time, the 3099 // Compute the number of needed tasks based on a target compaction time, the
3041 // profiled compaction speed and marked live memory. 3100 // profiled compaction speed and marked live memory.
3042 // 3101 //
3043 // The number of parallel compaction tasks is limited by: 3102 // The number of parallel compaction tasks is limited by:
(...skipping 29 matching lines...) Expand all
3073 3132
3074 static bool ProcessPageInParallel(Heap* heap, PerTaskData evacuator, 3133 static bool ProcessPageInParallel(Heap* heap, PerTaskData evacuator,
3075 MemoryChunk* chunk, PerPageData) { 3134 MemoryChunk* chunk, PerPageData) {
3076 return evacuator->EvacuatePage(chunk); 3135 return evacuator->EvacuatePage(chunk);
3077 } 3136 }
3078 3137
3079 static void FinalizePageSequentially(Heap*, MemoryChunk* chunk, bool success, 3138 static void FinalizePageSequentially(Heap*, MemoryChunk* chunk, bool success,
3080 PerPageData data) { 3139 PerPageData data) {
3081 if (chunk->InNewSpace()) { 3140 if (chunk->InNewSpace()) {
3082 DCHECK(success); 3141 DCHECK(success);
3142 } else if (chunk->IsFlagSet(Page::FAST_EVACUATION)) {
3143 // Nothing to do here, as the page is still owned by the compaction space.
3083 } else { 3144 } else {
3084 Page* p = static_cast<Page*>(chunk); 3145 Page* p = static_cast<Page*>(chunk);
3085 if (success) { 3146 if (success) {
3086 DCHECK(p->IsEvacuationCandidate()); 3147 DCHECK(p->IsEvacuationCandidate());
3087 DCHECK(p->SweepingDone()); 3148 DCHECK(p->SweepingDone());
3088 p->Unlink(); 3149 p->Unlink();
3089 } else { 3150 } else {
3090 // We have partially compacted the page, i.e., some objects may have 3151 // We have partially compacted the page, i.e., some objects may have
3091 // moved, others are still in place. 3152 // moved, others are still in place.
3092 // We need to: 3153 // We need to:
(...skipping 18 matching lines...) Expand all
3111 heap_, heap_->isolate()->cancelable_task_manager()); 3172 heap_, heap_->isolate()->cancelable_task_manager());
3112 3173
3113 int abandoned_pages = 0; 3174 int abandoned_pages = 0;
3114 intptr_t live_bytes = 0; 3175 intptr_t live_bytes = 0;
3115 for (Page* page : evacuation_candidates_) { 3176 for (Page* page : evacuation_candidates_) {
3116 live_bytes += page->LiveBytes(); 3177 live_bytes += page->LiveBytes();
3117 job.AddPage(page, &abandoned_pages); 3178 job.AddPage(page, &abandoned_pages);
3118 } 3179 }
3119 for (NewSpacePage* page : newspace_evacuation_candidates_) { 3180 for (NewSpacePage* page : newspace_evacuation_candidates_) {
3120 live_bytes += page->LiveBytes(); 3181 live_bytes += page->LiveBytes();
3182 if (!page->NeverEvacuate() &&
3183 (page->LiveBytes() > Evacuator::FastEvacuationThreshold()) &&
3184 page->IsFlagSet(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK)) {
3185 EvacuateNewSpacePageVisitor::MoveToOldSpace(page, heap()->old_space());
3186 }
3121 job.AddPage(page, &abandoned_pages); 3187 job.AddPage(page, &abandoned_pages);
3122 } 3188 }
3123 DCHECK_GE(job.NumberOfPages(), 1); 3189 DCHECK_GE(job.NumberOfPages(), 1);
3124 3190
3125 // Used for trace summary. 3191 // Used for trace summary.
3126 double compaction_speed = 0; 3192 double compaction_speed = 0;
3127 if (FLAG_trace_evacuation) { 3193 if (FLAG_trace_evacuation) {
3128 compaction_speed = heap()->tracer()->CompactionSpeedInBytesPerMillisecond(); 3194 compaction_speed = heap()->tracer()->CompactionSpeedInBytesPerMillisecond();
3129 } 3195 }
3130 3196
3131 const int wanted_num_tasks = 3197 const int wanted_num_tasks =
3132 NumberOfParallelCompactionTasks(job.NumberOfPages(), live_bytes); 3198 NumberOfParallelCompactionTasks(job.NumberOfPages(), live_bytes);
3133 Evacuator** evacuators = new Evacuator*[wanted_num_tasks]; 3199 Evacuator** evacuators = new Evacuator*[wanted_num_tasks];
3134 for (int i = 0; i < wanted_num_tasks; i++) { 3200 for (int i = 0; i < wanted_num_tasks; i++) {
3135 evacuators[i] = new Evacuator(this); 3201 evacuators[i] = new Evacuator(this);
3136 } 3202 }
3137 job.Run(wanted_num_tasks, [evacuators](int i) { return evacuators[i]; }); 3203 job.Run(wanted_num_tasks, [evacuators](int i) { return evacuators[i]; });
3138 for (int i = 0; i < wanted_num_tasks; i++) { 3204 for (int i = 0; i < wanted_num_tasks; i++) {
3139 evacuators[i]->Finalize(); 3205 evacuators[i]->Finalize();
3140 delete evacuators[i]; 3206 delete evacuators[i];
3141 } 3207 }
3142 delete[] evacuators; 3208 delete[] evacuators;
3143 3209
3210 bool fast_evac_pages = false;
Hannes Payer (out of office) 2016/04/08 10:42:40 Can you factor this block of code out into a metho
Michael Lippautz 2016/04/08 11:30:00 Done.
3211 std::vector<Page*>* shared_sweep_list = nullptr;
3212 for (MemoryChunk* chunk : newspace_evacuation_candidates_) {
3213 if (chunk->IsFlagSet(Page::FAST_EVACUATION)) {
3214 Page* page = reinterpret_cast<Page*>(chunk);
3215 page->ClearFlag(Page::FAST_EVACUATION);
3216 page->concurrent_sweeping_state().SetValue(Page::kSweepingPending);
3217 PagedSpace* space = static_cast<PagedSpace*>(page->owner());
3218 DCHECK_EQ(space, heap()->old_space());
3219 int to_sweep = page->area_size() - page->LiveBytes();
3220 space->accounting_stats_.ShrinkSpace(to_sweep);
3221 space->UnlinkFreeListCategories(page);
Hannes Payer (out of office) 2016/04/08 10:42:40 New space pages never have free lists. Can you DCH
Michael Lippautz 2016/04/08 11:30:00 Done.
3222 page->ForAllFreeListCategories(
3223 [](FreeListCategory* category) { category->Reset(); });
3224 if (shared_sweep_list == nullptr) {
3225 shared_sweep_list = new std::vector<Page*>();
3226 }
3227 shared_sweep_list->push_back(page);
3228 fast_evac_pages = true;
3229 }
3230 }
3231 if (fast_evac_pages) {
3232 {
3233 base::LockGuard<base::Mutex> guard(swept_pages_mutex());
3234 sweeping_list_shared_ = shared_sweep_list;
3235 }
3236 heap()
3237 ->external_string_table_
3238 .CleanUp<Heap::ExternalStringTable::CleanupMode::kPromoteOnly>();
3239 }
3240 if (FLAG_concurrent_sweeping) {
3241 V8::GetCurrentPlatform()->CallOnBackgroundThread(
3242 new SweeperTask(heap(), MAP_SPACE), v8::Platform::kShortRunningTask);
3243 } else {
3244 if (fast_evac_pages) {
3245 SweepInParallel(*sweeping_list_shared_, heap()->old_space(), 0);
3246 }
3247 }
3248
3144 if (FLAG_trace_evacuation) { 3249 if (FLAG_trace_evacuation) {
3145 PrintIsolate( 3250 PrintIsolate(
3146 isolate(), 3251 isolate(),
3147 "%8.0f ms: evacuation-summary: parallel=%s pages=%d aborted=%d " 3252 "%8.0f ms: evacuation-summary: parallel=%s pages=%d aborted=%d "
3148 "wanted_tasks=%d tasks=%d cores=%d live_bytes=%" V8_PTR_PREFIX 3253 "wanted_tasks=%d tasks=%d cores=%d live_bytes=%" V8_PTR_PREFIX
3149 "d compaction_speed=%.f\n", 3254 "d compaction_speed=%.f\n",
3150 isolate()->time_millis_since_init(), 3255 isolate()->time_millis_since_init(),
3151 FLAG_parallel_compaction ? "yes" : "no", job.NumberOfPages(), 3256 FLAG_parallel_compaction ? "yes" : "no", job.NumberOfPages(),
3152 abandoned_pages, wanted_num_tasks, job.NumberOfTasks(), 3257 abandoned_pages, wanted_num_tasks, job.NumberOfTasks(),
3153 V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads(), 3258 V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads(),
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
3245 if (free_space_mode == ZAP_FREE_SPACE) { 3350 if (free_space_mode == ZAP_FREE_SPACE) {
3246 memset(free_start, 0xcc, size); 3351 memset(free_start, 0xcc, size);
3247 } 3352 }
3248 freed_bytes = space->UnaccountedFree(free_start, size); 3353 freed_bytes = space->UnaccountedFree(free_start, size);
3249 max_freed_bytes = Max(freed_bytes, max_freed_bytes); 3354 max_freed_bytes = Max(freed_bytes, max_freed_bytes);
3250 } 3355 }
3251 p->concurrent_sweeping_state().SetValue(Page::kSweepingDone); 3356 p->concurrent_sweeping_state().SetValue(Page::kSweepingDone);
3252 return FreeList::GuaranteedAllocatable(static_cast<int>(max_freed_bytes)); 3357 return FreeList::GuaranteedAllocatable(static_cast<int>(max_freed_bytes));
3253 } 3358 }
3254 3359
3255
3256 void MarkCompactCollector::InvalidateCode(Code* code) { 3360 void MarkCompactCollector::InvalidateCode(Code* code) {
3257 if (heap_->incremental_marking()->IsCompacting() && 3361 if (heap_->incremental_marking()->IsCompacting() &&
3258 !ShouldSkipEvacuationSlotRecording(code)) { 3362 !ShouldSkipEvacuationSlotRecording(code)) {
3259 DCHECK(compacting_); 3363 DCHECK(compacting_);
3260 3364
3261 // If the object is white than no slots were recorded on it yet. 3365 // If the object is white than no slots were recorded on it yet.
3262 MarkBit mark_bit = Marking::MarkBitFrom(code); 3366 MarkBit mark_bit = Marking::MarkBitFrom(code);
3263 if (Marking::IsWhite(mark_bit)) return; 3367 if (Marking::IsWhite(mark_bit)) return;
3264 3368
3265 // Ignore all slots that might have been recorded in the body of the 3369 // Ignore all slots that might have been recorded in the body of the
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
3465 RememberedSet<OLD_TO_OLD>::IterateTyped( 3569 RememberedSet<OLD_TO_OLD>::IterateTyped(
3466 chunk, [isolate, visitor](SlotType type, Address slot) { 3570 chunk, [isolate, visitor](SlotType type, Address slot) {
3467 UpdateTypedSlot(isolate, visitor, type, slot); 3571 UpdateTypedSlot(isolate, visitor, type, slot);
3468 return REMOVE_SLOT; 3572 return REMOVE_SLOT;
3469 }); 3573 });
3470 } 3574 }
3471 } 3575 }
3472 3576
3473 static void UpdateOldToNewSlot(HeapObject** address, HeapObject* object) { 3577 static void UpdateOldToNewSlot(HeapObject** address, HeapObject* object) {
3474 MapWord map_word = object->map_word(); 3578 MapWord map_word = object->map_word();
3475 // Since we only filter invalid slots in old space, the store buffer can 3579 // There could still be stale pointers in large object space, map space,
3476 // still contain stale pointers in large object and in map spaces. Ignore 3580 // and old space for pages that have been promoted.
3477 // these pointers here.
3478 DCHECK(map_word.IsForwardingAddress() ||
3479 !object->GetHeap()->old_space()->Contains(
3480 reinterpret_cast<Address>(address)));
3481 if (map_word.IsForwardingAddress()) { 3581 if (map_word.IsForwardingAddress()) {
3482 // Update the corresponding slot. 3582 // Update the corresponding slot.
3483 *address = map_word.ToForwardingAddress(); 3583 *address = map_word.ToForwardingAddress();
3484 } 3584 }
3485 } 3585 }
3486 }; 3586 };
3487 3587
3488 int NumberOfPointerUpdateTasks(int pages) { 3588 int NumberOfPointerUpdateTasks(int pages) {
3489 if (!FLAG_parallel_pointer_update) return 1; 3589 if (!FLAG_parallel_pointer_update) return 1;
3490 const int kMaxTasks = 4; 3590 const int kMaxTasks = 4;
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
3606 } 3706 }
3607 evacuation_candidates_.Rewind(0); 3707 evacuation_candidates_.Rewind(0);
3608 compacting_ = false; 3708 compacting_ = false;
3609 heap()->FreeQueuedChunks(); 3709 heap()->FreeQueuedChunks();
3610 } 3710 }
3611 3711
3612 3712
3613 int MarkCompactCollector::SweepInParallel(PagedSpace* space, 3713 int MarkCompactCollector::SweepInParallel(PagedSpace* space,
3614 int required_freed_bytes, 3714 int required_freed_bytes,
3615 int max_pages) { 3715 int max_pages) {
3716 return SweepInParallel(sweeping_list(space), space, required_freed_bytes,
3717 max_pages);
3718 }
3719
3720 int MarkCompactCollector::SweepInParallel(std::vector<Page*>& pages,
3721 PagedSpace* space,
3722 int required_freed_bytes,
3723 int max_pages) {
3616 int max_freed = 0; 3724 int max_freed = 0;
3617 int max_freed_overall = 0; 3725 int max_freed_overall = 0;
3618 int page_count = 0; 3726 int page_count = 0;
3619 for (Page* p : sweeping_list(space)) { 3727 for (Page* p : pages) {
3620 max_freed = SweepInParallel(p, space); 3728 max_freed = SweepInParallel(p, space);
3621 DCHECK(max_freed >= 0); 3729 DCHECK(max_freed >= 0);
3622 if (required_freed_bytes > 0 && max_freed >= required_freed_bytes) { 3730 if (required_freed_bytes > 0 && max_freed >= required_freed_bytes) {
3623 return max_freed; 3731 return max_freed;
3624 } 3732 }
3625 max_freed_overall = Max(max_freed, max_freed_overall); 3733 max_freed_overall = Max(max_freed, max_freed_overall);
3626 page_count++; 3734 page_count++;
3627 if (max_pages > 0 && page_count >= max_pages) { 3735 if (max_pages > 0 && page_count >= max_pages) {
3628 break; 3736 break;
3629 } 3737 }
3630 } 3738 }
3631 return max_freed_overall; 3739 return max_freed_overall;
3632 } 3740 }
3633 3741
3634
3635 int MarkCompactCollector::SweepInParallel(Page* page, PagedSpace* space) { 3742 int MarkCompactCollector::SweepInParallel(Page* page, PagedSpace* space) {
3636 int max_freed = 0; 3743 int max_freed = 0;
3637 if (page->mutex()->TryLock()) { 3744 if (page->mutex()->TryLock()) {
3638 // If this page was already swept in the meantime, we can return here. 3745 // If this page was already swept in the meantime, we can return here.
3639 if (page->concurrent_sweeping_state().Value() != Page::kSweepingPending) { 3746 if (page->concurrent_sweeping_state().Value() != Page::kSweepingPending) {
3640 page->mutex()->Unlock(); 3747 page->mutex()->Unlock();
3641 return 0; 3748 return 0;
3642 } 3749 }
3643 page->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); 3750 page->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress);
3644 if (space->identity() == OLD_SPACE) { 3751 if (space->identity() == OLD_SPACE) {
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
3769 heap_->tracer()->AddSweepingTime(heap_->MonotonicallyIncreasingTimeInMs() - 3876 heap_->tracer()->AddSweepingTime(heap_->MonotonicallyIncreasingTimeInMs() -
3770 start_time); 3877 start_time);
3771 } 3878 }
3772 } 3879 }
3773 3880
3774 3881
3775 void MarkCompactCollector::ParallelSweepSpacesComplete() { 3882 void MarkCompactCollector::ParallelSweepSpacesComplete() {
3776 sweeping_list(heap()->old_space()).clear(); 3883 sweeping_list(heap()->old_space()).clear();
3777 sweeping_list(heap()->code_space()).clear(); 3884 sweeping_list(heap()->code_space()).clear();
3778 sweeping_list(heap()->map_space()).clear(); 3885 sweeping_list(heap()->map_space()).clear();
3886 if (sweeping_list_shared_ != nullptr) {
3887 base::LockGuard<base::Mutex> guard(swept_pages_mutex());
3888 delete sweeping_list_shared_;
3889 sweeping_list_shared_ = nullptr;
3890 }
3779 } 3891 }
3780 3892
3781 Isolate* MarkCompactCollector::isolate() const { return heap_->isolate(); } 3893 Isolate* MarkCompactCollector::isolate() const { return heap_->isolate(); }
3782 3894
3783 3895
3784 void MarkCompactCollector::Initialize() { 3896 void MarkCompactCollector::Initialize() {
3785 MarkCompactMarkingVisitor::Initialize(); 3897 MarkCompactMarkingVisitor::Initialize();
3786 IncrementalMarking::Initialize(); 3898 IncrementalMarking::Initialize();
3787 } 3899 }
3788 3900
(...skipping 17 matching lines...) Expand all
3806 MarkBit mark_bit = Marking::MarkBitFrom(host); 3918 MarkBit mark_bit = Marking::MarkBitFrom(host);
3807 if (Marking::IsBlack(mark_bit)) { 3919 if (Marking::IsBlack(mark_bit)) {
3808 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); 3920 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host);
3809 RecordRelocSlot(host, &rinfo, target); 3921 RecordRelocSlot(host, &rinfo, target);
3810 } 3922 }
3811 } 3923 }
3812 } 3924 }
3813 3925
3814 } // namespace internal 3926 } // namespace internal
3815 } // namespace v8 3927 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698