OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |