[heap] Implement concurrent marking boilerplate.
This patch adds a trivial ConcurrentMarking class that can start background tasks. BUG=chromium:694255 Review-Url: https://codereview.chromium.org/2728363002 Cr-Commit-Position: refs/heads/master@{#43615}
This commit is contained in:
parent
3c63c40f3e
commit
e96b5ed423
2
BUILD.gn
2
BUILD.gn
@ -1431,6 +1431,8 @@ v8_source_set("v8_base") {
|
||||
"src/heap/array-buffer-tracker.h",
|
||||
"src/heap/code-stats.cc",
|
||||
"src/heap/code-stats.h",
|
||||
"src/heap/concurrent-marking.cc",
|
||||
"src/heap/concurrent-marking.h",
|
||||
"src/heap/embedder-tracing.cc",
|
||||
"src/heap/embedder-tracing.h",
|
||||
"src/heap/gc-idle-time-handler.cc",
|
||||
|
@ -647,6 +647,7 @@ DEFINE_BOOL(age_code, true,
|
||||
DEFINE_BOOL(incremental_marking, true, "use incremental marking")
|
||||
DEFINE_BOOL(incremental_marking_wrappers, true,
|
||||
"use incremental marking for marking wrappers")
|
||||
DEFINE_BOOL(concurrent_marking, false, "use concurrent marking")
|
||||
DEFINE_INT(min_progress_during_incremental_marking_finalization, 32,
|
||||
"keep finalizing incremental marking as long as we discover at "
|
||||
"least this many unmarked objects")
|
||||
|
81
src/heap/concurrent-marking.cc
Normal file
81
src/heap/concurrent-marking.cc
Normal file
@ -0,0 +1,81 @@
|
||||
// Copyright 2017 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "src/heap/concurrent-marking.h"
|
||||
|
||||
#include "src/heap/heap-inl.h"
|
||||
#include "src/heap/heap.h"
|
||||
#include "src/isolate.h"
|
||||
#include "src/locked-queue-inl.h"
|
||||
#include "src/v8.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
class ConcurrentMarking::Task : public CancelableTask {
|
||||
public:
|
||||
Task(Heap* heap, Queue* queue, base::Semaphore* on_finish)
|
||||
: CancelableTask(heap->isolate()),
|
||||
heap_(heap),
|
||||
queue_(queue),
|
||||
on_finish_(on_finish) {}
|
||||
|
||||
virtual ~Task() {}
|
||||
|
||||
private:
|
||||
// v8::internal::CancelableTask overrides.
|
||||
void RunInternal() override {
|
||||
USE(heap_);
|
||||
HeapObject* object;
|
||||
while (queue_->Dequeue(&object)) {
|
||||
// TODO(ulan): Implement actual marking.
|
||||
}
|
||||
on_finish_->Signal();
|
||||
}
|
||||
|
||||
Heap* heap_;
|
||||
Queue* queue_;
|
||||
base::Semaphore* on_finish_;
|
||||
DISALLOW_COPY_AND_ASSIGN(Task);
|
||||
};
|
||||
|
||||
ConcurrentMarking::ConcurrentMarking(Heap* heap)
|
||||
: heap_(heap), pending_tasks_(0), number_of_tasks_(0) {}
|
||||
|
||||
ConcurrentMarking::~ConcurrentMarking() {}
|
||||
|
||||
void ConcurrentMarking::EnqueueObject(HeapObject* object) {
|
||||
queue_.Enqueue(object);
|
||||
}
|
||||
|
||||
bool ConcurrentMarking::IsQueueEmpty() { return queue_.IsEmpty(); }
|
||||
|
||||
void ConcurrentMarking::StartMarkingTasks(int number_of_tasks) {
|
||||
if (!FLAG_concurrent_marking) return;
|
||||
DCHECK_EQ(0, number_of_tasks_);
|
||||
|
||||
number_of_tasks_ = number_of_tasks;
|
||||
for (int i = 0; i < number_of_tasks; i++) {
|
||||
V8::GetCurrentPlatform()->CallOnBackgroundThread(
|
||||
new Task(heap_, &queue_, &pending_tasks_),
|
||||
v8::Platform::kShortRunningTask);
|
||||
}
|
||||
}
|
||||
|
||||
void ConcurrentMarking::WaitForTasksToComplete() {
|
||||
if (!FLAG_concurrent_marking) return;
|
||||
|
||||
CancelableTaskManager* cancelable_task_manager =
|
||||
heap_->isolate()->cancelable_task_manager();
|
||||
for (int i = 0; i < number_of_tasks_; i++) {
|
||||
if (cancelable_task_manager->TryAbort(task_ids_[i]) !=
|
||||
CancelableTaskManager::kTaskAborted) {
|
||||
pending_tasks_.Wait();
|
||||
}
|
||||
}
|
||||
number_of_tasks_ = 0;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
48
src/heap/concurrent-marking.h
Normal file
48
src/heap/concurrent-marking.h
Normal file
@ -0,0 +1,48 @@
|
||||
// Copyright 2017 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_HEAP_CONCURRENT_MARKING_
|
||||
#define V8_HEAP_CONCURRENT_MARKING_
|
||||
|
||||
#include "src/allocation.h"
|
||||
#include "src/cancelable-task.h"
|
||||
#include "src/locked-queue.h"
|
||||
#include "src/utils.h"
|
||||
#include "src/v8.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
class Heap;
|
||||
class Isolate;
|
||||
|
||||
class ConcurrentMarking {
|
||||
public:
|
||||
static const int kMaxNumberOfTasks = 10;
|
||||
|
||||
explicit ConcurrentMarking(Heap* heap);
|
||||
~ConcurrentMarking();
|
||||
|
||||
void EnqueueObject(HeapObject* object);
|
||||
bool IsQueueEmpty();
|
||||
|
||||
void StartMarkingTasks(int number_of_tasks);
|
||||
void WaitForTasksToComplete();
|
||||
|
||||
private:
|
||||
class Task;
|
||||
// TODO(ulan): Replace with faster queue.
|
||||
typedef LockedQueue<HeapObject*> Queue;
|
||||
|
||||
Heap* heap_;
|
||||
base::Semaphore pending_tasks_;
|
||||
Queue queue_;
|
||||
int number_of_tasks_;
|
||||
uint32_t task_ids_[kMaxNumberOfTasks];
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_HEAP_PAGE_PARALLEL_JOB_
|
@ -22,6 +22,7 @@
|
||||
#include "src/global-handles.h"
|
||||
#include "src/heap/array-buffer-tracker-inl.h"
|
||||
#include "src/heap/code-stats.h"
|
||||
#include "src/heap/concurrent-marking.h"
|
||||
#include "src/heap/embedder-tracing.h"
|
||||
#include "src/heap/gc-idle-time-handler.h"
|
||||
#include "src/heap/gc-tracer.h"
|
||||
@ -135,6 +136,7 @@ Heap::Heap()
|
||||
memory_allocator_(nullptr),
|
||||
store_buffer_(nullptr),
|
||||
incremental_marking_(nullptr),
|
||||
concurrent_marking_(nullptr),
|
||||
gc_idle_time_handler_(nullptr),
|
||||
memory_reducer_(nullptr),
|
||||
live_object_stats_(nullptr),
|
||||
@ -5500,12 +5502,12 @@ bool Heap::SetUp() {
|
||||
code_range_size_))
|
||||
return false;
|
||||
|
||||
// Initialize store buffer.
|
||||
store_buffer_ = new StoreBuffer(this);
|
||||
|
||||
// Initialize incremental marking.
|
||||
incremental_marking_ = new IncrementalMarking(this);
|
||||
|
||||
concurrent_marking_ = new ConcurrentMarking(this);
|
||||
|
||||
for (int i = 0; i <= LAST_SPACE; i++) {
|
||||
space_[i] = nullptr;
|
||||
}
|
||||
@ -5690,6 +5692,9 @@ void Heap::TearDown() {
|
||||
delete incremental_marking_;
|
||||
incremental_marking_ = nullptr;
|
||||
|
||||
delete concurrent_marking_;
|
||||
concurrent_marking_ = nullptr;
|
||||
|
||||
delete gc_idle_time_handler_;
|
||||
gc_idle_time_handler_ = nullptr;
|
||||
|
||||
|
@ -318,6 +318,7 @@ using v8::MemoryPressureLevel;
|
||||
// Forward declarations.
|
||||
class AllocationObserver;
|
||||
class ArrayBufferTracker;
|
||||
class ConcurrentMarking;
|
||||
class GCIdleTimeAction;
|
||||
class GCIdleTimeHandler;
|
||||
class GCIdleTimeHeapState;
|
||||
@ -2290,6 +2291,7 @@ class Heap {
|
||||
StoreBuffer* store_buffer_;
|
||||
|
||||
IncrementalMarking* incremental_marking_;
|
||||
ConcurrentMarking* concurrent_marking_;
|
||||
|
||||
GCIdleTimeHandler* gc_idle_time_handler_;
|
||||
|
||||
@ -2373,6 +2375,7 @@ class Heap {
|
||||
|
||||
// Classes in "heap" can be friends.
|
||||
friend class AlwaysAllocateScope;
|
||||
friend class ConcurrentMarking;
|
||||
friend class GCCallbacksScope;
|
||||
friend class GCTracer;
|
||||
friend class HeapIterator;
|
||||
|
@ -933,6 +933,8 @@
|
||||
'heap/array-buffer-tracker.h',
|
||||
'heap/code-stats.cc',
|
||||
'heap/code-stats.h',
|
||||
'heap/concurrent-marking.cc',
|
||||
'heap/concurrent-marking.h',
|
||||
'heap/embedder-tracing.cc',
|
||||
'heap/embedder-tracing.h',
|
||||
'heap/memory-reducer.cc',
|
||||
|
@ -73,6 +73,7 @@ v8_executable("cctest") {
|
||||
"heap/test-alloc.cc",
|
||||
"heap/test-array-buffer-tracker.cc",
|
||||
"heap/test-compaction.cc",
|
||||
"heap/test-concurrent-marking.cc",
|
||||
"heap/test-heap.cc",
|
||||
"heap/test-incremental-marking.cc",
|
||||
"heap/test-lab.cc",
|
||||
|
@ -104,6 +104,7 @@
|
||||
'heap/test-alloc.cc',
|
||||
'heap/test-array-buffer-tracker.cc',
|
||||
'heap/test-compaction.cc',
|
||||
'heap/test-concurrent-marking.cc',
|
||||
'heap/test-heap.cc',
|
||||
'heap/test-incremental-marking.cc',
|
||||
'heap/test-lab.cc',
|
||||
|
33
test/cctest/heap/test-concurrent-marking.cc
Normal file
33
test/cctest/heap/test-concurrent-marking.cc
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright 2017 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "src/v8.h"
|
||||
|
||||
#include "src/heap/concurrent-marking.h"
|
||||
#include "src/heap/heap-inl.h"
|
||||
#include "src/heap/heap.h"
|
||||
#include "test/cctest/cctest.h"
|
||||
#include "test/cctest/heap/heap-utils.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
TEST(ConcurrentMarking) {
|
||||
i::FLAG_concurrent_marking = true;
|
||||
CcTest::InitializeVM();
|
||||
Heap* heap = CcTest::heap();
|
||||
ConcurrentMarking* concurrent_marking = new ConcurrentMarking(heap);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
concurrent_marking->EnqueueObject(heap->undefined_value());
|
||||
}
|
||||
concurrent_marking->StartMarkingTasks(3);
|
||||
while (!concurrent_marking->IsQueueEmpty()) {
|
||||
}
|
||||
concurrent_marking->WaitForTasksToComplete();
|
||||
delete concurrent_marking;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
Loading…
Reference in New Issue
Block a user