Commit fd530c12 authored by Michael Lippautz's avatar Michael Lippautz Committed by Commit Bot

[heap] MinorMC: Parallel marking

Bug: chromium:651354
Change-Id: I9df2ca542112f04787987bda67657fc4015787b5
Reviewed-on: https://chromium-review.googlesource.com/506152
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Reviewed-by: 's avatarHannes Payer <hpayer@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#45363}
parent 9595d0f6
...@@ -671,6 +671,10 @@ DEFINE_BOOL(incremental_marking_wrappers, true, ...@@ -671,6 +671,10 @@ DEFINE_BOOL(incremental_marking_wrappers, true,
"use incremental marking for marking wrappers") "use incremental marking for marking wrappers")
DEFINE_BOOL(concurrent_marking, V8_CONCURRENT_MARKING, "use concurrent marking") DEFINE_BOOL(concurrent_marking, V8_CONCURRENT_MARKING, "use concurrent marking")
DEFINE_BOOL(trace_concurrent_marking, false, "trace concurrent marking") DEFINE_BOOL(trace_concurrent_marking, false, "trace concurrent marking")
DEFINE_BOOL(minor_mc_parallel_marking, true,
"use parallel marking for the young generation")
DEFINE_BOOL(trace_minor_mc_parallel_marking, false,
"trace parallel marking for the young generation")
DEFINE_INT(min_progress_during_incremental_marking_finalization, 32, DEFINE_INT(min_progress_during_incremental_marking_finalization, 32,
"keep finalizing incremental marking as long as we discover at " "keep finalizing incremental marking as long as we discover at "
"least this many unmarked objects") "least this many unmarked objects")
...@@ -1300,6 +1304,7 @@ DEFINE_BOOL(single_threaded, false, "disable the use of background tasks") ...@@ -1300,6 +1304,7 @@ DEFINE_BOOL(single_threaded, false, "disable the use of background tasks")
DEFINE_NEG_IMPLICATION(single_threaded, concurrent_recompilation) DEFINE_NEG_IMPLICATION(single_threaded, concurrent_recompilation)
DEFINE_NEG_IMPLICATION(single_threaded, concurrent_marking) DEFINE_NEG_IMPLICATION(single_threaded, concurrent_marking)
DEFINE_NEG_IMPLICATION(single_threaded, concurrent_sweeping) DEFINE_NEG_IMPLICATION(single_threaded, concurrent_sweeping)
DEFINE_NEG_IMPLICATION(single_threaded, minor_mc_parallel_marking)
DEFINE_NEG_IMPLICATION(single_threaded, parallel_compaction) DEFINE_NEG_IMPLICATION(single_threaded, parallel_compaction)
DEFINE_NEG_IMPLICATION(single_threaded, parallel_pointer_update) DEFINE_NEG_IMPLICATION(single_threaded, parallel_pointer_update)
DEFINE_NEG_IMPLICATION(single_threaded, concurrent_store_buffer) DEFINE_NEG_IMPLICATION(single_threaded, concurrent_store_buffer)
......
...@@ -531,8 +531,8 @@ void GCTracer::PrintNVP() const { ...@@ -531,8 +531,8 @@ void GCTracer::PrintNVP() const {
"finish_sweeping=%.2f " "finish_sweeping=%.2f "
"mark=%.2f " "mark=%.2f "
"mark.identify_global_handles=%.2f " "mark.identify_global_handles=%.2f "
"mark.seed=%.2f "
"mark.roots=%.2f " "mark.roots=%.2f "
"mark.old_to_new=%.2f "
"mark.weak=%.2f " "mark.weak=%.2f "
"mark.global_handles=%.2f " "mark.global_handles=%.2f "
"clear=%.2f " "clear=%.2f "
...@@ -552,8 +552,8 @@ void GCTracer::PrintNVP() const { ...@@ -552,8 +552,8 @@ void GCTracer::PrintNVP() const {
current_.scopes[Scope::MINOR_MC_SWEEPING], current_.scopes[Scope::MINOR_MC_SWEEPING],
current_.scopes[Scope::MINOR_MC_MARK], current_.scopes[Scope::MINOR_MC_MARK],
current_.scopes[Scope::MINOR_MC_MARK_IDENTIFY_GLOBAL_HANDLES], current_.scopes[Scope::MINOR_MC_MARK_IDENTIFY_GLOBAL_HANDLES],
current_.scopes[Scope::MINOR_MC_MARK_SEED],
current_.scopes[Scope::MINOR_MC_MARK_ROOTS], current_.scopes[Scope::MINOR_MC_MARK_ROOTS],
current_.scopes[Scope::MINOR_MC_MARK_OLD_TO_NEW_POINTERS],
current_.scopes[Scope::MINOR_MC_MARK_WEAK], current_.scopes[Scope::MINOR_MC_MARK_WEAK],
current_.scopes[Scope::MINOR_MC_MARK_GLOBAL_HANDLES], current_.scopes[Scope::MINOR_MC_MARK_GLOBAL_HANDLES],
current_.scopes[Scope::MINOR_MC_CLEAR], current_.scopes[Scope::MINOR_MC_CLEAR],
......
...@@ -101,7 +101,7 @@ enum ScavengeSpeedMode { kForAllObjects, kForSurvivedObjects }; ...@@ -101,7 +101,7 @@ enum ScavengeSpeedMode { kForAllObjects, kForSurvivedObjects };
F(MINOR_MC_MARK) \ F(MINOR_MC_MARK) \
F(MINOR_MC_MARK_GLOBAL_HANDLES) \ F(MINOR_MC_MARK_GLOBAL_HANDLES) \
F(MINOR_MC_MARK_IDENTIFY_GLOBAL_HANDLES) \ F(MINOR_MC_MARK_IDENTIFY_GLOBAL_HANDLES) \
F(MINOR_MC_MARK_OLD_TO_NEW_POINTERS) \ F(MINOR_MC_MARK_SEED) \
F(MINOR_MC_MARK_ROOTS) \ F(MINOR_MC_MARK_ROOTS) \
F(MINOR_MC_MARK_WEAK) \ F(MINOR_MC_MARK_WEAK) \
F(MINOR_MC_MARKING_DEQUE) \ F(MINOR_MC_MARKING_DEQUE) \
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "src/heap/concurrent-marking.h" #include "src/heap/concurrent-marking.h"
#include "src/heap/gc-tracer.h" #include "src/heap/gc-tracer.h"
#include "src/heap/incremental-marking.h" #include "src/heap/incremental-marking.h"
#include "src/heap/item-parallel-job.h"
#include "src/heap/mark-compact-inl.h" #include "src/heap/mark-compact-inl.h"
#include "src/heap/object-stats.h" #include "src/heap/object-stats.h"
#include "src/heap/objects-visiting-inl.h" #include "src/heap/objects-visiting-inl.h"
...@@ -350,6 +351,12 @@ int MarkCompactCollectorBase::NumberOfPointerUpdateTasks(int pages) { ...@@ -350,6 +351,12 @@ int MarkCompactCollectorBase::NumberOfPointerUpdateTasks(int pages) {
: 1; : 1;
} }
int MinorMarkCompactCollector::NumberOfMarkingTasks() {
return FLAG_minor_mc_parallel_marking
? Min(NumberOfAvailableCores(), kNumMarkers)
: 1;
}
MarkCompactCollector::MarkCompactCollector(Heap* heap) MarkCompactCollector::MarkCompactCollector(Heap* heap)
: MarkCompactCollectorBase(heap), : MarkCompactCollectorBase(heap),
page_parallel_job_semaphore_(0), page_parallel_job_semaphore_(0),
...@@ -381,7 +388,9 @@ void MarkCompactCollector::SetUp() { ...@@ -381,7 +388,9 @@ void MarkCompactCollector::SetUp() {
} }
} }
void MinorMarkCompactCollector::SetUp() { marking_deque()->SetUp(); } void MinorMarkCompactCollector::SetUp() {
for (int i = 0; i < kNumMarkers; i++) marking_deque(i)->SetUp();
}
void MarkCompactCollector::TearDown() { void MarkCompactCollector::TearDown() {
AbortCompaction(); AbortCompaction();
...@@ -389,7 +398,9 @@ void MarkCompactCollector::TearDown() { ...@@ -389,7 +398,9 @@ void MarkCompactCollector::TearDown() {
delete code_flusher_; delete code_flusher_;
} }
void MinorMarkCompactCollector::TearDown() { marking_deque()->TearDown(); } void MinorMarkCompactCollector::TearDown() {
for (int i = 0; i < kNumMarkers; i++) marking_deque(i)->TearDown();
}
void MarkCompactCollector::AddEvacuationCandidate(Page* p) { void MarkCompactCollector::AddEvacuationCandidate(Page* p) {
DCHECK(!p->NeverEvacuate()); DCHECK(!p->NeverEvacuate());
...@@ -2477,8 +2488,8 @@ class YoungGenerationMarkingVisitor final ...@@ -2477,8 +2488,8 @@ class YoungGenerationMarkingVisitor final
} }
inline void MarkObjectViaMarkingDeque(HeapObject* object) { inline void MarkObjectViaMarkingDeque(HeapObject* object) {
if (ObjectMarking::WhiteToBlack<MarkBit::NON_ATOMIC>( if (ObjectMarking::WhiteToBlack<MarkBit::ATOMIC>(object,
object, marking_state(object))) { marking_state(object))) {
// Marking deque overflow is unsupported for the young generation. // Marking deque overflow is unsupported for the young generation.
CHECK(marking_deque_->Push(object)); CHECK(marking_deque_->Push(object));
} }
...@@ -2491,7 +2502,7 @@ class YoungGenerationMarkingVisitor final ...@@ -2491,7 +2502,7 @@ class YoungGenerationMarkingVisitor final
Object* target = *p; Object* target = *p;
if (heap_->InNewSpace(target)) { if (heap_->InNewSpace(target)) {
HeapObject* target_object = HeapObject::cast(target); HeapObject* target_object = HeapObject::cast(target);
if (ObjectMarking::WhiteToBlack<MarkBit::NON_ATOMIC>( if (ObjectMarking::WhiteToBlack<MarkBit::ATOMIC>(
target_object, marking_state(target_object))) { target_object, marking_state(target_object))) {
Visit(target_object); Visit(target_object);
} }
...@@ -2533,7 +2544,7 @@ class MinorMarkCompactCollector::RootMarkingVisitor : public RootVisitor { ...@@ -2533,7 +2544,7 @@ class MinorMarkCompactCollector::RootMarkingVisitor : public RootVisitor {
if (ObjectMarking::WhiteToBlack<MarkBit::NON_ATOMIC>( if (ObjectMarking::WhiteToBlack<MarkBit::NON_ATOMIC>(
object, marking_state(object))) { object, marking_state(object))) {
collector_->marking_visitor_->Visit(object); collector_->marking_visitor(kMainMarker)->Visit(object);
collector_->EmptyMarkingDeque(); collector_->EmptyMarkingDeque();
} }
} }
...@@ -2541,16 +2552,190 @@ class MinorMarkCompactCollector::RootMarkingVisitor : public RootVisitor { ...@@ -2541,16 +2552,190 @@ class MinorMarkCompactCollector::RootMarkingVisitor : public RootVisitor {
MinorMarkCompactCollector* collector_; MinorMarkCompactCollector* collector_;
}; };
class MarkingItem;
class PageMarkingItem;
class RootMarkingItem;
class YoungGenerationMarkingTask;
class MarkingItem : public ItemParallelJob::Item {
public:
virtual ~MarkingItem() {}
virtual void Process(YoungGenerationMarkingTask* task) = 0;
};
class YoungGenerationMarkingTask : public ItemParallelJob::Task {
public:
YoungGenerationMarkingTask(Isolate* isolate,
MinorMarkCompactCollector* collector,
MarkingDeque* marking_deque,
YoungGenerationMarkingVisitor* visitor
)
: ItemParallelJob::Task(isolate),
collector_(collector),
marking_deque_(marking_deque),
visitor_(visitor) {}
void RunInParallel() override {
double marking_time = 0.0;
{
TimedScope scope(&marking_time);
MarkingItem* item = nullptr;
while ((item = GetItem<MarkingItem>()) != nullptr) {
item->Process(this);
item->MarkFinished();
collector_->EmptySpecificMarkingDeque(marking_deque_, visitor_);
}
DCHECK(marking_deque_->IsEmpty());
}
if (FLAG_trace_minor_mc_parallel_marking) {
PrintIsolate(collector_->isolate(), "marking[%p]: time=%f\n",
static_cast<void*>(this), marking_time);
}
};
void MarkObject(Object* object) {
if (!collector_->heap()->InNewSpace(object)) return;
HeapObject* heap_object = HeapObject::cast(object);
if (ObjectMarking::WhiteToBlack<MarkBit::ATOMIC>(
heap_object, collector_->marking_state(heap_object))) {
visitor_->Visit(heap_object);
}
}
private:
MinorMarkCompactCollector* collector_;
MarkingDeque* marking_deque_;
YoungGenerationMarkingVisitor* visitor_;
};
class BatchedRootMarkingItem : public MarkingItem {
public:
explicit BatchedRootMarkingItem(std::vector<Object*>&& objects)
: objects_(objects) {}
virtual ~BatchedRootMarkingItem() {}
void Process(YoungGenerationMarkingTask* task) override {
for (Object* object : objects_) {
task->MarkObject(object);
}
}
private:
std::vector<Object*> objects_;
};
class PageMarkingItem : public MarkingItem {
public:
explicit PageMarkingItem(MemoryChunk* chunk) : chunk_(chunk) {}
virtual ~PageMarkingItem() {}
void Process(YoungGenerationMarkingTask* task) override {
base::LockGuard<base::RecursiveMutex> guard(chunk_->mutex());
MarkUntypedPointers(task);
MarkTypedPointers(task);
}
private:
inline Heap* heap() { return chunk_->heap(); }
void MarkUntypedPointers(YoungGenerationMarkingTask* task) {
RememberedSet<OLD_TO_NEW>::Iterate(chunk_, [this, task](Address slot) {
return CheckAndMarkObject(task, slot);
});
}
void MarkTypedPointers(YoungGenerationMarkingTask* task) {
Isolate* isolate = heap()->isolate();
RememberedSet<OLD_TO_NEW>::IterateTyped(
chunk_, [this, isolate, task](SlotType slot_type, Address host_addr,
Address slot) {
return UpdateTypedSlotHelper::UpdateTypedSlot(
isolate, slot_type, slot, [this, task](Object** slot) {
return CheckAndMarkObject(task,
reinterpret_cast<Address>(slot));
});
});
}
SlotCallbackResult CheckAndMarkObject(YoungGenerationMarkingTask* task,
Address slot_address) {
Object* object = *reinterpret_cast<Object**>(slot_address);
if (heap()->InNewSpace(object)) {
// Marking happens before flipping the young generation, so the object
// has to be in ToSpace.
DCHECK(heap()->InToSpace(object));
HeapObject* heap_object = reinterpret_cast<HeapObject*>(object);
task->MarkObject(heap_object);
return KEEP_SLOT;
}
return REMOVE_SLOT;
}
MemoryChunk* chunk_;
};
// This root visitor walks all roots and creates items bundling objects that
// are then processed later on. Slots have to be dereferenced as they could
// live on the native (C++) stack, which requires filtering out the indirection.
class MinorMarkCompactCollector::RootMarkingVisitorSeedOnly
: public RootVisitor {
public:
explicit RootMarkingVisitorSeedOnly(ItemParallelJob* job) : job_(job) {
buffered_objects_.reserve(kBufferSize);
}
void VisitRootPointer(Root root, Object** p) override {
if (!(*p)->IsHeapObject()) return;
AddObject(*p);
}
void VisitRootPointers(Root root, Object** start, Object** end) override {
for (Object** p = start; p < end; p++) {
if (!(*p)->IsHeapObject()) continue;
AddObject(*p);
}
}
void FlushObjects() {
job_->AddItem(new BatchedRootMarkingItem(std::move(buffered_objects_)));
// Moving leaves the container in a valid but unspecified state. Reusing the
// container requires a call without precondition that resets the state.
buffered_objects_.clear();
buffered_objects_.reserve(kBufferSize);
}
private:
// Bundling several objects together in items avoids issues with allocating
// and deallocating items; both are operations that are performed on the main
// thread.
static const int kBufferSize = 32;
void AddObject(Object* object) {
buffered_objects_.push_back(object);
if (buffered_objects_.size() == kBufferSize) FlushObjects();
}
ItemParallelJob* job_;
std::vector<Object*> buffered_objects_;
};
MinorMarkCompactCollector::MinorMarkCompactCollector(Heap* heap) MinorMarkCompactCollector::MinorMarkCompactCollector(Heap* heap)
: MarkCompactCollectorBase(heap), : MarkCompactCollectorBase(heap), page_parallel_job_semaphore_(0) {
marking_deque_(heap), for (int i = 0; i < kNumMarkers; i++) {
marking_visitor_( marking_deque_[i] = new MarkingDeque(heap);
new YoungGenerationMarkingVisitor(heap, &marking_deque_)), marking_visitor_[i] =
page_parallel_job_semaphore_(0) {} new YoungGenerationMarkingVisitor(heap, marking_deque_[i]);
}
}
MinorMarkCompactCollector::~MinorMarkCompactCollector() { MinorMarkCompactCollector::~MinorMarkCompactCollector() {
DCHECK_NOT_NULL(marking_visitor_); for (int i = 0; i < kNumMarkers; i++) {
delete marking_visitor_; DCHECK_NOT_NULL(marking_visitor_[i]);
DCHECK_NOT_NULL(marking_deque_[i]);
delete marking_visitor_[i];
delete marking_deque_[i];
}
} }
SlotCallbackResult MinorMarkCompactCollector::CheckAndMarkObject( SlotCallbackResult MinorMarkCompactCollector::CheckAndMarkObject(
...@@ -2563,8 +2748,9 @@ SlotCallbackResult MinorMarkCompactCollector::CheckAndMarkObject( ...@@ -2563,8 +2748,9 @@ SlotCallbackResult MinorMarkCompactCollector::CheckAndMarkObject(
HeapObject* heap_object = reinterpret_cast<HeapObject*>(object); HeapObject* heap_object = reinterpret_cast<HeapObject*>(object);
const MarkingState state = MarkingState::External(heap_object); const MarkingState state = MarkingState::External(heap_object);
if (ObjectMarking::WhiteToBlack<MarkBit::NON_ATOMIC>(heap_object, state)) { if (ObjectMarking::WhiteToBlack<MarkBit::NON_ATOMIC>(heap_object, state)) {
heap->minor_mark_compact_collector()->marking_visitor_->Visit( heap->minor_mark_compact_collector()
heap_object); ->marking_visitor(kMainMarker)
->Visit(heap_object);
} }
return KEEP_SLOT; return KEEP_SLOT;
} }
...@@ -2578,6 +2764,33 @@ static bool IsUnmarkedObjectForYoungGeneration(Heap* heap, Object** p) { ...@@ -2578,6 +2764,33 @@ static bool IsUnmarkedObjectForYoungGeneration(Heap* heap, Object** p) {
MarkingState::External(HeapObject::cast(*p))); MarkingState::External(HeapObject::cast(*p)));
} }
void MinorMarkCompactCollector::MarkRootSetInParallel() {
// Seed the root set (roots + old->new set).
ItemParallelJob job(isolate()->cancelable_task_manager(),
&page_parallel_job_semaphore_);
{
TRACE_GC(heap()->tracer(), GCTracer::Scope::MINOR_MC_MARK_SEED);
RootMarkingVisitorSeedOnly root_seed_visitor(&job);
heap()->IterateRoots(&root_seed_visitor, VISIT_ALL_IN_SCAVENGE);
RememberedSet<OLD_TO_NEW>::IterateMemoryChunks(
heap(), [&job](MemoryChunk* chunk) {
job.AddItem(new PageMarkingItem(chunk));
});
root_seed_visitor.FlushObjects();
}
{
TRACE_GC(heap()->tracer(), GCTracer::Scope::MINOR_MC_MARK_ROOTS);
const int num_tasks = NumberOfMarkingTasks();
for (int i = 0; i < num_tasks; i++) {
job.AddTask(new YoungGenerationMarkingTask(
isolate(), this, marking_deque(i), marking_visitor(i)));
}
job.Run();
}
}
void MinorMarkCompactCollector::MarkLiveObjects() { void MinorMarkCompactCollector::MarkLiveObjects() {
TRACE_GC(heap()->tracer(), GCTracer::Scope::MINOR_MC_MARK); TRACE_GC(heap()->tracer(), GCTracer::Scope::MINOR_MC_MARK);
...@@ -2585,7 +2798,7 @@ void MinorMarkCompactCollector::MarkLiveObjects() { ...@@ -2585,7 +2798,7 @@ void MinorMarkCompactCollector::MarkLiveObjects() {
RootMarkingVisitor root_visitor(this); RootMarkingVisitor root_visitor(this);
marking_deque()->StartUsing(); for (int i = 0; i < kNumMarkers; i++) marking_deque(i)->StartUsing();
{ {
TRACE_GC(heap()->tracer(), TRACE_GC(heap()->tracer(),
...@@ -2594,30 +2807,9 @@ void MinorMarkCompactCollector::MarkLiveObjects() { ...@@ -2594,30 +2807,9 @@ void MinorMarkCompactCollector::MarkLiveObjects() {
&Heap::IsUnmodifiedHeapObject); &Heap::IsUnmodifiedHeapObject);
} }
{ MarkRootSetInParallel();
TRACE_GC(heap()->tracer(), GCTracer::Scope::MINOR_MC_MARK_ROOTS);
heap()->IterateRoots(&root_visitor, VISIT_ALL_IN_SCAVENGE);
ProcessMarkingDeque();
}
{
TRACE_GC(heap()->tracer(),
GCTracer::Scope::MINOR_MC_MARK_OLD_TO_NEW_POINTERS);
RememberedSet<OLD_TO_NEW>::Iterate(
heap(), NON_SYNCHRONIZED,
[this](Address addr) { return CheckAndMarkObject(heap(), addr); });
RememberedSet<OLD_TO_NEW>::IterateTyped(
heap(), NON_SYNCHRONIZED,
[this](SlotType type, Address host_addr, Address addr) {
return UpdateTypedSlotHelper::UpdateTypedSlot(
isolate(), type, addr, [this](Object** addr) {
return CheckAndMarkObject(heap(),
reinterpret_cast<Address>(addr));
});
});
ProcessMarkingDeque();
}
// Mark rest on the main thread.
{ {
TRACE_GC(heap()->tracer(), GCTracer::Scope::MINOR_MC_MARK_WEAK); TRACE_GC(heap()->tracer(), GCTracer::Scope::MINOR_MC_MARK_WEAK);
heap()->IterateEncounteredWeakCollections(&root_visitor); heap()->IterateEncounteredWeakCollections(&root_visitor);
...@@ -2633,30 +2825,35 @@ void MinorMarkCompactCollector::MarkLiveObjects() { ...@@ -2633,30 +2825,35 @@ void MinorMarkCompactCollector::MarkLiveObjects() {
ProcessMarkingDeque(); ProcessMarkingDeque();
} }
marking_deque()->StopUsing(); for (int i = 0; i < kNumMarkers; i++) marking_deque(i)->StopUsing();
} }
void MinorMarkCompactCollector::ProcessMarkingDeque() { void MinorMarkCompactCollector::ProcessMarkingDeque() {
EmptyMarkingDeque(); EmptyMarkingDeque();
DCHECK(!marking_deque()->overflowed()); DCHECK(!marking_deque(kMainMarker)->overflowed());
DCHECK(marking_deque()->IsEmpty()); DCHECK(marking_deque(kMainMarker)->IsEmpty());
} }
void MinorMarkCompactCollector::EmptyMarkingDeque() { void MinorMarkCompactCollector::EmptySpecificMarkingDeque(
while (!marking_deque()->IsEmpty()) { MarkingDeque* marking_deque, YoungGenerationMarkingVisitor* visitor) {
HeapObject* object = marking_deque()->Pop(); while (!marking_deque->IsEmpty()) {
HeapObject* object = marking_deque->Pop();
DCHECK(!object->IsFiller()); DCHECK(!object->IsFiller());
DCHECK(object->IsHeapObject()); DCHECK(object->IsHeapObject());
DCHECK(heap()->Contains(object)); DCHECK(heap()->Contains(object));
DCHECK(!(ObjectMarking::IsWhite<MarkBit::NON_ATOMIC>( DCHECK(!(ObjectMarking::IsWhite<MarkBit::NON_ATOMIC>(
object, marking_state(object)))); object, marking_state(object))));
DCHECK((ObjectMarking::IsBlack<MarkBit::NON_ATOMIC>( DCHECK((ObjectMarking::IsBlack<MarkBit::NON_ATOMIC>(
object, marking_state(object)))); object, marking_state(object))));
marking_visitor_->Visit(object); visitor->Visit(object);
} }
DCHECK(!marking_deque->overflowed());
DCHECK(marking_deque->IsEmpty());
}
void MinorMarkCompactCollector::EmptyMarkingDeque() {
EmptySpecificMarkingDeque(marking_deque(kMainMarker),
marking_visitor(kMainMarker));
} }
void MinorMarkCompactCollector::CollectGarbage() { void MinorMarkCompactCollector::CollectGarbage() {
......
...@@ -360,14 +360,29 @@ class MinorMarkCompactCollector final : public MarkCompactCollectorBase { ...@@ -360,14 +360,29 @@ class MinorMarkCompactCollector final : public MarkCompactCollectorBase {
void CleanupSweepToIteratePages(); void CleanupSweepToIteratePages();
private: private:
class RootMarkingVisitorSeedOnly;
class RootMarkingVisitor; class RootMarkingVisitor;
inline MarkingDeque* marking_deque() { return &marking_deque_; } static const int kNumMarkers = 4;
static const int kMainMarker = 0;
inline MarkingDeque* marking_deque(int index) {
DCHECK_LT(index, kNumMarkers);
return marking_deque_[index];
}
inline YoungGenerationMarkingVisitor* marking_visitor(int index) {
DCHECK_LT(index, kNumMarkers);
return marking_visitor_[index];
}
SlotCallbackResult CheckAndMarkObject(Heap* heap, Address slot_address); SlotCallbackResult CheckAndMarkObject(Heap* heap, Address slot_address);
void MarkLiveObjects() override; void MarkLiveObjects() override;
void MarkRootSetInParallel();
void ProcessMarkingDeque() override; void ProcessMarkingDeque() override;
void EmptyMarkingDeque() override; void EmptyMarkingDeque() override;
void EmptySpecificMarkingDeque(MarkingDeque* marking_deque,
YoungGenerationMarkingVisitor* visitor);
void ClearNonLiveReferences() override; void ClearNonLiveReferences() override;
void EvacuatePrologue() override; void EvacuatePrologue() override;
...@@ -376,12 +391,16 @@ class MinorMarkCompactCollector final : public MarkCompactCollectorBase { ...@@ -376,12 +391,16 @@ class MinorMarkCompactCollector final : public MarkCompactCollectorBase {
void EvacuatePagesInParallel() override; void EvacuatePagesInParallel() override;
void UpdatePointersAfterEvacuation() override; void UpdatePointersAfterEvacuation() override;
MarkingDeque marking_deque_; int NumberOfMarkingTasks();
YoungGenerationMarkingVisitor* marking_visitor_;
MarkingDeque* marking_deque_[kNumMarkers];
YoungGenerationMarkingVisitor* marking_visitor_[kNumMarkers];
base::Semaphore page_parallel_job_semaphore_; base::Semaphore page_parallel_job_semaphore_;
List<Page*> new_space_evacuation_pages_; List<Page*> new_space_evacuation_pages_;
std::vector<Page*> sweep_to_iterate_pages_; std::vector<Page*> sweep_to_iterate_pages_;
friend class MarkYoungGenerationJobTraits;
friend class YoungGenerationMarkingTask;
friend class YoungGenerationMarkingVisitor; friend class YoungGenerationMarkingVisitor;
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment