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

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

Issue 1891683002: Reland of "[heap] Better integrate handling of aborted compaction pages" (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: fixed 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
« no previous file with comments | « src/heap/mark-compact.h ('k') | src/heap/spaces-inl.h » ('j') | 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 1800 matching lines...) Expand 10 before | Expand all | Expand 10 after
1811 Page::FromAddress(object->address())->owner()->identity()); 1811 Page::FromAddress(object->address())->owner()->identity());
1812 HeapObject* target_object = nullptr; 1812 HeapObject* target_object = nullptr;
1813 if (TryEvacuateObject(target_space, object, &target_object)) { 1813 if (TryEvacuateObject(target_space, object, &target_object)) {
1814 DCHECK(object->map_word().IsForwardingAddress()); 1814 DCHECK(object->map_word().IsForwardingAddress());
1815 return true; 1815 return true;
1816 } 1816 }
1817 return false; 1817 return false;
1818 } 1818 }
1819 }; 1819 };
1820 1820
1821 class MarkCompactCollector::EvacuateRecordOnlyVisitor final
1822 : public MarkCompactCollector::HeapObjectVisitor {
1823 public:
1824 explicit EvacuateRecordOnlyVisitor(AllocationSpace space) : space_(space) {}
1825
1826 inline bool Visit(HeapObject* object) {
1827 if (space_ == OLD_SPACE) {
1828 RecordMigratedSlotVisitor visitor;
1829 object->IterateBody(&visitor);
1830 } else {
1831 DCHECK_EQ(space_, CODE_SPACE);
1832 // Add a typed slot for the whole code object.
1833 RememberedSet<OLD_TO_OLD>::InsertTyped(
Michael Lippautz 2016/04/14 07:50:11 We also need to record within CODE_SPACE. I am usi
1834 Page::FromAddress(object->address()), RELOCATED_CODE_OBJECT,
1835 object->address());
1836 }
1837 return true;
1838 }
1839
1840 private:
1841 AllocationSpace space_;
1842 };
1821 1843
1822 void MarkCompactCollector::DiscoverGreyObjectsInSpace(PagedSpace* space) { 1844 void MarkCompactCollector::DiscoverGreyObjectsInSpace(PagedSpace* space) {
1823 PageIterator it(space); 1845 PageIterator it(space);
1824 while (it.has_next()) { 1846 while (it.has_next()) {
1825 Page* p = it.next(); 1847 Page* p = it.next();
1826 if (!p->IsFlagSet(Page::BLACK_PAGE)) { 1848 if (!p->IsFlagSet(Page::BLACK_PAGE)) {
1827 DiscoverGreyObjectsOnPage(p); 1849 DiscoverGreyObjectsOnPage(p);
1828 } 1850 }
1829 if (marking_deque()->IsFull()) return; 1851 if (marking_deque()->IsFull()) return;
1830 } 1852 }
(...skipping 1254 matching lines...) Expand 10 before | Expand all | Expand 10 after
3085 if (chunk->InNewSpace()) { 3107 if (chunk->InNewSpace()) {
3086 DCHECK_EQ(chunk->concurrent_sweeping_state().Value(), 3108 DCHECK_EQ(chunk->concurrent_sweeping_state().Value(),
3087 NewSpacePage::kSweepingDone); 3109 NewSpacePage::kSweepingDone);
3088 success = EvacuateSinglePage<kClearMarkbits>(chunk, &new_space_visitor_); 3110 success = EvacuateSinglePage<kClearMarkbits>(chunk, &new_space_visitor_);
3089 DCHECK(success); 3111 DCHECK(success);
3090 USE(success); 3112 USE(success);
3091 } else { 3113 } else {
3092 DCHECK(chunk->IsEvacuationCandidate()); 3114 DCHECK(chunk->IsEvacuationCandidate());
3093 DCHECK_EQ(chunk->concurrent_sweeping_state().Value(), Page::kSweepingDone); 3115 DCHECK_EQ(chunk->concurrent_sweeping_state().Value(), Page::kSweepingDone);
3094 success = EvacuateSinglePage<kClearMarkbits>(chunk, &old_space_visitor_); 3116 success = EvacuateSinglePage<kClearMarkbits>(chunk, &old_space_visitor_);
3117 if (!success) {
3118 // Aborted compaction page. We can record slots here to have them
3119 // processed in parallel later on.
3120 EvacuateRecordOnlyVisitor record_visitor(chunk->owner()->identity());
3121 success = EvacuateSinglePage<kKeepMarking>(chunk, &record_visitor);
3122 DCHECK(success);
3123 USE(success);
3124 // We need to return failure here to indicate that we want this page added
3125 // to the sweeper.
3126 return false;
3127 }
3095 } 3128 }
3096 return success; 3129 return success;
3097 } 3130 }
3098 3131
3099 void MarkCompactCollector::Evacuator::Finalize() { 3132 void MarkCompactCollector::Evacuator::Finalize() {
3100 heap()->old_space()->MergeCompactionSpace(compaction_spaces_.Get(OLD_SPACE)); 3133 heap()->old_space()->MergeCompactionSpace(compaction_spaces_.Get(OLD_SPACE));
3101 heap()->code_space()->MergeCompactionSpace( 3134 heap()->code_space()->MergeCompactionSpace(
3102 compaction_spaces_.Get(CODE_SPACE)); 3135 compaction_spaces_.Get(CODE_SPACE));
3103 heap()->tracer()->AddCompactionEvent(duration_, bytes_compacted_); 3136 heap()->tracer()->AddCompactionEvent(duration_, bytes_compacted_);
3104 heap()->IncrementPromotedObjectsSize(new_space_visitor_.promoted_size()); 3137 heap()->IncrementPromotedObjectsSize(new_space_visitor_.promoted_size());
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
3145 typedef int* PerPageData; // Pointer to number of aborted pages. 3178 typedef int* PerPageData; // Pointer to number of aborted pages.
3146 typedef MarkCompactCollector::Evacuator* PerTaskData; 3179 typedef MarkCompactCollector::Evacuator* PerTaskData;
3147 3180
3148 static const bool NeedSequentialFinalization = true; 3181 static const bool NeedSequentialFinalization = true;
3149 3182
3150 static bool ProcessPageInParallel(Heap* heap, PerTaskData evacuator, 3183 static bool ProcessPageInParallel(Heap* heap, PerTaskData evacuator,
3151 MemoryChunk* chunk, PerPageData) { 3184 MemoryChunk* chunk, PerPageData) {
3152 return evacuator->EvacuatePage(chunk); 3185 return evacuator->EvacuatePage(chunk);
3153 } 3186 }
3154 3187
3155 static void FinalizePageSequentially(Heap*, MemoryChunk* chunk, bool success, 3188 static void FinalizePageSequentially(Heap* heap, MemoryChunk* chunk,
3156 PerPageData data) { 3189 bool success, PerPageData data) {
3157 if (chunk->InNewSpace()) { 3190 if (chunk->InNewSpace()) {
3158 DCHECK(success); 3191 DCHECK(success);
3159 } else { 3192 } else {
3160 Page* p = static_cast<Page*>(chunk); 3193 Page* p = static_cast<Page*>(chunk);
3161 if (success) { 3194 if (success) {
3162 DCHECK(p->IsEvacuationCandidate()); 3195 DCHECK(p->IsEvacuationCandidate());
3163 DCHECK(p->SweepingDone()); 3196 DCHECK(p->SweepingDone());
3164 p->Unlink(); 3197 p->Unlink();
3165 } else { 3198 } else {
3166 // We have partially compacted the page, i.e., some objects may have 3199 // We have partially compacted the page, i.e., some objects may have
3167 // moved, others are still in place. 3200 // moved, others are still in place.
3168 // We need to:
3169 // - Leave the evacuation candidate flag for later processing of slots
3170 // buffer entries.
3171 // - Leave the slots buffer there for processing of entries added by
3172 // the write barrier.
3173 // - Rescan the page as slot recording in the migration buffer only
3174 // happens upon moving (which we potentially didn't do).
3175 // - Leave the page in the list of pages of a space since we could not
3176 // fully evacuate it.
3177 DCHECK(p->IsEvacuationCandidate());
3178 p->SetFlag(Page::COMPACTION_WAS_ABORTED); 3201 p->SetFlag(Page::COMPACTION_WAS_ABORTED);
3202 p->ClearEvacuationCandidate();
3203 // Slots have already been recorded so we just need to add it to the
3204 // sweeper.
Michael Lippautz 2016/04/14 07:50:11 We cannot add the page to the sweeper here because
3179 *data += 1; 3205 *data += 1;
3180 } 3206 }
3181 } 3207 }
3182 } 3208 }
3183 }; 3209 };
3184 3210
3185 void MarkCompactCollector::EvacuatePagesInParallel() { 3211 void MarkCompactCollector::EvacuatePagesInParallel() {
3186 PageParallelJob<EvacuationJobTraits> job( 3212 PageParallelJob<EvacuationJobTraits> job(
3187 heap_, heap_->isolate()->cancelable_task_manager()); 3213 heap_, heap_->isolate()->cancelable_task_manager());
3188 3214
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
3412 object->IterateBody(map->instance_type(), size, visitor); 3438 object->IterateBody(map->instance_type(), size, visitor);
3413 } 3439 }
3414 } 3440 }
3415 3441
3416 void MarkCompactCollector::Sweeper::AddSweptPageSafe(PagedSpace* space, 3442 void MarkCompactCollector::Sweeper::AddSweptPageSafe(PagedSpace* space,
3417 Page* page) { 3443 Page* page) {
3418 base::LockGuard<base::Mutex> guard(&mutex_); 3444 base::LockGuard<base::Mutex> guard(&mutex_);
3419 swept_list_[space->identity()].Add(page); 3445 swept_list_[space->identity()].Add(page);
3420 } 3446 }
3421 3447
3422 void MarkCompactCollector::SweepAbortedPages() {
3423 // Second pass on aborted pages.
3424 for (Page* p : evacuation_candidates_) {
3425 if (p->IsFlagSet(Page::COMPACTION_WAS_ABORTED)) {
3426 p->ClearFlag(MemoryChunk::COMPACTION_WAS_ABORTED);
3427 p->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress);
3428 PagedSpace* space = static_cast<PagedSpace*>(p->owner());
3429 switch (space->identity()) {
3430 case OLD_SPACE:
3431 Sweeper::RawSweep<Sweeper::SWEEP_ONLY, Sweeper::SWEEP_ON_MAIN_THREAD,
3432 Sweeper::IGNORE_SKIP_LIST,
3433 Sweeper::IGNORE_FREE_SPACE>(space, p, nullptr);
3434 break;
3435 case CODE_SPACE:
3436 if (FLAG_zap_code_space) {
3437 Sweeper::RawSweep<
3438 Sweeper::SWEEP_ONLY, Sweeper::SWEEP_ON_MAIN_THREAD,
3439 Sweeper::REBUILD_SKIP_LIST, Sweeper::ZAP_FREE_SPACE>(space, p,
3440 nullptr);
3441 } else {
3442 Sweeper::RawSweep<
3443 Sweeper::SWEEP_ONLY, Sweeper::SWEEP_ON_MAIN_THREAD,
3444 Sweeper::REBUILD_SKIP_LIST, Sweeper::IGNORE_FREE_SPACE>(
3445 space, p, nullptr);
3446 }
3447 break;
3448 default:
3449 UNREACHABLE();
3450 break;
3451 }
3452 sweeper().AddSweptPageSafe(space, p);
3453 }
3454 }
3455 }
3456
3457
3458 void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { 3448 void MarkCompactCollector::EvacuateNewSpaceAndCandidates() {
3459 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE); 3449 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE);
3460 Heap::RelocationLock relocation_lock(heap()); 3450 Heap::RelocationLock relocation_lock(heap());
3461 3451
3462 { 3452 {
3463 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE_COPY); 3453 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE_COPY);
3464 EvacuationScope evacuation_scope(this); 3454 EvacuationScope evacuation_scope(this);
3465 3455
3466 EvacuateNewSpacePrologue(); 3456 EvacuateNewSpacePrologue();
3467 EvacuatePagesInParallel(); 3457 EvacuatePagesInParallel();
3468 EvacuateNewSpaceEpilogue(); 3458 EvacuateNewSpaceEpilogue();
3469 heap()->new_space()->set_age_mark(heap()->new_space()->top()); 3459 heap()->new_space()->set_age_mark(heap()->new_space()->top());
3470 } 3460 }
3471 3461
3472 UpdatePointersAfterEvacuation(); 3462 UpdatePointersAfterEvacuation();
3473 3463
3474 // Give pages that are queued to be freed back to the OS. Note that filtering 3464 // Give pages that are queued to be freed back to the OS. Note that filtering
3475 // slots only handles old space (for unboxed doubles), and thus map space can 3465 // slots only handles old space (for unboxed doubles), and thus map space can
3476 // still contain stale pointers. We only free the chunks after pointer updates 3466 // still contain stale pointers. We only free the chunks after pointer updates
3477 // to still have access to page headers. 3467 // to still have access to page headers.
3478 heap()->FreeQueuedChunks(); 3468 heap()->FreeQueuedChunks();
3479 3469
3480 { 3470 {
3481 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE_CLEAN_UP); 3471 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE_CLEAN_UP);
3482 // After updating all pointers, we can finally sweep the aborted pages, 3472
3483 // effectively overriding any forward pointers. 3473 for (Page* p : evacuation_candidates_) {
Michael Lippautz 2016/04/14 07:50:11 Moving this part to MC_EVACUATE_CLEAN_UP as it has
3484 SweepAbortedPages(); 3474 // Important: skip list should be cleared only after roots were updated
3475 // because root iteration traverses the stack and might have to find
3476 // code objects from non-updated pc pointing into evacuation candidate.
3477 SkipList* list = p->skip_list();
3478 if (list != NULL) list->Clear();
3479 if (p->IsFlagSet(Page::COMPACTION_WAS_ABORTED)) {
3480 sweeper().AddLatePage(p->owner()->identity(), p);
3481 p->ClearFlag(Page::COMPACTION_WAS_ABORTED);
3482 }
3483 }
3485 3484
3486 // EvacuateNewSpaceAndCandidates iterates over new space objects and for 3485 // EvacuateNewSpaceAndCandidates iterates over new space objects and for
3487 // ArrayBuffers either re-registers them as live or promotes them. This is 3486 // ArrayBuffers either re-registers them as live or promotes them. This is
3488 // needed to properly free them. 3487 // needed to properly free them.
3489 heap()->array_buffer_tracker()->FreeDead(false); 3488 heap()->array_buffer_tracker()->FreeDead(false);
3490 3489
3491 // Deallocate evacuated candidate pages. 3490 // Deallocate evacuated candidate pages.
3492 ReleaseEvacuationCandidates(); 3491 ReleaseEvacuationCandidates();
3493 } 3492 }
3494 3493
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
3630 3629
3631 { 3630 {
3632 Heap* heap = this->heap(); 3631 Heap* heap = this->heap();
3633 TRACE_GC(heap->tracer(), 3632 TRACE_GC(heap->tracer(),
3634 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_TO_EVACUATED); 3633 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_TO_EVACUATED);
3635 UpdatePointersInParallel<OLD_TO_OLD>(heap_); 3634 UpdatePointersInParallel<OLD_TO_OLD>(heap_);
3636 } 3635 }
3637 3636
3638 { 3637 {
3639 TRACE_GC(heap()->tracer(), 3638 TRACE_GC(heap()->tracer(),
3640 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_BETWEEN_EVACUATED);
3641 for (Page* p : evacuation_candidates_) {
3642 DCHECK(p->IsEvacuationCandidate());
3643 // Important: skip list should be cleared only after roots were updated
3644 // because root iteration traverses the stack and might have to find
3645 // code objects from non-updated pc pointing into evacuation candidate.
3646 SkipList* list = p->skip_list();
3647 if (list != NULL) list->Clear();
3648
3649 // First pass on aborted pages, fixing up all live objects.
3650 if (p->IsFlagSet(Page::COMPACTION_WAS_ABORTED)) {
3651 p->ClearEvacuationCandidate();
3652 VisitLiveObjectsBody(p, &updating_visitor);
3653 }
3654 }
3655 }
3656
3657 {
3658 TRACE_GC(heap()->tracer(),
3659 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_WEAK); 3639 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_WEAK);
3660 // Update pointers from external string table. 3640 // Update pointers from external string table.
3661 heap_->UpdateReferencesInExternalStringTable( 3641 heap_->UpdateReferencesInExternalStringTable(
3662 &UpdateReferenceInExternalStringTableEntry); 3642 &UpdateReferenceInExternalStringTableEntry);
3663 3643
3664 EvacuationWeakObjectRetainer evacuation_object_retainer; 3644 EvacuationWeakObjectRetainer evacuation_object_retainer;
3665 heap()->ProcessWeakListRoots(&evacuation_object_retainer); 3645 heap()->ProcessWeakListRoots(&evacuation_object_retainer);
3666 } 3646 }
3667 } 3647 }
3668 3648
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
3896 MarkBit mark_bit = Marking::MarkBitFrom(host); 3876 MarkBit mark_bit = Marking::MarkBitFrom(host);
3897 if (Marking::IsBlack(mark_bit)) { 3877 if (Marking::IsBlack(mark_bit)) {
3898 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); 3878 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host);
3899 RecordRelocSlot(host, &rinfo, target); 3879 RecordRelocSlot(host, &rinfo, target);
3900 } 3880 }
3901 } 3881 }
3902 } 3882 }
3903 3883
3904 } // namespace internal 3884 } // namespace internal
3905 } // namespace v8 3885 } // namespace v8
OLDNEW
« no previous file with comments | « src/heap/mark-compact.h ('k') | src/heap/spaces-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698