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

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: Addressed comments Created 5 years, 2 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.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 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 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
3694 DCHECK(p->IsEvacuationCandidate() || 3696 DCHECK(p->IsEvacuationCandidate() ||
3695 p->IsFlagSet(Page::RESCAN_ON_EVACUATION)); 3697 p->IsFlagSet(Page::RESCAN_ON_EVACUATION));
3696 if (p->IsEvacuationCandidate()) { 3698 if (p->IsEvacuationCandidate()) {
3697 SlotsBuffer::RemoveObjectSlots(heap_, p->slots_buffer(), start_slot, 3699 SlotsBuffer::RemoveObjectSlots(heap_, p->slots_buffer(), start_slot,
3698 end_slot); 3700 end_slot);
3699 } 3701 }
3700 } 3702 }
3701 } 3703 }
3702 3704
3703 3705
3706 void MarkCompactCollector::VisitLiveObjects(Page* page,
3707 ObjectVisitor* visitor) {
3708 // First pass on aborted pages.
3709 int offsets[16];
3710 for (MarkBitCellIterator it(page); !it.Done(); it.Advance()) {
3711 Address cell_base = it.CurrentCellBase();
3712 MarkBit::CellType* cell = it.CurrentCell();
3713 if (*cell == 0) continue;
3714 int live_objects = MarkWordToObjectStarts(*cell, offsets);
3715 for (int i = 0; i < live_objects; i++) {
3716 Address object_addr = cell_base + offsets[i] * kPointerSize;
3717 HeapObject* live_object = HeapObject::FromAddress(object_addr);
3718 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(live_object)));
3719 Map* map = live_object->synchronized_map();
3720 int size = live_object->SizeFromMap(map);
3721 live_object->IterateBody(map->instance_type(), size, visitor);
3722 }
3723 }
3724 }
3725
3726
3727 void MarkCompactCollector::SweepAbortedPages() {
3728 // Second pass on aborted pages.
3729 for (int i = 0; i < evacuation_candidates_.length(); i++) {
3730 Page* p = evacuation_candidates_[i];
3731 if (p->IsFlagSet(Page::COMPACTION_WAS_ABORTED)) {
3732 p->ClearFlag(MemoryChunk::COMPACTION_WAS_ABORTED);
3733 PagedSpace* space = static_cast<PagedSpace*>(p->owner());
3734 switch (space->identity()) {
3735 case OLD_SPACE:
3736 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, IGNORE_SKIP_LIST,
3737 IGNORE_FREE_SPACE>(space, nullptr, p, nullptr);
3738 break;
3739 case CODE_SPACE:
3740 if (FLAG_zap_code_space) {
3741 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, REBUILD_SKIP_LIST,
3742 ZAP_FREE_SPACE>(space, NULL, p, nullptr);
3743 } else {
3744 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, REBUILD_SKIP_LIST,
3745 IGNORE_FREE_SPACE>(space, NULL, p, nullptr);
3746 }
3747 break;
3748 default:
3749 UNREACHABLE();
3750 break;
3751 }
3752 }
3753 }
3754 }
3755
3756
3704 void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { 3757 void MarkCompactCollector::EvacuateNewSpaceAndCandidates() {
3705 Heap::RelocationLock relocation_lock(heap()); 3758 Heap::RelocationLock relocation_lock(heap());
3706 3759
3707 { 3760 {
3708 GCTracer::Scope gc_scope(heap()->tracer(), 3761 GCTracer::Scope gc_scope(heap()->tracer(),
3709 GCTracer::Scope::MC_SWEEP_NEWSPACE); 3762 GCTracer::Scope::MC_SWEEP_NEWSPACE);
3710 EvacuationScope evacuation_scope(this); 3763 EvacuationScope evacuation_scope(this);
3711 EvacuateNewSpace(); 3764 EvacuateNewSpace();
3712 } 3765 }
3713 3766
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
3787 PrintF(" page %p slots buffer: %d\n", reinterpret_cast<void*>(p), 3840 PrintF(" page %p slots buffer: %d\n", reinterpret_cast<void*>(p),
3788 SlotsBuffer::SizeOfChain(p->slots_buffer())); 3841 SlotsBuffer::SizeOfChain(p->slots_buffer()));
3789 } 3842 }
3790 slots_buffer_allocator_->DeallocateChain(p->slots_buffer_address()); 3843 slots_buffer_allocator_->DeallocateChain(p->slots_buffer_address());
3791 3844
3792 // Important: skip list should be cleared only after roots were updated 3845 // Important: skip list should be cleared only after roots were updated
3793 // because root iteration traverses the stack and might have to find 3846 // because root iteration traverses the stack and might have to find
3794 // code objects from non-updated pc pointing into evacuation candidate. 3847 // code objects from non-updated pc pointing into evacuation candidate.
3795 SkipList* list = p->skip_list(); 3848 SkipList* list = p->skip_list();
3796 if (list != NULL) list->Clear(); 3849 if (list != NULL) list->Clear();
3797 }
3798 3850
3799 if (p->IsEvacuationCandidate() && 3851 // First pass on aborted pages, fixing up all live objects.
3800 p->IsFlagSet(Page::RESCAN_ON_EVACUATION)) { 3852 if (p->IsFlagSet(Page::COMPACTION_WAS_ABORTED)) {
3801 // Case where we've aborted compacting a page. Clear the flag here to 3853 // Clearing the evacuation candidate flag here has the effect of
3802 // avoid release the page later on. 3854 // stopping recording of slots for it in the following pointer
3803 p->ClearEvacuationCandidate(); 3855 // update phases.
3856 p->ClearEvacuationCandidate();
3857 VisitLiveObjects(p, &updating_visitor);
3858 }
3804 } 3859 }
3805 3860
3806 if (p->IsFlagSet(Page::RESCAN_ON_EVACUATION)) { 3861 if (p->IsFlagSet(Page::RESCAN_ON_EVACUATION)) {
3807 if (FLAG_gc_verbose) { 3862 if (FLAG_gc_verbose) {
3808 PrintF("Sweeping 0x%" V8PRIxPTR " during evacuation.\n", 3863 PrintF("Sweeping 0x%" V8PRIxPTR " during evacuation.\n",
3809 reinterpret_cast<intptr_t>(p)); 3864 reinterpret_cast<intptr_t>(p));
3810 } 3865 }
3811 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); 3866 PagedSpace* space = static_cast<PagedSpace*>(p->owner());
3812 p->ClearFlag(MemoryChunk::RESCAN_ON_EVACUATION); 3867 p->ClearFlag(MemoryChunk::RESCAN_ON_EVACUATION);
3813 3868
(...skipping 15 matching lines...) Expand all
3829 } 3884 }
3830 break; 3885 break;
3831 default: 3886 default:
3832 UNREACHABLE(); 3887 UNREACHABLE();
3833 break; 3888 break;
3834 } 3889 }
3835 } 3890 }
3836 } 3891 }
3837 } 3892 }
3838 3893
3839 GCTracer::Scope gc_scope(heap()->tracer(), 3894 {
3840 GCTracer::Scope::MC_UPDATE_MISC_POINTERS); 3895 GCTracer::Scope gc_scope(heap()->tracer(),
3896 GCTracer::Scope::MC_UPDATE_MISC_POINTERS);
3897 heap_->string_table()->Iterate(&updating_visitor);
3841 3898
3842 heap_->string_table()->Iterate(&updating_visitor); 3899 // Update pointers from external string table.
3900 heap_->UpdateReferencesInExternalStringTable(
3901 &UpdateReferenceInExternalStringTableEntry);
3843 3902
3844 // Update pointers from external string table. 3903 EvacuationWeakObjectRetainer evacuation_object_retainer;
3845 heap_->UpdateReferencesInExternalStringTable( 3904 heap()->ProcessAllWeakReferences(&evacuation_object_retainer);
3846 &UpdateReferenceInExternalStringTableEntry); 3905 }
3847 3906
3848 EvacuationWeakObjectRetainer evacuation_object_retainer; 3907 {
3849 heap()->ProcessAllWeakReferences(&evacuation_object_retainer); 3908 GCTracer::Scope gc_scope(heap()->tracer(),
3909 GCTracer::Scope::MC_SWEEP_ABORTED);
3910 // After updating all pointers, we can finally sweep the aborted pages,
3911 // effectively overriding any forward pointers.
3912 SweepAbortedPages();
3913 }
3850 3914
3851 heap_->isolate()->inner_pointer_to_code_cache()->Flush(); 3915 heap_->isolate()->inner_pointer_to_code_cache()->Flush();
3852 3916
3853 // The hashing of weak_object_to_code_table is no longer valid. 3917 // The hashing of weak_object_to_code_table is no longer valid.
3854 heap()->weak_object_to_code_table()->Rehash( 3918 heap()->weak_object_to_code_table()->Rehash(
3855 heap()->isolate()->factory()->undefined_value()); 3919 heap()->isolate()->factory()->undefined_value());
3856 } 3920 }
3857 3921
3858 3922
3859 void MarkCompactCollector::MoveEvacuationCandidatesToEndOfPagesList() { 3923 void MarkCompactCollector::MoveEvacuationCandidatesToEndOfPagesList() {
(...skipping 752 matching lines...) Expand 10 before | Expand all | Expand 10 after
4612 MarkBit mark_bit = Marking::MarkBitFrom(host); 4676 MarkBit mark_bit = Marking::MarkBitFrom(host);
4613 if (Marking::IsBlack(mark_bit)) { 4677 if (Marking::IsBlack(mark_bit)) {
4614 RelocInfo rinfo(pc, RelocInfo::CODE_TARGET, 0, host); 4678 RelocInfo rinfo(pc, RelocInfo::CODE_TARGET, 0, host);
4615 RecordRelocSlot(&rinfo, target); 4679 RecordRelocSlot(&rinfo, target);
4616 } 4680 }
4617 } 4681 }
4618 } 4682 }
4619 4683
4620 } // namespace internal 4684 } // namespace internal
4621 } // namespace v8 4685 } // namespace v8
OLDNEW
« no previous file with comments | « src/heap/mark-compact.h ('k') | src/heap/spaces.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698