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

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

Issue 2494723002: [heap] Record pretenuring feedback for moved pages (Closed)
Patch Set: Better DCHECK Created 4 years, 1 month 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
« no previous file with comments | « src/heap/mark-compact.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 1816 matching lines...) Expand 10 before | Expand all | Expand 10 after
1827 return allocation; 1827 return allocation;
1828 } 1828 }
1829 1829
1830 LocalAllocationBuffer buffer_; 1830 LocalAllocationBuffer buffer_;
1831 AllocationSpace space_to_allocate_; 1831 AllocationSpace space_to_allocate_;
1832 intptr_t promoted_size_; 1832 intptr_t promoted_size_;
1833 intptr_t semispace_copied_size_; 1833 intptr_t semispace_copied_size_;
1834 base::HashMap* local_pretenuring_feedback_; 1834 base::HashMap* local_pretenuring_feedback_;
1835 }; 1835 };
1836 1836
1837 template <PageEvacuationMode mode>
1837 class MarkCompactCollector::EvacuateNewSpacePageVisitor final 1838 class MarkCompactCollector::EvacuateNewSpacePageVisitor final
1838 : public MarkCompactCollector::HeapObjectVisitor { 1839 : public MarkCompactCollector::HeapObjectVisitor {
1839 public: 1840 public:
1840 explicit EvacuateNewSpacePageVisitor(Heap* heap) 1841 explicit EvacuateNewSpacePageVisitor(
1841 : heap_(heap), promoted_size_(0), semispace_copied_size_(0) {} 1842 Heap* heap, base::HashMap* local_pretenuring_feedback)
1843 : heap_(heap),
1844 moved_bytes_(0),
1845 local_pretenuring_feedback_(local_pretenuring_feedback) {}
1842 1846
1843 static void MoveToOldSpace(Page* page, PagedSpace* owner) { 1847 static void Move(Page* page, PagedSpace* new_owner = nullptr) {
Hannes Payer (out of office) 2016/11/10 16:09:46 I do not need the both the mode and the new_owner.
Michael Lippautz 2016/11/10 16:20:29 Done.
1844 page->Unlink(); 1848 switch (mode) {
1845 Page* new_page = Page::ConvertNewToOld(page, owner); 1849 case NEW_TO_NEW:
1846 new_page->SetFlag(Page::PAGE_NEW_OLD_PROMOTION); 1850 DCHECK_NULL(new_owner);
1847 } 1851 page->heap()->new_space()->MovePageFromSpaceToSpace(page);
1848 1852 page->SetFlag(Page::PAGE_NEW_NEW_PROMOTION);
1849 static void MoveToToSpace(Page* page) { 1853 break;
1850 page->heap()->new_space()->MovePageFromSpaceToSpace(page); 1854 case NEW_TO_OLD: {
1851 page->SetFlag(Page::PAGE_NEW_NEW_PROMOTION); 1855 page->Unlink();
1856 Page* new_page = Page::ConvertNewToOld(page, new_owner);
1857 new_page->SetFlag(Page::PAGE_NEW_OLD_PROMOTION);
1858 break;
1859 }
1860 }
1852 } 1861 }
1853 1862
1854 inline bool Visit(HeapObject* object) { 1863 inline bool Visit(HeapObject* object) {
1855 RecordMigratedSlotVisitor visitor(heap_->mark_compact_collector()); 1864 heap_->UpdateAllocationSite<Heap::kCached>(object,
1856 object->IterateBodyFast(&visitor); 1865 local_pretenuring_feedback_);
1857 promoted_size_ += object->Size(); 1866 if (mode == NEW_TO_OLD) {
1867 RecordMigratedSlotVisitor visitor(heap_->mark_compact_collector());
1868 object->IterateBodyFast(&visitor);
1869 }
1858 return true; 1870 return true;
1859 } 1871 }
1860 1872
1861 intptr_t promoted_size() { return promoted_size_; } 1873 intptr_t moved_bytes() { return moved_bytes_; }
1862 intptr_t semispace_copied_size() { return semispace_copied_size_; } 1874 void account_moved_bytes(intptr_t bytes) { moved_bytes_ += bytes; }
1863
1864 void account_semispace_copied(intptr_t copied) {
1865 semispace_copied_size_ += copied;
1866 }
1867 1875
1868 private: 1876 private:
1869 Heap* heap_; 1877 Heap* heap_;
1870 intptr_t promoted_size_; 1878 intptr_t moved_bytes_;
1871 intptr_t semispace_copied_size_; 1879 base::HashMap* local_pretenuring_feedback_;
1872 }; 1880 };
1873 1881
1874 class MarkCompactCollector::EvacuateOldSpaceVisitor final 1882 class MarkCompactCollector::EvacuateOldSpaceVisitor final
1875 : public MarkCompactCollector::EvacuateVisitorBase { 1883 : public MarkCompactCollector::EvacuateVisitorBase {
1876 public: 1884 public:
1877 EvacuateOldSpaceVisitor(Heap* heap, 1885 EvacuateOldSpaceVisitor(Heap* heap,
1878 CompactionSpaceCollection* compaction_spaces) 1886 CompactionSpaceCollection* compaction_spaces)
1879 : EvacuateVisitorBase(heap, compaction_spaces) {} 1887 : EvacuateVisitorBase(heap, compaction_spaces) {}
1880 1888
1881 inline bool Visit(HeapObject* object) override { 1889 inline bool Visit(HeapObject* object) override {
(...skipping 1036 matching lines...) Expand 10 before | Expand all | Expand 10 after
2918 return FLAG_page_promotion_threshold * Page::kAllocatableMemory / 100; 2926 return FLAG_page_promotion_threshold * Page::kAllocatableMemory / 100;
2919 return Page::kAllocatableMemory + kPointerSize; 2927 return Page::kAllocatableMemory + kPointerSize;
2920 } 2928 }
2921 2929
2922 explicit Evacuator(MarkCompactCollector* collector) 2930 explicit Evacuator(MarkCompactCollector* collector)
2923 : collector_(collector), 2931 : collector_(collector),
2924 compaction_spaces_(collector->heap()), 2932 compaction_spaces_(collector->heap()),
2925 local_pretenuring_feedback_(kInitialLocalPretenuringFeedbackCapacity), 2933 local_pretenuring_feedback_(kInitialLocalPretenuringFeedbackCapacity),
2926 new_space_visitor_(collector->heap(), &compaction_spaces_, 2934 new_space_visitor_(collector->heap(), &compaction_spaces_,
2927 &local_pretenuring_feedback_), 2935 &local_pretenuring_feedback_),
2928 new_space_page_visitor(collector->heap()), 2936 new_to_new_page_visitor_(collector->heap(),
2937 &local_pretenuring_feedback_),
2938 new_to_old_page_visitor_(collector->heap(),
2939 &local_pretenuring_feedback_),
2940
2929 old_space_visitor_(collector->heap(), &compaction_spaces_), 2941 old_space_visitor_(collector->heap(), &compaction_spaces_),
2930 duration_(0.0), 2942 duration_(0.0),
2931 bytes_compacted_(0) {} 2943 bytes_compacted_(0) {}
2932 2944
2933 inline bool EvacuatePage(Page* chunk); 2945 inline bool EvacuatePage(Page* chunk);
2934 2946
2935 // Merge back locally cached info sequentially. Note that this method needs 2947 // Merge back locally cached info sequentially. Note that this method needs
2936 // to be called from the main thread. 2948 // to be called from the main thread.
2937 inline void Finalize(); 2949 inline void Finalize();
2938 2950
(...skipping 10 matching lines...) Expand all
2949 } 2961 }
2950 2962
2951 MarkCompactCollector* collector_; 2963 MarkCompactCollector* collector_;
2952 2964
2953 // Locally cached collector data. 2965 // Locally cached collector data.
2954 CompactionSpaceCollection compaction_spaces_; 2966 CompactionSpaceCollection compaction_spaces_;
2955 base::HashMap local_pretenuring_feedback_; 2967 base::HashMap local_pretenuring_feedback_;
2956 2968
2957 // Visitors for the corresponding spaces. 2969 // Visitors for the corresponding spaces.
2958 EvacuateNewSpaceVisitor new_space_visitor_; 2970 EvacuateNewSpaceVisitor new_space_visitor_;
2959 EvacuateNewSpacePageVisitor new_space_page_visitor; 2971 EvacuateNewSpacePageVisitor<PageEvacuationMode::NEW_TO_NEW>
2972 new_to_new_page_visitor_;
2973 EvacuateNewSpacePageVisitor<PageEvacuationMode::NEW_TO_OLD>
2974 new_to_old_page_visitor_;
2960 EvacuateOldSpaceVisitor old_space_visitor_; 2975 EvacuateOldSpaceVisitor old_space_visitor_;
2961 2976
2962 // Book keeping info. 2977 // Book keeping info.
2963 double duration_; 2978 double duration_;
2964 intptr_t bytes_compacted_; 2979 intptr_t bytes_compacted_;
2965 }; 2980 };
2966 2981
2967 bool MarkCompactCollector::Evacuator::EvacuatePage(Page* page) { 2982 bool MarkCompactCollector::Evacuator::EvacuatePage(Page* page) {
2968 bool success = false; 2983 bool success = false;
2969 DCHECK(page->SweepingDone()); 2984 DCHECK(page->SweepingDone());
2970 int saved_live_bytes = page->LiveBytes(); 2985 int saved_live_bytes = page->LiveBytes();
2971 double evacuation_time = 0.0; 2986 double evacuation_time = 0.0;
2972 Heap* heap = page->heap(); 2987 Heap* heap = page->heap();
2973 { 2988 {
2974 AlwaysAllocateScope always_allocate(heap->isolate()); 2989 AlwaysAllocateScope always_allocate(heap->isolate());
2975 TimedScope timed_scope(&evacuation_time); 2990 TimedScope timed_scope(&evacuation_time);
2976 switch (ComputeEvacuationMode(page)) { 2991 switch (ComputeEvacuationMode(page)) {
2977 case kObjectsNewToOld: 2992 case kObjectsNewToOld:
2978 success = collector_->VisitLiveObjects(page, &new_space_visitor_, 2993 success = collector_->VisitLiveObjects(page, &new_space_visitor_,
2979 kClearMarkbits); 2994 kClearMarkbits);
2995 DCHECK(success);
2980 ArrayBufferTracker::ProcessBuffers( 2996 ArrayBufferTracker::ProcessBuffers(
2981 page, ArrayBufferTracker::kUpdateForwardedRemoveOthers); 2997 page, ArrayBufferTracker::kUpdateForwardedRemoveOthers);
2982 DCHECK(success);
2983 break; 2998 break;
2984 case kPageNewToOld: 2999 case kPageNewToOld:
2985 success = collector_->VisitLiveObjects(page, &new_space_page_visitor, 3000 success = collector_->VisitLiveObjects(page, &new_to_old_page_visitor_,
2986 kKeepMarking); 3001 kKeepMarking);
3002 DCHECK(success);
3003 new_to_old_page_visitor_.account_moved_bytes(page->LiveBytes());
2987 // ArrayBufferTracker will be updated during sweeping. 3004 // ArrayBufferTracker will be updated during sweeping.
2988 DCHECK(success);
2989 break; 3005 break;
2990 case kPageNewToNew: 3006 case kPageNewToNew:
2991 new_space_page_visitor.account_semispace_copied(page->LiveBytes()); 3007 success = collector_->VisitLiveObjects(page, &new_to_new_page_visitor_,
3008 kKeepMarking);
3009 new_to_new_page_visitor_.account_moved_bytes(page->LiveBytes());
3010 DCHECK(success);
Hannes Payer (out of office) 2016/11/10 16:09:46 move up DCHECK one line to be in sync with the pre
Michael Lippautz 2016/11/10 16:20:29 Done.
2992 // ArrayBufferTracker will be updated during sweeping. 3011 // ArrayBufferTracker will be updated during sweeping.
2993 success = true;
2994 break; 3012 break;
2995 case kObjectsOldToOld: 3013 case kObjectsOldToOld:
2996 success = collector_->VisitLiveObjects(page, &old_space_visitor_, 3014 success = collector_->VisitLiveObjects(page, &old_space_visitor_,
2997 kClearMarkbits); 3015 kClearMarkbits);
2998 if (!success) { 3016 if (!success) {
2999 // Aborted compaction page. We have to record slots here, since we 3017 // Aborted compaction page. We have to record slots here, since we
3000 // might not have recorded them in first place. 3018 // might not have recorded them in first place.
3001 // Note: We mark the page as aborted here to be able to record slots 3019 // Note: We mark the page as aborted here to be able to record slots
3002 // for code objects in |RecordMigratedSlotVisitor|. 3020 // for code objects in |RecordMigratedSlotVisitor|.
3003 page->SetFlag(Page::COMPACTION_WAS_ABORTED); 3021 page->SetFlag(Page::COMPACTION_WAS_ABORTED);
3004 EvacuateRecordOnlyVisitor record_visitor(collector_->heap()); 3022 EvacuateRecordOnlyVisitor record_visitor(collector_->heap());
3005 success = 3023 success =
3006 collector_->VisitLiveObjects(page, &record_visitor, kKeepMarking); 3024 collector_->VisitLiveObjects(page, &record_visitor, kKeepMarking);
3007 ArrayBufferTracker::ProcessBuffers( 3025 ArrayBufferTracker::ProcessBuffers(
3008 page, ArrayBufferTracker::kUpdateForwardedKeepOthers); 3026 page, ArrayBufferTracker::kUpdateForwardedKeepOthers);
3009 DCHECK(success); 3027 DCHECK(success);
3010 // We need to return failure here to indicate that we want this page 3028 // We need to return failure here to indicate that we want this page
3011 // added to the sweeper. 3029 // added to the sweeper.
3012 success = false; 3030 success = false;
3013 } else { 3031 } else {
3014 ArrayBufferTracker::ProcessBuffers( 3032 ArrayBufferTracker::ProcessBuffers(
3015 page, ArrayBufferTracker::kUpdateForwardedRemoveOthers); 3033 page, ArrayBufferTracker::kUpdateForwardedRemoveOthers);
3016 } 3034 }
3017 break; 3035 break;
3018 default:
3019 UNREACHABLE();
3020 } 3036 }
3021 } 3037 }
3022 ReportCompactionProgress(evacuation_time, saved_live_bytes); 3038 ReportCompactionProgress(evacuation_time, saved_live_bytes);
3023 if (FLAG_trace_evacuation) { 3039 if (FLAG_trace_evacuation) {
3024 PrintIsolate(heap->isolate(), 3040 PrintIsolate(heap->isolate(),
3025 "evacuation[%p]: page=%p new_space=%d " 3041 "evacuation[%p]: page=%p new_space=%d "
3026 "page_evacuation=%d executable=%d contains_age_mark=%d " 3042 "page_evacuation=%d executable=%d contains_age_mark=%d "
3027 "live_bytes=%d time=%f\n", 3043 "live_bytes=%d time=%f\n",
3028 static_cast<void*>(this), static_cast<void*>(page), 3044 static_cast<void*>(this), static_cast<void*>(page),
3029 page->InNewSpace(), 3045 page->InNewSpace(),
3030 page->IsFlagSet(Page::PAGE_NEW_OLD_PROMOTION) || 3046 page->IsFlagSet(Page::PAGE_NEW_OLD_PROMOTION) ||
3031 page->IsFlagSet(Page::PAGE_NEW_NEW_PROMOTION), 3047 page->IsFlagSet(Page::PAGE_NEW_NEW_PROMOTION),
3032 page->IsFlagSet(MemoryChunk::IS_EXECUTABLE), 3048 page->IsFlagSet(MemoryChunk::IS_EXECUTABLE),
3033 page->Contains(heap->new_space()->age_mark()), 3049 page->Contains(heap->new_space()->age_mark()),
3034 saved_live_bytes, evacuation_time); 3050 saved_live_bytes, evacuation_time);
3035 } 3051 }
3036 return success; 3052 return success;
3037 } 3053 }
3038 3054
3039 void MarkCompactCollector::Evacuator::Finalize() { 3055 void MarkCompactCollector::Evacuator::Finalize() {
3040 heap()->old_space()->MergeCompactionSpace(compaction_spaces_.Get(OLD_SPACE)); 3056 heap()->old_space()->MergeCompactionSpace(compaction_spaces_.Get(OLD_SPACE));
3041 heap()->code_space()->MergeCompactionSpace( 3057 heap()->code_space()->MergeCompactionSpace(
3042 compaction_spaces_.Get(CODE_SPACE)); 3058 compaction_spaces_.Get(CODE_SPACE));
3043 heap()->tracer()->AddCompactionEvent(duration_, bytes_compacted_); 3059 heap()->tracer()->AddCompactionEvent(duration_, bytes_compacted_);
3044 heap()->IncrementPromotedObjectsSize(new_space_visitor_.promoted_size() + 3060 heap()->IncrementPromotedObjectsSize(new_space_visitor_.promoted_size() +
3045 new_space_page_visitor.promoted_size()); 3061 new_to_old_page_visitor_.moved_bytes());
3046 heap()->IncrementSemiSpaceCopiedObjectSize( 3062 heap()->IncrementSemiSpaceCopiedObjectSize(
3047 new_space_visitor_.semispace_copied_size() + 3063 new_space_visitor_.semispace_copied_size() +
3048 new_space_page_visitor.semispace_copied_size()); 3064 new_to_new_page_visitor_.moved_bytes());
3049 heap()->IncrementYoungSurvivorsCounter( 3065 heap()->IncrementYoungSurvivorsCounter(
3050 new_space_visitor_.promoted_size() + 3066 new_space_visitor_.promoted_size() +
3051 new_space_visitor_.semispace_copied_size() + 3067 new_space_visitor_.semispace_copied_size() +
3052 new_space_page_visitor.promoted_size() + 3068 new_to_old_page_visitor_.moved_bytes() +
3053 new_space_page_visitor.semispace_copied_size()); 3069 new_to_new_page_visitor_.moved_bytes());
3054 heap()->MergeAllocationSitePretenuringFeedback(local_pretenuring_feedback_); 3070 heap()->MergeAllocationSitePretenuringFeedback(local_pretenuring_feedback_);
3055 } 3071 }
3056 3072
3057 int MarkCompactCollector::NumberOfParallelCompactionTasks(int pages, 3073 int MarkCompactCollector::NumberOfParallelCompactionTasks(int pages,
3058 intptr_t live_bytes) { 3074 intptr_t live_bytes) {
3059 if (!FLAG_parallel_compaction) return 1; 3075 if (!FLAG_parallel_compaction) return 1;
3060 // Compute the number of needed tasks based on a target compaction time, the 3076 // Compute the number of needed tasks based on a target compaction time, the
3061 // profiled compaction speed and marked live memory. 3077 // profiled compaction speed and marked live memory.
3062 // 3078 //
3063 // The number of parallel compaction tasks is limited by: 3079 // The number of parallel compaction tasks is limited by:
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
3140 } 3156 }
3141 3157
3142 const bool reduce_memory = heap()->ShouldReduceMemory(); 3158 const bool reduce_memory = heap()->ShouldReduceMemory();
3143 const Address age_mark = heap()->new_space()->age_mark(); 3159 const Address age_mark = heap()->new_space()->age_mark();
3144 for (Page* page : newspace_evacuation_candidates_) { 3160 for (Page* page : newspace_evacuation_candidates_) {
3145 live_bytes += page->LiveBytes(); 3161 live_bytes += page->LiveBytes();
3146 if (!reduce_memory && !page->NeverEvacuate() && 3162 if (!reduce_memory && !page->NeverEvacuate() &&
3147 (page->LiveBytes() > Evacuator::PageEvacuationThreshold()) && 3163 (page->LiveBytes() > Evacuator::PageEvacuationThreshold()) &&
3148 !page->Contains(age_mark)) { 3164 !page->Contains(age_mark)) {
3149 if (page->IsFlagSet(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK)) { 3165 if (page->IsFlagSet(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK)) {
3150 EvacuateNewSpacePageVisitor::MoveToOldSpace(page, heap()->old_space()); 3166 EvacuateNewSpacePageVisitor<NEW_TO_OLD>::Move(page,
3167 heap()->old_space());
3151 } else { 3168 } else {
3152 EvacuateNewSpacePageVisitor::MoveToToSpace(page); 3169 EvacuateNewSpacePageVisitor<NEW_TO_NEW>::Move(page);
3153 } 3170 }
3154 } 3171 }
3155 3172
3156 job.AddPage(page, &abandoned_pages); 3173 job.AddPage(page, &abandoned_pages);
3157 } 3174 }
3158 DCHECK_GE(job.NumberOfPages(), 1); 3175 DCHECK_GE(job.NumberOfPages(), 1);
3159 3176
3160 // Used for trace summary. 3177 // Used for trace summary.
3161 double compaction_speed = 0; 3178 double compaction_speed = 0;
3162 if (FLAG_trace_evacuation) { 3179 if (FLAG_trace_evacuation) {
(...skipping 758 matching lines...) Expand 10 before | Expand all | Expand 10 after
3921 // The target is always in old space, we don't have to record the slot in 3938 // The target is always in old space, we don't have to record the slot in
3922 // the old-to-new remembered set. 3939 // the old-to-new remembered set.
3923 DCHECK(!heap()->InNewSpace(target)); 3940 DCHECK(!heap()->InNewSpace(target));
3924 RecordRelocSlot(host, &rinfo, target); 3941 RecordRelocSlot(host, &rinfo, target);
3925 } 3942 }
3926 } 3943 }
3927 } 3944 }
3928 3945
3929 } // namespace internal 3946 } // namespace internal
3930 } // namespace v8 3947 } // namespace v8
OLDNEW
« no previous file with comments | « src/heap/mark-compact.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698