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

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

Issue 1413763011: [heap] Fix rescanning live objects when aborting compaction. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 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 | « no previous file | src/heap/spaces.h » ('j') | src/heap/spaces.h » ('J')
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 2917 matching lines...) Expand 10 before | Expand all | Expand 10 after
2928 const uintptr_t kBoundary = V8_UINT64_C(1) << 48; 2928 const uintptr_t kBoundary = V8_UINT64_C(1) << 48;
2929 STATIC_ASSERT(kBoundary > 0); 2929 STATIC_ASSERT(kBoundary > 0);
2930 if (reinterpret_cast<uintptr_t>(heap_obj->address()) >= kBoundary) { 2930 if (reinterpret_cast<uintptr_t>(heap_obj->address()) >= kBoundary) {
2931 CheckLayoutDescriptorAndDie(heap, slot); 2931 CheckLayoutDescriptorAndDie(heap, slot);
2932 } 2932 }
2933 #endif 2933 #endif
2934 #endif 2934 #endif
2935 MapWord map_word = heap_obj->map_word(); 2935 MapWord map_word = heap_obj->map_word();
2936 if (map_word.IsForwardingAddress()) { 2936 if (map_word.IsForwardingAddress()) {
2937 DCHECK(heap->InFromSpace(heap_obj) || 2937 DCHECK(heap->InFromSpace(heap_obj) ||
2938 MarkCompactCollector::IsOnEvacuationCandidate(heap_obj)); 2938 MarkCompactCollector::IsOnEvacuationCandidate(heap_obj) ||
2939 Page::FromAddress(heap_obj->address())
2940 ->IsFlagSet(Page::COMPACTION_WAS_ABORTED));
2939 HeapObject* target = map_word.ToForwardingAddress(); 2941 HeapObject* target = map_word.ToForwardingAddress();
2940 base::NoBarrier_CompareAndSwap( 2942 base::NoBarrier_CompareAndSwap(
2941 reinterpret_cast<base::AtomicWord*>(slot), 2943 reinterpret_cast<base::AtomicWord*>(slot),
2942 reinterpret_cast<base::AtomicWord>(obj), 2944 reinterpret_cast<base::AtomicWord>(obj),
2943 reinterpret_cast<base::AtomicWord>(target)); 2945 reinterpret_cast<base::AtomicWord>(target));
2944 DCHECK(!heap->InFromSpace(target) && 2946 DCHECK(!heap->InFromSpace(target) &&
2945 !MarkCompactCollector::IsOnEvacuationCandidate(target)); 2947 !MarkCompactCollector::IsOnEvacuationCandidate(target));
2946 } 2948 }
2947 } 2949 }
2948 2950
(...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after
3456 // We need to: 3458 // We need to:
3457 // - Leave the evacuation candidate flag for later processing of 3459 // - Leave the evacuation candidate flag for later processing of
3458 // slots buffer entries. 3460 // slots buffer entries.
3459 // - Leave the slots buffer there for processing of entries added by 3461 // - Leave the slots buffer there for processing of entries added by
3460 // the write barrier. 3462 // the write barrier.
3461 // - Rescan the page as slot recording in the migration buffer only 3463 // - Rescan the page as slot recording in the migration buffer only
3462 // happens upon moving (which we potentially didn't do). 3464 // happens upon moving (which we potentially didn't do).
3463 // - Leave the page in the list of pages of a space since we could not 3465 // - Leave the page in the list of pages of a space since we could not
3464 // fully evacuate it. 3466 // fully evacuate it.
3465 DCHECK(p->IsEvacuationCandidate()); 3467 DCHECK(p->IsEvacuationCandidate());
3466 p->SetFlag(Page::RESCAN_ON_EVACUATION); 3468 p->SetFlag(Page::COMPACTION_WAS_ABORTED);
3467 abandoned_pages++; 3469 abandoned_pages++;
3468 break; 3470 break;
3469 case MemoryChunk::kCompactingFinalize: 3471 case MemoryChunk::kCompactingFinalize:
3470 DCHECK(p->IsEvacuationCandidate()); 3472 DCHECK(p->IsEvacuationCandidate());
3471 p->SetWasSwept(); 3473 p->SetWasSwept();
3472 p->Unlink(); 3474 p->Unlink();
3473 break; 3475 break;
3474 case MemoryChunk::kCompactingDone: 3476 case MemoryChunk::kCompactingDone:
3475 DCHECK(p->IsFlagSet(Page::POPULAR_PAGE)); 3477 DCHECK(p->IsFlagSet(Page::POPULAR_PAGE));
3476 DCHECK(p->IsFlagSet(Page::RESCAN_ON_EVACUATION)); 3478 DCHECK(p->IsFlagSet(Page::RESCAN_ON_EVACUATION));
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
3765 3767
3766 { 3768 {
3767 GCTracer::Scope gc_scope(heap()->tracer(), 3769 GCTracer::Scope gc_scope(heap()->tracer(),
3768 GCTracer::Scope::MC_UPDATE_OLD_TO_NEW_POINTERS); 3770 GCTracer::Scope::MC_UPDATE_OLD_TO_NEW_POINTERS);
3769 StoreBufferRebuildScope scope(heap_, heap_->store_buffer(), 3771 StoreBufferRebuildScope scope(heap_, heap_->store_buffer(),
3770 &Heap::ScavengeStoreBufferCallback); 3772 &Heap::ScavengeStoreBufferCallback);
3771 heap_->store_buffer()->IteratePointersToNewSpace(&UpdatePointer); 3773 heap_->store_buffer()->IteratePointersToNewSpace(&UpdatePointer);
3772 } 3774 }
3773 3775
3774 int npages = evacuation_candidates_.length(); 3776 int npages = evacuation_candidates_.length();
3775 { 3777 {
Hannes Payer (out of office) 2015/10/23 13:09:18 This function is getting super long (and complicat
Michael Lippautz 2015/10/23 13:27:05 Factored out a few pieces.
3776 GCTracer::Scope gc_scope( 3778 GCTracer::Scope gc_scope(
3777 heap()->tracer(), 3779 heap()->tracer(),
3778 GCTracer::Scope::MC_UPDATE_POINTERS_BETWEEN_EVACUATED); 3780 GCTracer::Scope::MC_UPDATE_POINTERS_BETWEEN_EVACUATED);
3779 for (int i = 0; i < npages; i++) { 3781 for (int i = 0; i < npages; i++) {
3780 Page* p = evacuation_candidates_[i]; 3782 Page* p = evacuation_candidates_[i];
3781 DCHECK(p->IsEvacuationCandidate() || 3783 DCHECK(p->IsEvacuationCandidate() ||
3782 p->IsFlagSet(Page::RESCAN_ON_EVACUATION)); 3784 p->IsFlagSet(Page::RESCAN_ON_EVACUATION));
3783 3785
3784 if (p->IsEvacuationCandidate()) { 3786 if (p->IsEvacuationCandidate()) {
3785 UpdateSlotsRecordedIn(p->slots_buffer()); 3787 UpdateSlotsRecordedIn(p->slots_buffer());
3786 if (FLAG_trace_fragmentation_verbose) { 3788 if (FLAG_trace_fragmentation_verbose) {
3787 PrintF(" page %p slots buffer: %d\n", reinterpret_cast<void*>(p), 3789 PrintF(" page %p slots buffer: %d\n", reinterpret_cast<void*>(p),
3788 SlotsBuffer::SizeOfChain(p->slots_buffer())); 3790 SlotsBuffer::SizeOfChain(p->slots_buffer()));
3789 } 3791 }
3790 slots_buffer_allocator_->DeallocateChain(p->slots_buffer_address()); 3792 slots_buffer_allocator_->DeallocateChain(p->slots_buffer_address());
3791 3793
3792 // Important: skip list should be cleared only after roots were updated 3794 // Important: skip list should be cleared only after roots were updated
3793 // because root iteration traverses the stack and might have to find 3795 // because root iteration traverses the stack and might have to find
3794 // code objects from non-updated pc pointing into evacuation candidate. 3796 // code objects from non-updated pc pointing into evacuation candidate.
3795 SkipList* list = p->skip_list(); 3797 SkipList* list = p->skip_list();
3796 if (list != NULL) list->Clear(); 3798 if (list != NULL) list->Clear();
3797 }
3798 3799
3799 if (p->IsEvacuationCandidate() && 3800 if (p->IsFlagSet(Page::COMPACTION_WAS_ABORTED)) {
3800 p->IsFlagSet(Page::RESCAN_ON_EVACUATION)) { 3801 p->ClearEvacuationCandidate();
3801 // Case where we've aborted compacting a page. Clear the flag here to 3802 // First pass on aborted pages.
3802 // avoid release the page later on. 3803 int offsets[16];
3803 p->ClearEvacuationCandidate(); 3804 for (MarkBitCellIterator it(p); !it.Done(); it.Advance()) {
3805 Address cell_base = it.CurrentCellBase();
3806 MarkBit::CellType* cell = it.CurrentCell();
3807 if (*cell == 0) continue;
3808 int live_objects = MarkWordToObjectStarts(*cell, offsets);
3809 for (int i = 0; i < live_objects; i++) {
3810 Address object_addr = cell_base + offsets[i] * kPointerSize;
3811 HeapObject* live_object = HeapObject::FromAddress(object_addr);
3812 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(live_object)));
3813 Map* map = live_object->synchronized_map();
3814 int size = live_object->SizeFromMap(map);
3815 live_object->IterateBody(map->instance_type(), size,
3816 &updating_visitor);
3817 }
3818 }
3819 }
3804 } 3820 }
3805 3821
3806 if (p->IsFlagSet(Page::RESCAN_ON_EVACUATION)) { 3822 if (p->IsFlagSet(Page::RESCAN_ON_EVACUATION)) {
3807 if (FLAG_gc_verbose) { 3823 if (FLAG_gc_verbose) {
3808 PrintF("Sweeping 0x%" V8PRIxPTR " during evacuation.\n", 3824 PrintF("Sweeping 0x%" V8PRIxPTR " during evacuation.\n",
3809 reinterpret_cast<intptr_t>(p)); 3825 reinterpret_cast<intptr_t>(p));
3810 } 3826 }
3811 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); 3827 PagedSpace* space = static_cast<PagedSpace*>(p->owner());
3812 p->ClearFlag(MemoryChunk::RESCAN_ON_EVACUATION); 3828 p->ClearFlag(MemoryChunk::RESCAN_ON_EVACUATION);
3813 3829
(...skipping 15 matching lines...) Expand all
3829 } 3845 }
3830 break; 3846 break;
3831 default: 3847 default:
3832 UNREACHABLE(); 3848 UNREACHABLE();
3833 break; 3849 break;
3834 } 3850 }
3835 } 3851 }
3836 } 3852 }
3837 } 3853 }
3838 3854
3839 GCTracer::Scope gc_scope(heap()->tracer(), 3855 GCTracer::Scope gc_scope(heap()->tracer(),
Hannes Payer (out of office) 2015/10/23 13:09:18 This timer scope now also covers the sweeping.
Michael Lippautz 2015/10/23 13:27:05 Fixed to only track updating the pointers.
3840 GCTracer::Scope::MC_UPDATE_MISC_POINTERS); 3856 GCTracer::Scope::MC_UPDATE_MISC_POINTERS);
3841 3857
3842 heap_->string_table()->Iterate(&updating_visitor); 3858 heap_->string_table()->Iterate(&updating_visitor);
3843 3859
3844 // Update pointers from external string table. 3860 // Update pointers from external string table.
3845 heap_->UpdateReferencesInExternalStringTable( 3861 heap_->UpdateReferencesInExternalStringTable(
3846 &UpdateReferenceInExternalStringTableEntry); 3862 &UpdateReferenceInExternalStringTableEntry);
3847 3863
3848 EvacuationWeakObjectRetainer evacuation_object_retainer; 3864 EvacuationWeakObjectRetainer evacuation_object_retainer;
3849 heap()->ProcessAllWeakReferences(&evacuation_object_retainer); 3865 heap()->ProcessAllWeakReferences(&evacuation_object_retainer);
3850 3866
3867 // Second pass on aborted pages.
Hannes Payer (out of office) 2015/10/23 13:09:18 Please add a separate timer scope here.
Michael Lippautz 2015/10/23 13:27:05 Done.
3868 for (int i = 0; i < npages; i++) {
3869 Page* p = evacuation_candidates_[i];
3870 if (p->IsFlagSet(Page::COMPACTION_WAS_ABORTED)) {
3871 p->ClearFlag(MemoryChunk::COMPACTION_WAS_ABORTED);
3872 PagedSpace* space = static_cast<PagedSpace*>(p->owner());
3873 switch (space->identity()) {
3874 case OLD_SPACE:
3875 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, IGNORE_SKIP_LIST,
3876 IGNORE_FREE_SPACE>(space, nullptr, p, nullptr);
3877 break;
3878 case CODE_SPACE:
3879 if (FLAG_zap_code_space) {
3880 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, REBUILD_SKIP_LIST,
3881 ZAP_FREE_SPACE>(space, NULL, p, nullptr);
3882 } else {
3883 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, REBUILD_SKIP_LIST,
3884 IGNORE_FREE_SPACE>(space, NULL, p, nullptr);
3885 }
3886 break;
3887 default:
3888 UNREACHABLE();
3889 break;
3890 }
3891 }
3892 }
3893
3851 heap_->isolate()->inner_pointer_to_code_cache()->Flush(); 3894 heap_->isolate()->inner_pointer_to_code_cache()->Flush();
3852 3895
3853 // The hashing of weak_object_to_code_table is no longer valid. 3896 // The hashing of weak_object_to_code_table is no longer valid.
3854 heap()->weak_object_to_code_table()->Rehash( 3897 heap()->weak_object_to_code_table()->Rehash(
3855 heap()->isolate()->factory()->undefined_value()); 3898 heap()->isolate()->factory()->undefined_value());
3856 } 3899 }
3857 3900
3858 3901
3859 void MarkCompactCollector::MoveEvacuationCandidatesToEndOfPagesList() { 3902 void MarkCompactCollector::MoveEvacuationCandidatesToEndOfPagesList() {
3860 int npages = evacuation_candidates_.length(); 3903 int npages = evacuation_candidates_.length();
(...skipping 751 matching lines...) Expand 10 before | Expand all | Expand 10 after
4612 MarkBit mark_bit = Marking::MarkBitFrom(host); 4655 MarkBit mark_bit = Marking::MarkBitFrom(host);
4613 if (Marking::IsBlack(mark_bit)) { 4656 if (Marking::IsBlack(mark_bit)) {
4614 RelocInfo rinfo(pc, RelocInfo::CODE_TARGET, 0, host); 4657 RelocInfo rinfo(pc, RelocInfo::CODE_TARGET, 0, host);
4615 RecordRelocSlot(&rinfo, target); 4658 RecordRelocSlot(&rinfo, target);
4616 } 4659 }
4617 } 4660 }
4618 } 4661 }
4619 4662
4620 } // namespace internal 4663 } // namespace internal
4621 } // namespace v8 4664 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | src/heap/spaces.h » ('j') | src/heap/spaces.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698