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

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

Issue 2783873002: [heap] Reland: Make SlotSet allocation thread-safe and refactor code. (Closed)
Patch Set: fix and cleanup Created 3 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 | « no previous file | src/heap/remembered-set.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 671 matching lines...) Expand 10 before | Expand all | Expand 10 after
682 space->top() == space->limit() 682 space->top() == space->limit()
683 ? nullptr 683 ? nullptr
684 : Page::FromAllocationAreaAddress(space->top()); 684 : Page::FromAllocationAreaAddress(space->top());
685 for (Page* p : *space) { 685 for (Page* p : *space) {
686 if (p->NeverEvacuate() || p == owner_of_linear_allocation_area) continue; 686 if (p->NeverEvacuate() || p == owner_of_linear_allocation_area) continue;
687 // Invariant: Evacuation candidates are just created when marking is 687 // Invariant: Evacuation candidates are just created when marking is
688 // started. This means that sweeping has finished. Furthermore, at the end 688 // started. This means that sweeping has finished. Furthermore, at the end
689 // of a GC all evacuation candidates are cleared and their slot buffers are 689 // of a GC all evacuation candidates are cleared and their slot buffers are
690 // released. 690 // released.
691 CHECK(!p->IsEvacuationCandidate()); 691 CHECK(!p->IsEvacuationCandidate());
692 CHECK_NULL(p->old_to_old_slots()); 692 CHECK_NULL(p->slot_set<OLD_TO_OLD>());
693 CHECK_NULL(p->typed_old_to_old_slots()); 693 CHECK_NULL(p->typed_slot_set<OLD_TO_OLD>());
694 CHECK(p->SweepingDone()); 694 CHECK(p->SweepingDone());
695 DCHECK(p->area_size() == area_size); 695 DCHECK(p->area_size() == area_size);
696 pages.push_back(std::make_pair(p->LiveBytesFromFreeList(), p)); 696 pages.push_back(std::make_pair(p->LiveBytesFromFreeList(), p));
697 } 697 }
698 698
699 int candidate_count = 0; 699 int candidate_count = 0;
700 size_t total_live_bytes = 0; 700 size_t total_live_bytes = 0;
701 701
702 const bool reduce_memory = heap()->ShouldReduceMemory(); 702 const bool reduce_memory = heap()->ShouldReduceMemory();
703 if (FLAG_manual_evacuation_candidates_selection) { 703 if (FLAG_manual_evacuation_candidates_selection) {
(...skipping 2719 matching lines...) Expand 10 before | Expand all | Expand 10 after
3423 return map_word.ToForwardingAddress(); 3423 return map_word.ToForwardingAddress();
3424 } 3424 }
3425 } 3425 }
3426 return object; 3426 return object;
3427 } 3427 }
3428 }; 3428 };
3429 3429
3430 MarkCompactCollector::Sweeper::ClearOldToNewSlotsMode 3430 MarkCompactCollector::Sweeper::ClearOldToNewSlotsMode
3431 MarkCompactCollector::Sweeper::GetClearOldToNewSlotsMode(Page* p) { 3431 MarkCompactCollector::Sweeper::GetClearOldToNewSlotsMode(Page* p) {
3432 AllocationSpace identity = p->owner()->identity(); 3432 AllocationSpace identity = p->owner()->identity();
3433 if (p->old_to_new_slots() && 3433 if (p->slot_set<OLD_TO_NEW>() &&
3434 (identity == OLD_SPACE || identity == MAP_SPACE)) { 3434 (identity == OLD_SPACE || identity == MAP_SPACE)) {
3435 return MarkCompactCollector::Sweeper::CLEAR_REGULAR_SLOTS; 3435 return MarkCompactCollector::Sweeper::CLEAR_REGULAR_SLOTS;
3436 } else if (p->typed_old_to_new_slots() && identity == CODE_SPACE) { 3436 } else if (p->typed_slot_set<OLD_TO_NEW>() && identity == CODE_SPACE) {
3437 return MarkCompactCollector::Sweeper::CLEAR_TYPED_SLOTS; 3437 return MarkCompactCollector::Sweeper::CLEAR_TYPED_SLOTS;
3438 } 3438 }
3439 return MarkCompactCollector::Sweeper::DO_NOT_CLEAR; 3439 return MarkCompactCollector::Sweeper::DO_NOT_CLEAR;
3440 } 3440 }
3441 3441
3442 int MarkCompactCollector::Sweeper::RawSweep( 3442 int MarkCompactCollector::Sweeper::RawSweep(
3443 Page* p, FreeListRebuildingMode free_list_mode, 3443 Page* p, FreeListRebuildingMode free_list_mode,
3444 FreeSpaceTreatmentMode free_space_mode) { 3444 FreeSpaceTreatmentMode free_space_mode) {
3445 Space* space = p->owner(); 3445 Space* space = p->owner();
3446 DCHECK_NOT_NULL(space); 3446 DCHECK_NOT_NULL(space);
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
3539 RememberedSet<OLD_TO_NEW>::RemoveRange(p, free_start, p->area_end(), 3539 RememberedSet<OLD_TO_NEW>::RemoveRange(p, free_start, p->area_end(),
3540 SlotSet::KEEP_EMPTY_BUCKETS); 3540 SlotSet::KEEP_EMPTY_BUCKETS);
3541 } else if (slots_clearing_mode == CLEAR_TYPED_SLOTS) { 3541 } else if (slots_clearing_mode == CLEAR_TYPED_SLOTS) {
3542 free_ranges.insert(std::pair<uint32_t, uint32_t>( 3542 free_ranges.insert(std::pair<uint32_t, uint32_t>(
3543 static_cast<uint32_t>(free_start - p->address()), 3543 static_cast<uint32_t>(free_start - p->address()),
3544 static_cast<uint32_t>(p->area_end() - p->address()))); 3544 static_cast<uint32_t>(p->area_end() - p->address())));
3545 } 3545 }
3546 } 3546 }
3547 3547
3548 // Clear invalid typed slots after collection all free ranges. 3548 // Clear invalid typed slots after collection all free ranges.
3549 if (slots_clearing_mode == CLEAR_TYPED_SLOTS) { 3549 TypedSlotSet* typed_slot_set = p->typed_slot_set<OLD_TO_NEW>();
3550 p->typed_old_to_new_slots()->RemoveInvaldSlots(free_ranges); 3550 if (typed_slot_set != nullptr && slots_clearing_mode == CLEAR_TYPED_SLOTS) {
ulan 2017/03/29 14:41:50 How about putting the type_slot_set inside the bra
Hannes Payer (out of office) 2017/03/29 14:53:15 Done.
3551 typed_slot_set->RemoveInvaldSlots(free_ranges);
3551 } 3552 }
3552 3553
3553 // Clear the mark bits of that page and reset live bytes count. 3554 // Clear the mark bits of that page and reset live bytes count.
3554 MarkingState::Internal(p).ClearLiveness(); 3555 MarkingState::Internal(p).ClearLiveness();
3555 3556
3556 p->concurrent_sweeping_state().SetValue(Page::kSweepingDone); 3557 p->concurrent_sweeping_state().SetValue(Page::kSweepingDone);
3557 if (free_list_mode == IGNORE_FREE_LIST) return 0; 3558 if (free_list_mode == IGNORE_FREE_LIST) return 0;
3558 return static_cast<int>(FreeList::GuaranteedAllocatable(max_freed_bytes)); 3559 return static_cast<int>(FreeList::GuaranteedAllocatable(max_freed_bytes));
3559 } 3560 }
3560 3561
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
3599 IterationMode iteration_mode) { 3600 IterationMode iteration_mode) {
3600 LiveObjectIterator<kBlackObjects> it(chunk, state); 3601 LiveObjectIterator<kBlackObjects> it(chunk, state);
3601 HeapObject* object = nullptr; 3602 HeapObject* object = nullptr;
3602 while ((object = it.Next()) != nullptr) { 3603 while ((object = it.Next()) != nullptr) {
3603 DCHECK(ObjectMarking::IsBlack(object, state)); 3604 DCHECK(ObjectMarking::IsBlack(object, state));
3604 if (!visitor->Visit(object)) { 3605 if (!visitor->Visit(object)) {
3605 if (iteration_mode == kClearMarkbits) { 3606 if (iteration_mode == kClearMarkbits) {
3606 state.bitmap()->ClearRange( 3607 state.bitmap()->ClearRange(
3607 chunk->AddressToMarkbitIndex(chunk->area_start()), 3608 chunk->AddressToMarkbitIndex(chunk->area_start()),
3608 chunk->AddressToMarkbitIndex(object->address())); 3609 chunk->AddressToMarkbitIndex(object->address()));
3609 if (chunk->old_to_new_slots() != nullptr) { 3610 SlotSet* slot_set = chunk->slot_set<OLD_TO_NEW>();
3610 chunk->old_to_new_slots()->RemoveRange( 3611 if (slot_set != nullptr) {
3612 slot_set->RemoveRange(
3611 0, static_cast<int>(object->address() - chunk->address()), 3613 0, static_cast<int>(object->address() - chunk->address()),
3612 SlotSet::PREFREE_EMPTY_BUCKETS); 3614 SlotSet::PREFREE_EMPTY_BUCKETS);
3613 } 3615 }
3614 if (chunk->typed_old_to_new_slots() != nullptr) { 3616 RememberedSet<OLD_TO_NEW>::RemoveRangeTyped(chunk, chunk->address(),
3615 RememberedSet<OLD_TO_NEW>::RemoveRangeTyped(chunk, chunk->address(), 3617 object->address());
3616 object->address());
3617 }
3618 RecomputeLiveBytes(chunk, state); 3618 RecomputeLiveBytes(chunk, state);
3619 } 3619 }
3620 return false; 3620 return false;
3621 } 3621 }
3622 } 3622 }
3623 if (iteration_mode == kClearMarkbits) { 3623 if (iteration_mode == kClearMarkbits) {
3624 state.ClearLiveness(); 3624 state.ClearLiveness();
3625 } 3625 }
3626 return true; 3626 return true;
3627 } 3627 }
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
3707 EvacuateEpilogue(); 3707 EvacuateEpilogue();
3708 } 3708 }
3709 3709
3710 #ifdef VERIFY_HEAP 3710 #ifdef VERIFY_HEAP
3711 if (FLAG_verify_heap && !sweeper().sweeping_in_progress()) { 3711 if (FLAG_verify_heap && !sweeper().sweeping_in_progress()) {
3712 VerifyEvacuation(heap()); 3712 VerifyEvacuation(heap());
3713 } 3713 }
3714 #endif 3714 #endif
3715 } 3715 }
3716 3716
3717 template <PointerDirection direction> 3717 template <RememberedSetType type>
3718 class PointerUpdateJobTraits { 3718 class PointerUpdateJobTraits {
3719 public: 3719 public:
3720 typedef int PerPageData; // Per page data is not used in this job. 3720 typedef int PerPageData; // Per page data is not used in this job.
3721 typedef int PerTaskData; // Per task data is not used in this job. 3721 typedef int PerTaskData; // Per task data is not used in this job.
3722 3722
3723 static bool ProcessPageInParallel(Heap* heap, PerTaskData, MemoryChunk* chunk, 3723 static bool ProcessPageInParallel(Heap* heap, PerTaskData, MemoryChunk* chunk,
3724 PerPageData) { 3724 PerPageData) {
3725 UpdateUntypedPointers(heap, chunk); 3725 UpdateUntypedPointers(heap, chunk);
3726 UpdateTypedPointers(heap, chunk); 3726 UpdateTypedPointers(heap, chunk);
3727 return true; 3727 return true;
3728 } 3728 }
3729 static const bool NeedSequentialFinalization = false; 3729 static const bool NeedSequentialFinalization = false;
3730 static void FinalizePageSequentially(Heap*, MemoryChunk*, bool, PerPageData) { 3730 static void FinalizePageSequentially(Heap*, MemoryChunk*, bool, PerPageData) {
3731 } 3731 }
3732 3732
3733 private: 3733 private:
3734 static void UpdateUntypedPointers(Heap* heap, MemoryChunk* chunk) { 3734 static void UpdateUntypedPointers(Heap* heap, MemoryChunk* chunk) {
3735 if (direction == OLD_TO_NEW) { 3735 if (type == OLD_TO_NEW) {
3736 RememberedSet<OLD_TO_NEW>::Iterate(chunk, [heap](Address slot) { 3736 RememberedSet<OLD_TO_NEW>::Iterate(chunk, [heap](Address slot) {
3737 return CheckAndUpdateOldToNewSlot(heap, slot); 3737 return CheckAndUpdateOldToNewSlot(heap, slot);
3738 }); 3738 });
3739 } else { 3739 } else {
3740 RememberedSet<OLD_TO_OLD>::Iterate(chunk, [](Address slot) { 3740 RememberedSet<OLD_TO_OLD>::Iterate(chunk, [](Address slot) {
3741 return UpdateSlot(reinterpret_cast<Object**>(slot)); 3741 return UpdateSlot(reinterpret_cast<Object**>(slot));
3742 }); 3742 });
3743 } 3743 }
3744 } 3744 }
3745 3745
3746 static void UpdateTypedPointers(Heap* heap, MemoryChunk* chunk) { 3746 static void UpdateTypedPointers(Heap* heap, MemoryChunk* chunk) {
3747 if (direction == OLD_TO_OLD) { 3747 if (type == OLD_TO_OLD) {
3748 Isolate* isolate = heap->isolate(); 3748 Isolate* isolate = heap->isolate();
3749 RememberedSet<OLD_TO_OLD>::IterateTyped( 3749 RememberedSet<OLD_TO_OLD>::IterateTyped(
3750 chunk, [isolate](SlotType type, Address host_addr, Address slot) { 3750 chunk,
3751 return UpdateTypedSlotHelper::UpdateTypedSlot(isolate, type, slot, 3751 [isolate](SlotType slot_type, Address host_addr, Address slot) {
3752 UpdateSlot); 3752 return UpdateTypedSlotHelper::UpdateTypedSlot(isolate, slot_type,
3753 slot, UpdateSlot);
3753 }); 3754 });
3754 } else { 3755 } else {
3755 Isolate* isolate = heap->isolate(); 3756 Isolate* isolate = heap->isolate();
3756 RememberedSet<OLD_TO_NEW>::IterateTyped( 3757 RememberedSet<OLD_TO_NEW>::IterateTyped(
3757 chunk, 3758 chunk,
3758 [isolate, heap](SlotType type, Address host_addr, Address slot) { 3759 [isolate, heap](SlotType slot_type, Address host_addr, Address slot) {
3759 return UpdateTypedSlotHelper::UpdateTypedSlot( 3760 return UpdateTypedSlotHelper::UpdateTypedSlot(
3760 isolate, type, slot, [heap](Object** slot) { 3761 isolate, slot_type, slot, [heap](Object** slot) {
3761 return CheckAndUpdateOldToNewSlot( 3762 return CheckAndUpdateOldToNewSlot(
3762 heap, reinterpret_cast<Address>(slot)); 3763 heap, reinterpret_cast<Address>(slot));
3763 }); 3764 });
3764 }); 3765 });
3765 } 3766 }
3766 } 3767 }
3767 3768
3768 static SlotCallbackResult CheckAndUpdateOldToNewSlot(Heap* heap, 3769 static SlotCallbackResult CheckAndUpdateOldToNewSlot(Heap* heap,
3769 Address slot_address) { 3770 Address slot_address) {
3770 // There may be concurrent action on slots in dead objects. Concurrent 3771 // There may be concurrent action on slots in dead objects. Concurrent
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
3817 3818
3818 int NumberOfPointerUpdateTasks(int pages) { 3819 int NumberOfPointerUpdateTasks(int pages) {
3819 if (!FLAG_parallel_pointer_update) return 1; 3820 if (!FLAG_parallel_pointer_update) return 1;
3820 const int available_cores = Max( 3821 const int available_cores = Max(
3821 1, static_cast<int>( 3822 1, static_cast<int>(
3822 V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads())); 3823 V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads()));
3823 const int kPagesPerTask = 4; 3824 const int kPagesPerTask = 4;
3824 return Min(available_cores, (pages + kPagesPerTask - 1) / kPagesPerTask); 3825 return Min(available_cores, (pages + kPagesPerTask - 1) / kPagesPerTask);
3825 } 3826 }
3826 3827
3827 template <PointerDirection direction> 3828 template <RememberedSetType type>
3828 void UpdatePointersInParallel(Heap* heap, base::Semaphore* semaphore) { 3829 void UpdatePointersInParallel(Heap* heap, base::Semaphore* semaphore) {
3829 PageParallelJob<PointerUpdateJobTraits<direction> > job( 3830 PageParallelJob<PointerUpdateJobTraits<type> > job(
3830 heap, heap->isolate()->cancelable_task_manager(), semaphore); 3831 heap, heap->isolate()->cancelable_task_manager(), semaphore);
3831 RememberedSet<direction>::IterateMemoryChunks( 3832 RememberedSet<type>::IterateMemoryChunks(
3832 heap, [&job](MemoryChunk* chunk) { job.AddPage(chunk, 0); }); 3833 heap, [&job](MemoryChunk* chunk) { job.AddPage(chunk, 0); });
3833 int num_pages = job.NumberOfPages(); 3834 int num_pages = job.NumberOfPages();
3834 int num_tasks = NumberOfPointerUpdateTasks(num_pages); 3835 int num_tasks = NumberOfPointerUpdateTasks(num_pages);
3835 job.Run(num_tasks, [](int i) { return 0; }); 3836 job.Run(num_tasks, [](int i) { return 0; });
3836 } 3837 }
3837 3838
3838 class ToSpacePointerUpdateJobTraits { 3839 class ToSpacePointerUpdateJobTraits {
3839 public: 3840 public:
3840 typedef std::pair<Address, Address> PerPageData; 3841 typedef std::pair<Address, Address> PerPageData;
3841 typedef PointersUpdatingVisitor* PerTaskData; 3842 typedef PointersUpdatingVisitor* PerTaskData;
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
3976 const Sweeper::FreeSpaceTreatmentMode free_space_mode = 3977 const Sweeper::FreeSpaceTreatmentMode free_space_mode =
3977 Heap::ShouldZapGarbage() ? ZAP_FREE_SPACE : IGNORE_FREE_SPACE; 3978 Heap::ShouldZapGarbage() ? ZAP_FREE_SPACE : IGNORE_FREE_SPACE;
3978 if (identity == NEW_SPACE) { 3979 if (identity == NEW_SPACE) {
3979 RawSweep(page, IGNORE_FREE_LIST, free_space_mode); 3980 RawSweep(page, IGNORE_FREE_LIST, free_space_mode);
3980 } else { 3981 } else {
3981 max_freed = RawSweep(page, REBUILD_FREE_LIST, free_space_mode); 3982 max_freed = RawSweep(page, REBUILD_FREE_LIST, free_space_mode);
3982 } 3983 }
3983 DCHECK(page->SweepingDone()); 3984 DCHECK(page->SweepingDone());
3984 3985
3985 // After finishing sweeping of a page we clean up its remembered set. 3986 // After finishing sweeping of a page we clean up its remembered set.
3986 if (page->typed_old_to_new_slots()) { 3987 TypedSlotSet* typed_slot_set = page->typed_slot_set<OLD_TO_NEW>();
3987 page->typed_old_to_new_slots()->FreeToBeFreedChunks(); 3988 if (typed_slot_set) {
3989 typed_slot_set->FreeToBeFreedChunks();
3988 } 3990 }
3989 if (page->old_to_new_slots()) { 3991 SlotSet* slot_set = page->slot_set<OLD_TO_NEW>();
3990 page->old_to_new_slots()->FreeToBeFreedBuckets(); 3992 if (slot_set) {
3993 slot_set->FreeToBeFreedBuckets();
3991 } 3994 }
3992 } 3995 }
3993 3996
3994 { 3997 {
3995 base::LockGuard<base::Mutex> guard(&mutex_); 3998 base::LockGuard<base::Mutex> guard(&mutex_);
3996 swept_list_[identity].Add(page); 3999 swept_list_[identity].Add(page);
3997 } 4000 }
3998 return max_freed; 4001 return max_freed;
3999 } 4002 }
4000 4003
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
4147 // The target is always in old space, we don't have to record the slot in 4150 // The target is always in old space, we don't have to record the slot in
4148 // the old-to-new remembered set. 4151 // the old-to-new remembered set.
4149 DCHECK(!heap()->InNewSpace(target)); 4152 DCHECK(!heap()->InNewSpace(target));
4150 RecordRelocSlot(host, &rinfo, target); 4153 RecordRelocSlot(host, &rinfo, target);
4151 } 4154 }
4152 } 4155 }
4153 } 4156 }
4154 4157
4155 } // namespace internal 4158 } // namespace internal
4156 } // namespace v8 4159 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | src/heap/remembered-set.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698