Commit 017f48d2 authored by ulan's avatar ulan Committed by Commit bot

Reland "[heap] Uncommit marking deque in concurrent task."

This reverts commit 35e4a03f.

BUG=

Review-Url: https://codereview.chromium.org/2454723002
Cr-Commit-Position: refs/heads/master@{#40614}
parent 8cd5592f
......@@ -48,8 +48,8 @@ void CancelableTaskManager::RemoveFinishedTask(uint32_t id) {
cancelable_tasks_barrier_.NotifyOne();
}
bool CancelableTaskManager::TryAbort(uint32_t id) {
CancelableTaskManager::TryAbortResult CancelableTaskManager::TryAbort(
uint32_t id) {
base::LockGuard<base::Mutex> guard(&mutex_);
auto entry = cancelable_tasks_.find(id);
if (entry != cancelable_tasks_.end()) {
......@@ -58,10 +58,12 @@ bool CancelableTaskManager::TryAbort(uint32_t id) {
// Cannot call RemoveFinishedTask here because of recursive locking.
cancelable_tasks_.erase(entry);
cancelable_tasks_barrier_.NotifyOne();
return true;
return kTaskAborted;
} else {
return kTaskRunning;
}
}
return false;
return kTaskRemoved;
}
......
......@@ -32,14 +32,14 @@ class V8_EXPORT_PRIVATE CancelableTaskManager {
uint32_t Register(Cancelable* task);
// Try to abort running a task identified by {id}. The possible outcomes are:
// (1) The task is already finished running and thus has been removed from
// the manager.
// (1) The task is already finished running or was canceled before and
// thus has been removed from the manager.
// (2) The task is currently running and cannot be canceled anymore.
// (3) The task is not yet running (or finished) so it is canceled and
// removed.
//
// Returns {false} for (1) and (2), and {true} for (3).
bool TryAbort(uint32_t id);
enum TryAbortResult { kTaskRemoved, kTaskRunning, kTaskAborted };
TryAbortResult TryAbort(uint32_t id);
// Cancels all remaining registered tasks and waits for tasks that are
// already running. This disallows subsequent Register calls.
......
......@@ -58,6 +58,7 @@ MarkCompactCollector::MarkCompactCollector(Heap* heap)
compacting_(false),
black_allocation_(false),
have_code_to_deoptimize_(false),
marking_deque_(heap),
code_flusher_(nullptr),
sweeper_(heap) {
}
......@@ -2117,9 +2118,13 @@ void MarkingDeque::SetUp() {
}
}
void MarkingDeque::TearDown() { delete backing_store_; }
void MarkingDeque::TearDown() {
CancelOrWaitForUncommitTask();
delete backing_store_;
}
void MarkingDeque::StartUsing() {
base::LockGuard<base::Mutex> guard(&mutex_);
if (in_use_) {
// This can happen in mark-compact GC if the incremental marker already
// started using the marking deque.
......@@ -2139,11 +2144,16 @@ void MarkingDeque::StartUsing() {
}
void MarkingDeque::StopUsing() {
base::LockGuard<base::Mutex> guard(&mutex_);
DCHECK(IsEmpty());
DCHECK(!overflowed_);
top_ = bottom_ = mask_ = 0;
Uncommit();
in_use_ = false;
if (FLAG_concurrent_sweeping) {
StartUncommitTask();
} else {
Uncommit();
}
}
void MarkingDeque::Clear() {
......@@ -2153,7 +2163,7 @@ void MarkingDeque::Clear() {
}
void MarkingDeque::Uncommit() {
DCHECK(in_use_);
DCHECK(!in_use_);
bool success = backing_store_->Uncommit(backing_store_->address(),
backing_store_committed_size_);
backing_store_committed_size_ = 0;
......@@ -2175,6 +2185,28 @@ void MarkingDeque::EnsureCommitted() {
}
}
void MarkingDeque::StartUncommitTask() {
if (!uncommit_task_pending_) {
UncommitTask* task = new UncommitTask(heap_->isolate(), this);
uncommit_task_id_ = task->id();
uncommit_task_pending_ = true;
V8::GetCurrentPlatform()->CallOnBackgroundThread(
task, v8::Platform::kShortRunningTask);
}
}
void MarkingDeque::CancelOrWaitForUncommitTask() {
base::LockGuard<base::Mutex> guard(&mutex_);
if (!uncommit_task_pending_ ||
heap_->isolate()->cancelable_task_manager()->TryAbort(
uncommit_task_id_) != CancelableTaskManager::kTaskRunning) {
return;
}
while (uncommit_task_pending_) {
uncommit_task_barrier_.Wait(&mutex_);
}
}
class MarkCompactCollector::ObjectStatsVisitor
: public MarkCompactCollector::HeapObjectVisitor {
public:
......
......@@ -8,6 +8,8 @@
#include <deque>
#include "src/base/bits.h"
#include "src/base/platform/condition-variable.h"
#include "src/cancelable-task.h"
#include "src/heap/marking.h"
#include "src/heap/spaces.h"
#include "src/heap/store-buffer.h"
......@@ -52,7 +54,7 @@ class ObjectMarking : public AllStatic {
// Marking deque for tracing live objects.
class MarkingDeque {
public:
MarkingDeque()
explicit MarkingDeque(Heap* heap)
: backing_store_(nullptr),
backing_store_committed_size_(0),
array_(nullptr),
......@@ -60,11 +62,16 @@ class MarkingDeque {
bottom_(0),
mask_(0),
overflowed_(false),
in_use_(false) {}
in_use_(false),
uncommit_task_pending_(false),
uncommit_task_id_(0),
heap_(heap) {}
void SetUp();
void TearDown();
// Ensures that the marking deque is committed and will stay committed until
// StopUsing() is called.
void StartUsing();
void StopUsing();
void Clear();
......@@ -122,12 +129,45 @@ class MarkingDeque {
void set_top(int top) { top_ = top; }
private:
// This task uncommits the marking_deque backing store if
// markin_deque->in_use_ is false.
class UncommitTask : public CancelableTask {
public:
explicit UncommitTask(Isolate* isolate, MarkingDeque* marking_deque)
: CancelableTask(isolate), marking_deque_(marking_deque) {}
private:
// CancelableTask override.
void RunInternal() override {
base::LockGuard<base::Mutex> guard(&marking_deque_->mutex_);
if (!marking_deque_->in_use_) {
marking_deque_->Uncommit();
}
marking_deque_->uncommit_task_pending_ = false;
marking_deque_->uncommit_task_barrier_.NotifyOne();
}
MarkingDeque* marking_deque_;
DISALLOW_COPY_AND_ASSIGN(UncommitTask);
};
static const size_t kMaxSize = 4 * MB;
static const size_t kMinSize = 256 * KB;
// Must be called with mutex lock.
void EnsureCommitted();
// Must be called with mutex lock.
void Uncommit();
// Must be called with mutex lock.
void StartUncommitTask();
void CancelOrWaitForUncommitTask();
base::Mutex mutex_;
base::ConditionVariable uncommit_task_barrier_;
base::VirtualMemory* backing_store_;
size_t backing_store_committed_size_;
HeapObject** array_;
......@@ -138,7 +178,12 @@ class MarkingDeque {
int bottom_;
int mask_;
bool overflowed_;
// in_use_ == true after taking mutex lock implies that the marking deque is
// committed and will stay committed at least until in_use_ == false.
bool in_use_;
bool uncommit_task_pending_;
uint32_t uncommit_task_id_;
Heap* heap_;
DISALLOW_COPY_AND_ASSIGN(MarkingDeque);
};
......
......@@ -103,7 +103,8 @@ class PageParallelJob {
delete main_task;
// Wait for background tasks.
for (int i = 0; i < num_tasks_; i++) {
if (!cancelable_task_manager_->TryAbort(task_ids[i])) {
if (cancelable_task_manager_->TryAbort(task_ids[i]) !=
CancelableTaskManager::kTaskAborted) {
pending_tasks_->Wait();
}
}
......
......@@ -319,7 +319,8 @@ void WaitForCompilationTasks(Isolate* isolate, uint32_t* task_ids,
for (size_t i = 0; i < num_tasks; ++i) {
// If the task has not started yet, then we abort it. Otherwise we wait for
// it to finish.
if (!isolate->cancelable_task_manager()->TryAbort(task_ids[i])) {
if (isolate->cancelable_task_manager()->TryAbort(task_ids[i]) !=
CancelableTaskManager::kTaskAborted) {
pending_tasks->Wait();
}
}
......
......@@ -51,7 +51,7 @@ using v8::Just;
TEST(MarkingDeque) {
CcTest::InitializeVM();
MarkingDeque s;
MarkingDeque s(CcTest::i_isolate()->heap());
s.SetUp();
s.StartUsing();
Address original_address = reinterpret_cast<Address>(&s);
......
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