Commit a3923ce2 authored by ulan's avatar ulan Committed by Commit bot

[heap] Implement simple marking in the concurrent marking thread.

The concurrent marker uses ObjectVisitor to iterate pointers in objects
and local marking bitmaps to keep track of visited objects.

To keep it simple for now, I removed support for multiple tasks
and canceling unfinished tasks.

BUG=chromium:694255

Review-Url: https://codereview.chromium.org/2732053002
Cr-Commit-Position: refs/heads/master@{#43618}
parent 1338ae97
......@@ -4,8 +4,12 @@
#include "src/heap/concurrent-marking.h"
#include <stack>
#include <unordered_map>
#include "src/heap/heap-inl.h"
#include "src/heap/heap.h"
#include "src/heap/marking.h"
#include "src/isolate.h"
#include "src/locked-queue-inl.h"
#include "src/v8.h"
......@@ -13,13 +17,75 @@
namespace v8 {
namespace internal {
class ConcurrentMarkingMarkbits {
public:
ConcurrentMarkingMarkbits() {}
~ConcurrentMarkingMarkbits() {
for (auto chunk_bitmap : bitmap_) {
FreeBitmap(chunk_bitmap.second);
}
}
bool Mark(HeapObject* obj) {
Address address = obj->address();
MemoryChunk* chunk = MemoryChunk::FromAddress(address);
if (bitmap_.count(chunk) == 0) {
bitmap_[chunk] = AllocateBitmap();
}
MarkBit mark_bit =
bitmap_[chunk]->MarkBitFromIndex(chunk->AddressToMarkbitIndex(address));
if (mark_bit.Get()) return false;
mark_bit.Set();
return true;
}
Bitmap* AllocateBitmap() {
return static_cast<Bitmap*>(calloc(1, Bitmap::kSize));
}
void FreeBitmap(Bitmap* bitmap) { free(bitmap); }
private:
std::unordered_map<MemoryChunk*, Bitmap*> bitmap_;
};
class ConcurrentMarkingVisitor : public ObjectVisitor {
public:
ConcurrentMarkingVisitor() {}
void VisitPointers(Object** start, Object** end) override {
for (Object** p = start; p < end; p++) {
if (!(*p)->IsHeapObject()) continue;
MarkObject(HeapObject::cast(*p));
}
}
void MarkObject(HeapObject* obj) {
if (markbits_.Mark(obj)) {
marking_stack_.push(obj);
}
}
void MarkTransitively() {
while (!marking_stack_.empty()) {
HeapObject* obj = marking_stack_.top();
marking_stack_.pop();
obj->Iterate(this);
}
}
private:
std::stack<HeapObject*> marking_stack_;
ConcurrentMarkingMarkbits markbits_;
};
class ConcurrentMarking::Task : public CancelableTask {
public:
Task(Heap* heap, Queue* queue, base::Semaphore* on_finish)
Task(Heap* heap, std::vector<HeapObject*>* root_set,
base::Semaphore* on_finish)
: CancelableTask(heap->isolate()),
heap_(heap),
queue_(queue),
on_finish_(on_finish) {}
on_finish_(on_finish),
root_set_(root_set) {}
virtual ~Task() {}
......@@ -27,54 +93,40 @@ class ConcurrentMarking::Task : public CancelableTask {
// v8::internal::CancelableTask overrides.
void RunInternal() override {
USE(heap_);
HeapObject* object;
while (queue_->Dequeue(&object)) {
// TODO(ulan): Implement actual marking.
for (HeapObject* obj : *root_set_) {
marking_visitor_.MarkObject(obj);
}
marking_visitor_.MarkTransitively();
on_finish_->Signal();
}
Heap* heap_;
Queue* queue_;
base::Semaphore* on_finish_;
ConcurrentMarkingVisitor marking_visitor_;
std::vector<HeapObject*>* root_set_;
DISALLOW_COPY_AND_ASSIGN(Task);
};
ConcurrentMarking::ConcurrentMarking(Heap* heap)
: heap_(heap), pending_tasks_(0), number_of_tasks_(0) {}
: heap_(heap), pending_task_(0) {}
ConcurrentMarking::~ConcurrentMarking() {}
void ConcurrentMarking::EnqueueObject(HeapObject* object) {
queue_.Enqueue(object);
void ConcurrentMarking::AddRoot(HeapObject* object) {
root_set_.push_back(object);
}
bool ConcurrentMarking::IsQueueEmpty() { return queue_.IsEmpty(); }
void ConcurrentMarking::StartMarkingTasks(int number_of_tasks) {
void ConcurrentMarking::StartMarkingTask() {
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);
}
V8::GetCurrentPlatform()->CallOnBackgroundThread(
new Task(heap_, &root_set_, &pending_task_),
v8::Platform::kShortRunningTask);
}
void ConcurrentMarking::WaitForTasksToComplete() {
void ConcurrentMarking::WaitForTaskToComplete() {
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;
pending_task_.Wait();
}
} // namespace internal
......
......@@ -5,9 +5,10 @@
#ifndef V8_HEAP_CONCURRENT_MARKING_
#define V8_HEAP_CONCURRENT_MARKING_
#include <vector>
#include "src/allocation.h"
#include "src/cancelable-task.h"
#include "src/locked-queue.h"
#include "src/utils.h"
#include "src/v8.h"
......@@ -19,27 +20,19 @@ class Isolate;
class ConcurrentMarking {
public:
static const int kMaxNumberOfTasks = 10;
explicit ConcurrentMarking(Heap* heap);
~ConcurrentMarking();
void EnqueueObject(HeapObject* object);
bool IsQueueEmpty();
void AddRoot(HeapObject* object);
void StartMarkingTasks(int number_of_tasks);
void WaitForTasksToComplete();
void StartMarkingTask();
void WaitForTaskToComplete();
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];
base::Semaphore pending_task_;
std::vector<HeapObject*> root_set_;
};
} // namespace internal
......
......@@ -43,6 +43,7 @@ class MarkBit {
CellType mask_;
friend class IncrementalMarking;
friend class ConcurrentMarkingMarkbits;
friend class Marking;
};
......
......@@ -19,13 +19,9 @@ TEST(ConcurrentMarking) {
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();
concurrent_marking->AddRoot(heap->undefined_value());
concurrent_marking->StartMarkingTask();
concurrent_marking->WaitForTaskToComplete();
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