Commit 3477957e authored by ulan's avatar ulan Committed by Commit bot

[heap] Start concurrent marking simultaneously with incremental marking.

This patch hooks up concurrent marking (behind the flag) with the rest
of the GC:
1. Incremental marking spawns concurrent marking task seeded with the
root set.
2. Mark-compact waits for concurrent marking tasks to finish.
3. Scavenger does fast promotion if concurrent marking is pending.

BUG=chromium:694255

Review-Url: https://codereview.chromium.org/2735803005
Cr-Commit-Position: refs/heads/master@{#44526}
parent 85b1f108
...@@ -654,6 +654,7 @@ DEFINE_BOOL(incremental_marking, true, "use incremental marking") ...@@ -654,6 +654,7 @@ DEFINE_BOOL(incremental_marking, true, "use incremental marking")
DEFINE_BOOL(incremental_marking_wrappers, true, DEFINE_BOOL(incremental_marking_wrappers, true,
"use incremental marking for marking wrappers") "use incremental marking for marking wrappers")
DEFINE_BOOL(concurrent_marking, false, "use concurrent marking") DEFINE_BOOL(concurrent_marking, false, "use concurrent marking")
DEFINE_BOOL(trace_concurrent_marking, false, "trace concurrent marking")
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")
...@@ -1283,6 +1284,7 @@ DEFINE_VALUE_IMPLICATION(single_threaded, wasm_num_compilation_tasks, 0) ...@@ -1283,6 +1284,7 @@ DEFINE_VALUE_IMPLICATION(single_threaded, wasm_num_compilation_tasks, 0)
DEFINE_BOOL(single_threaded, false, "disable the use of background tasks") 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_sweeping) DEFINE_NEG_IMPLICATION(single_threaded, concurrent_sweeping)
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)
......
...@@ -118,6 +118,7 @@ namespace internal { ...@@ -118,6 +118,7 @@ namespace internal {
#define V8_DOUBLE_FIELDS_UNBOXING 0 #define V8_DOUBLE_FIELDS_UNBOXING 0
#endif #endif
#define V8_CONCURRENT_MARKING 0
typedef uint8_t byte; typedef uint8_t byte;
typedef byte* Address; typedef byte* Address;
......
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
#include "src/heap/marking.h" #include "src/heap/marking.h"
#include "src/isolate.h" #include "src/isolate.h"
#include "src/locked-queue-inl.h" #include "src/locked-queue-inl.h"
#include "src/utils-inl.h"
#include "src/utils.h"
#include "src/v8.h" #include "src/v8.h"
namespace v8 { namespace v8 {
...@@ -50,7 +52,7 @@ class ConcurrentMarkingMarkbits { ...@@ -50,7 +52,7 @@ class ConcurrentMarkingMarkbits {
class ConcurrentMarkingVisitor : public ObjectVisitor { class ConcurrentMarkingVisitor : public ObjectVisitor {
public: public:
ConcurrentMarkingVisitor() {} ConcurrentMarkingVisitor() : bytes_marked_(0) {}
void VisitPointers(Object** start, Object** end) override { void VisitPointers(Object** start, Object** end) override {
for (Object** p = start; p < end; p++) { for (Object** p = start; p < end; p++) {
...@@ -61,6 +63,7 @@ class ConcurrentMarkingVisitor : public ObjectVisitor { ...@@ -61,6 +63,7 @@ class ConcurrentMarkingVisitor : public ObjectVisitor {
void MarkObject(HeapObject* obj) { void MarkObject(HeapObject* obj) {
if (markbits_.Mark(obj)) { if (markbits_.Mark(obj)) {
bytes_marked_ += obj->Size();
marking_stack_.push(obj); marking_stack_.push(obj);
} }
} }
...@@ -73,7 +76,10 @@ class ConcurrentMarkingVisitor : public ObjectVisitor { ...@@ -73,7 +76,10 @@ class ConcurrentMarkingVisitor : public ObjectVisitor {
} }
} }
size_t bytes_marked() { return bytes_marked_; }
private: private:
size_t bytes_marked_;
std::stack<HeapObject*> marking_stack_; std::stack<HeapObject*> marking_stack_;
ConcurrentMarkingMarkbits markbits_; ConcurrentMarkingMarkbits markbits_;
}; };
...@@ -92,11 +98,19 @@ class ConcurrentMarking::Task : public CancelableTask { ...@@ -92,11 +98,19 @@ class ConcurrentMarking::Task : public CancelableTask {
private: private:
// v8::internal::CancelableTask overrides. // v8::internal::CancelableTask overrides.
void RunInternal() override { void RunInternal() override {
USE(heap_); double time_ms = heap_->MonotonicallyIncreasingTimeInMs();
for (HeapObject* obj : *root_set_) { {
marking_visitor_.MarkObject(obj); TimedScope scope(&time_ms);
for (HeapObject* obj : *root_set_) {
marking_visitor_.MarkObject(obj);
}
marking_visitor_.MarkTransitively();
}
if (FLAG_trace_concurrent_marking) {
heap_->isolate()->PrintWithTimestamp(
"concurrently marked %dKB in %.2fms\n",
static_cast<int>(marking_visitor_.bytes_marked() / KB), time_ms);
} }
marking_visitor_.MarkTransitively();
on_finish_->Signal(); on_finish_->Signal();
} }
...@@ -108,7 +122,12 @@ class ConcurrentMarking::Task : public CancelableTask { ...@@ -108,7 +122,12 @@ class ConcurrentMarking::Task : public CancelableTask {
}; };
ConcurrentMarking::ConcurrentMarking(Heap* heap) ConcurrentMarking::ConcurrentMarking(Heap* heap)
: heap_(heap), pending_task_(0) {} : heap_(heap), pending_task_semaphore_(0), is_task_pending_(false) {
// Concurrent marking does not work with double unboxing.
STATIC_ASSERT(!(V8_CONCURRENT_MARKING && V8_DOUBLE_FIELDS_UNBOXING));
// The runtime flag should be set only if the compile time flag was set.
CHECK(!FLAG_concurrent_marking || V8_CONCURRENT_MARKING);
}
ConcurrentMarking::~ConcurrentMarking() {} ConcurrentMarking::~ConcurrentMarking() {}
...@@ -116,17 +135,26 @@ void ConcurrentMarking::AddRoot(HeapObject* object) { ...@@ -116,17 +135,26 @@ void ConcurrentMarking::AddRoot(HeapObject* object) {
root_set_.push_back(object); root_set_.push_back(object);
} }
void ConcurrentMarking::StartMarkingTask() { void ConcurrentMarking::StartTask() {
if (!FLAG_concurrent_marking) return; if (!FLAG_concurrent_marking) return;
is_task_pending_ = true;
V8::GetCurrentPlatform()->CallOnBackgroundThread( V8::GetCurrentPlatform()->CallOnBackgroundThread(
new Task(heap_, &root_set_, &pending_task_), new Task(heap_, &root_set_, &pending_task_semaphore_),
v8::Platform::kShortRunningTask); v8::Platform::kShortRunningTask);
} }
void ConcurrentMarking::WaitForTaskToComplete() { void ConcurrentMarking::WaitForTaskToComplete() {
if (!FLAG_concurrent_marking) return; if (!FLAG_concurrent_marking) return;
pending_task_.Wait(); pending_task_semaphore_.Wait();
is_task_pending_ = false;
root_set_.clear();
}
void ConcurrentMarking::EnsureTaskCompleted() {
if (IsTaskPending()) {
WaitForTaskToComplete();
}
} }
} // namespace internal } // namespace internal
......
...@@ -25,13 +25,16 @@ class ConcurrentMarking { ...@@ -25,13 +25,16 @@ class ConcurrentMarking {
void AddRoot(HeapObject* object); void AddRoot(HeapObject* object);
void StartMarkingTask(); void StartTask();
void WaitForTaskToComplete(); void WaitForTaskToComplete();
bool IsTaskPending() { return is_task_pending_; }
void EnsureTaskCompleted();
private: private:
class Task; class Task;
Heap* heap_; Heap* heap_;
base::Semaphore pending_task_; base::Semaphore pending_task_semaphore_;
bool is_task_pending_;
std::vector<HeapObject*> root_set_; std::vector<HeapObject*> root_set_;
}; };
......
...@@ -1353,8 +1353,9 @@ bool Heap::PerformGarbageCollection( ...@@ -1353,8 +1353,9 @@ bool Heap::PerformGarbageCollection(
MinorMarkCompact(); MinorMarkCompact();
break; break;
case SCAVENGER: case SCAVENGER:
if (fast_promotion_mode_ && if ((fast_promotion_mode_ &&
CanExpandOldGeneration(new_space()->Size())) { CanExpandOldGeneration(new_space()->Size())) ||
concurrent_marking_->IsTaskPending()) {
tracer()->NotifyYoungGenerationHandling( tracer()->NotifyYoungGenerationHandling(
YoungGenerationHandling::kFastPromotionDuringScavenge); YoungGenerationHandling::kFastPromotionDuringScavenge);
EvacuateYoungGeneration(); EvacuateYoungGeneration();
...@@ -1626,8 +1627,10 @@ class ScavengeWeakObjectRetainer : public WeakObjectRetainer { ...@@ -1626,8 +1627,10 @@ class ScavengeWeakObjectRetainer : public WeakObjectRetainer {
void Heap::EvacuateYoungGeneration() { void Heap::EvacuateYoungGeneration() {
TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_EVACUATE); TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_EVACUATE);
DCHECK(fast_promotion_mode_); if (!FLAG_concurrent_marking) {
DCHECK(CanExpandOldGeneration(new_space()->Size())); DCHECK(fast_promotion_mode_);
DCHECK(CanExpandOldGeneration(new_space()->Size()));
}
mark_compact_collector()->sweeper().EnsureNewSpaceCompleted(); mark_compact_collector()->sweeper().EnsureNewSpaceCompleted();
......
...@@ -1239,6 +1239,12 @@ class Heap { ...@@ -1239,6 +1239,12 @@ class Heap {
IncrementalMarking* incremental_marking() { return incremental_marking_; } IncrementalMarking* incremental_marking() { return incremental_marking_; }
// ===========================================================================
// Concurrent marking API. ===================================================
// ===========================================================================
ConcurrentMarking* concurrent_marking() { return concurrent_marking_; }
// The runtime uses this function to notify potentially unsafe object layout // The runtime uses this function to notify potentially unsafe object layout
// changes that require special synchronization with the concurrent marker. // changes that require special synchronization with the concurrent marker.
// A layout change is unsafe if // A layout change is unsafe if
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "src/code-stubs.h" #include "src/code-stubs.h"
#include "src/compilation-cache.h" #include "src/compilation-cache.h"
#include "src/conversions.h" #include "src/conversions.h"
#include "src/heap/concurrent-marking.h"
#include "src/heap/gc-idle-time-handler.h" #include "src/heap/gc-idle-time-handler.h"
#include "src/heap/gc-tracer.h" #include "src/heap/gc-tracer.h"
#include "src/heap/heap-inl.h" #include "src/heap/heap-inl.h"
...@@ -545,6 +546,15 @@ void IncrementalMarking::StartMarking() { ...@@ -545,6 +546,15 @@ void IncrementalMarking::StartMarking() {
IncrementalMarkingRootMarkingVisitor visitor(this); IncrementalMarkingRootMarkingVisitor visitor(this);
heap_->IterateStrongRoots(&visitor, VISIT_ONLY_STRONG); heap_->IterateStrongRoots(&visitor, VISIT_ONLY_STRONG);
if (FLAG_concurrent_marking) {
ConcurrentMarking* concurrent_marking = heap_->concurrent_marking();
heap_->mark_compact_collector()->marking_deque()->Iterate(
[concurrent_marking](HeapObject* obj) {
concurrent_marking->AddRoot(obj);
});
concurrent_marking->StartTask();
}
// Ready to start incremental marking. // Ready to start incremental marking.
if (FLAG_trace_incremental_marking) { if (FLAG_trace_incremental_marking) {
heap()->isolate()->PrintWithTimestamp("[IncrementalMarking] Running\n"); heap()->isolate()->PrintWithTimestamp("[IncrementalMarking] Running\n");
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "src/gdb-jit.h" #include "src/gdb-jit.h"
#include "src/global-handles.h" #include "src/global-handles.h"
#include "src/heap/array-buffer-tracker.h" #include "src/heap/array-buffer-tracker.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/mark-compact-inl.h" #include "src/heap/mark-compact-inl.h"
...@@ -847,6 +848,8 @@ void MarkCompactCollector::Prepare() { ...@@ -847,6 +848,8 @@ void MarkCompactCollector::Prepare() {
// them here. // them here.
heap()->memory_allocator()->unmapper()->WaitUntilCompleted(); heap()->memory_allocator()->unmapper()->WaitUntilCompleted();
heap()->concurrent_marking()->EnsureTaskCompleted();
// Clear marking bits if incremental marking is aborted. // Clear marking bits if incremental marking is aborted.
if (was_marked_incrementally_ && heap_->ShouldAbortIncrementalMarking()) { if (was_marked_incrementally_ && heap_->ShouldAbortIncrementalMarking()) {
heap()->incremental_marking()->Stop(); heap()->incremental_marking()->Stop();
......
...@@ -186,6 +186,15 @@ class MarkingDeque { ...@@ -186,6 +186,15 @@ class MarkingDeque {
} }
} }
template <typename Callback>
void Iterate(Callback callback) {
int i = bottom_;
while (i != top_) {
callback(array_[i]);
i = (i + 1) & mask_;
}
}
HeapObject** array() { return array_; } HeapObject** array() { return array_; }
int bottom() { return bottom_; } int bottom() { return bottom_; }
int top() { return top_; } int top() { return top_; }
......
...@@ -15,12 +15,12 @@ ...@@ -15,12 +15,12 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
TEST(ConcurrentMarking) { TEST(ConcurrentMarking) {
i::FLAG_concurrent_marking = true; if (!i::FLAG_concurrent_marking) return;
CcTest::InitializeVM(); CcTest::InitializeVM();
Heap* heap = CcTest::heap(); Heap* heap = CcTest::heap();
ConcurrentMarking* concurrent_marking = new ConcurrentMarking(heap); ConcurrentMarking* concurrent_marking = new ConcurrentMarking(heap);
concurrent_marking->AddRoot(heap->undefined_value()); concurrent_marking->AddRoot(heap->undefined_value());
concurrent_marking->StartMarkingTask(); concurrent_marking->StartTask();
concurrent_marking->WaitForTaskToComplete(); concurrent_marking->WaitForTaskToComplete();
delete concurrent_marking; delete concurrent_marking;
} }
......
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