Commit 469c7ee9 authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

Add cancelable lambda tasks

Often, tasks just need to call a single API method. By implementing
such tasks via a lambda, we save a lot of boilerplate. Additionally,
since lambdas are defined inside other function bodies, they have
access to private methods, which sometimes allows for better
encapsulation.

This CL introduces {CancelableLambdaTask} and
{CancelableIdleLambdaTask} and uses them to replace some custom tasks.
More can be refactored later.

R=ahaas@chromium.org

Bug: v8:8238
Change-Id: I88bd2c9bd57ebc32d082528f2e4251d741a0d021
Reviewed-on: https://chromium-review.googlesource.com/c/1256773
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarHannes Payer <hpayer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56367}
parent f5d6ea17
......@@ -134,7 +134,6 @@ class V8_EXPORT_PRIVATE Cancelable {
DISALLOW_COPY_AND_ASSIGN(Cancelable);
};
// Multiple inheritance can be used because Task is a pure interface.
class V8_EXPORT_PRIVATE CancelableTask : public Cancelable,
NON_EXPORTED_BASE(public Task) {
......@@ -155,6 +154,32 @@ class V8_EXPORT_PRIVATE CancelableTask : public Cancelable,
DISALLOW_COPY_AND_ASSIGN(CancelableTask);
};
// TODO(clemensh): Use std::function and move implementation to cc file.
template <typename Func>
class CancelableLambdaTask final : public CancelableTask {
public:
CancelableLambdaTask(Isolate* isolate, Func func)
: CancelableTask(isolate), func_(std::move(func)) {}
CancelableLambdaTask(CancelableTaskManager* manager, Func func)
: CancelableTask(manager), func_(std::move(func)) {}
void RunInternal() final { func_(); }
private:
Func func_;
};
template <typename Func>
std::unique_ptr<CancelableTask> MakeCancelableLambdaTask(Isolate* isolate,
Func func) {
return std::unique_ptr<CancelableTask>(
new CancelableLambdaTask<Func>(isolate, std::move(func)));
}
template <typename Func>
std::unique_ptr<CancelableTask> MakeCancelableLambdaTask(
CancelableTaskManager* manager, Func func) {
return std::unique_ptr<CancelableTask>(
new CancelableLambdaTask<Func>(manager, std::move(func)));
}
// Multiple inheritance can be used because IdleTask is a pure interface.
class CancelableIdleTask : public Cancelable, public IdleTask {
......@@ -175,6 +200,33 @@ class CancelableIdleTask : public Cancelable, public IdleTask {
DISALLOW_COPY_AND_ASSIGN(CancelableIdleTask);
};
template <typename Func>
class CancelableIdleLambdaTask final : public CancelableIdleTask {
public:
CancelableIdleLambdaTask(Isolate* isolate, Func func)
: CancelableIdleTask(isolate), func_(std::move(func)) {}
CancelableIdleLambdaTask(CancelableTaskManager* manager, Func func)
: CancelableIdleTask(manager), func_(std::move(func)) {}
void RunInternal(double deadline_in_seconds) final {
func_(deadline_in_seconds);
}
private:
Func func_;
};
template <typename Func>
std::unique_ptr<CancelableIdleTask> MakeCancelableIdleLambdaTask(
Isolate* isolate, Func func) {
return std::unique_ptr<CancelableIdleTask>(
new CancelableIdleLambdaTask<Func>(isolate, std::move(func)));
}
template <typename Func>
std::unique_ptr<CancelableIdleTask> MakeCancelableIdleLambdaTask(
CancelableTaskManager* manager, Func func) {
return std::unique_ptr<CancelableIdleTask>(
new CancelableIdleLambdaTask<Func>(manager, std::move(func)));
}
} // namespace internal
} // namespace v8
......
......@@ -39,107 +39,8 @@ void FinalizeJobOnMainThread(Isolate* isolate, CompilerDispatcherJob* job,
// we'll get all of it so try to be a conservative.
const double kMaxIdleTimeToExpectInMs = 40;
class MemoryPressureTask : public CancelableTask {
public:
MemoryPressureTask(CancelableTaskManager* task_manager,
CompilerDispatcher* dispatcher);
~MemoryPressureTask() override;
// CancelableTask implementation.
void RunInternal() override;
private:
CompilerDispatcher* dispatcher_;
DISALLOW_COPY_AND_ASSIGN(MemoryPressureTask);
};
MemoryPressureTask::MemoryPressureTask(CancelableTaskManager* task_manager,
CompilerDispatcher* dispatcher)
: CancelableTask(task_manager), dispatcher_(dispatcher) {}
MemoryPressureTask::~MemoryPressureTask() = default;
void MemoryPressureTask::RunInternal() {
dispatcher_->AbortAll(BlockingBehavior::kDontBlock);
}
} // namespace
class CompilerDispatcher::AbortTask : public CancelableTask {
public:
AbortTask(CancelableTaskManager* task_manager,
CompilerDispatcher* dispatcher);
~AbortTask() override;
// CancelableTask implementation.
void RunInternal() override;
private:
CompilerDispatcher* dispatcher_;
DISALLOW_COPY_AND_ASSIGN(AbortTask);
};
CompilerDispatcher::AbortTask::AbortTask(CancelableTaskManager* task_manager,
CompilerDispatcher* dispatcher)
: CancelableTask(task_manager), dispatcher_(dispatcher) {}
CompilerDispatcher::AbortTask::~AbortTask() = default;
void CompilerDispatcher::AbortTask::RunInternal() {
dispatcher_->AbortInactiveJobs();
}
class CompilerDispatcher::WorkerTask : public CancelableTask {
public:
WorkerTask(CancelableTaskManager* task_manager,
CompilerDispatcher* dispatcher);
~WorkerTask() override;
// CancelableTask implementation.
void RunInternal() override;
private:
CompilerDispatcher* dispatcher_;
DISALLOW_COPY_AND_ASSIGN(WorkerTask);
};
CompilerDispatcher::WorkerTask::WorkerTask(CancelableTaskManager* task_manager,
CompilerDispatcher* dispatcher)
: CancelableTask(task_manager), dispatcher_(dispatcher) {}
CompilerDispatcher::WorkerTask::~WorkerTask() = default;
void CompilerDispatcher::WorkerTask::RunInternal() {
dispatcher_->DoBackgroundWork();
}
class CompilerDispatcher::IdleTask : public CancelableIdleTask {
public:
IdleTask(CancelableTaskManager* task_manager, CompilerDispatcher* dispatcher);
~IdleTask() override;
// CancelableIdleTask implementation.
void RunInternal(double deadline_in_seconds) override;
private:
CompilerDispatcher* dispatcher_;
DISALLOW_COPY_AND_ASSIGN(IdleTask);
};
CompilerDispatcher::IdleTask::IdleTask(CancelableTaskManager* task_manager,
CompilerDispatcher* dispatcher)
: CancelableIdleTask(task_manager), dispatcher_(dispatcher) {}
CompilerDispatcher::IdleTask::~IdleTask() = default;
void CompilerDispatcher::IdleTask::RunInternal(double deadline_in_seconds) {
dispatcher_->DoIdleWork(deadline_in_seconds);
}
CompilerDispatcher::CompilerDispatcher(Isolate* isolate, Platform* platform,
size_t max_stack_size)
: isolate_(isolate),
......@@ -398,9 +299,11 @@ void CompilerDispatcher::MemoryPressureNotification(
abort_ = true;
pending_background_jobs_.clear();
}
platform_->CallOnForegroundThread(
reinterpret_cast<v8::Isolate*>(isolate_),
new MemoryPressureTask(task_manager_.get(), this));
auto abort_task = MakeCancelableLambdaTask(task_manager_.get(), [this] {
AbortAll(BlockingBehavior::kDontBlock);
});
platform_->CallOnForegroundThread(reinterpret_cast<v8::Isolate*>(isolate_),
abort_task.release());
}
}
......@@ -422,8 +325,10 @@ void CompilerDispatcher::ScheduleIdleTaskFromAnyThread() {
if (idle_task_scheduled_ || abort_) return;
idle_task_scheduled_ = true;
}
platform_->CallIdleOnForegroundThread(
v8_isolate, new IdleTask(task_manager_.get(), this));
auto idle_task = MakeCancelableIdleLambdaTask(
task_manager_.get(),
[this](double deadline_in_seconds) { DoIdleWork(deadline_in_seconds); });
platform_->CallIdleOnForegroundThread(v8_isolate, idle_task.release());
}
void CompilerDispatcher::ScheduleIdleTaskIfNeeded() {
......@@ -433,8 +338,9 @@ void CompilerDispatcher::ScheduleIdleTaskIfNeeded() {
void CompilerDispatcher::ScheduleAbortTask() {
v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_);
platform_->CallOnForegroundThread(v8_isolate,
new AbortTask(task_manager_.get(), this));
auto abort_task = MakeCancelableLambdaTask(task_manager_.get(),
[this] { AbortInactiveJobs(); });
platform_->CallOnForegroundThread(v8_isolate, abort_task.release());
}
void CompilerDispatcher::ConsiderJobForBackgroundProcessing(
......@@ -458,8 +364,8 @@ void CompilerDispatcher::ScheduleMoreWorkerTasksIfNeeded() {
}
++num_worker_tasks_;
}
platform_->CallOnWorkerThread(
base::make_unique<WorkerTask>(task_manager_.get(), this));
platform_->CallOnWorkerThread(MakeCancelableLambdaTask(
task_manager_.get(), [this] { DoBackgroundWork(); }));
}
void CompilerDispatcher::DoBackgroundWork() {
......
......@@ -500,22 +500,6 @@ class GlobalHandles::NodeIterator {
DISALLOW_COPY_AND_ASSIGN(NodeIterator);
};
class GlobalHandles::PendingPhantomCallbacksSecondPassTask
: public v8::internal::CancelableTask {
public:
PendingPhantomCallbacksSecondPassTask(GlobalHandles* global_handles,
Isolate* isolate)
: CancelableTask(isolate), global_handles_(global_handles) {}
void RunInternal() override {
global_handles_->InvokeSecondPassPhantomCallbacksFromTask();
}
private:
GlobalHandles* global_handles_;
DISALLOW_COPY_AND_ASSIGN(PendingPhantomCallbacksSecondPassTask);
};
GlobalHandles::GlobalHandles(Isolate* isolate)
: isolate_(isolate),
number_of_global_handles_(0),
......@@ -871,9 +855,10 @@ int GlobalHandles::DispatchPendingPhantomCallbacks(
GCType::kGCTypeProcessWeakCallbacks, kNoGCCallbackFlags);
} else if (!second_pass_callbacks_task_posted_) {
second_pass_callbacks_task_posted_ = true;
auto task = new PendingPhantomCallbacksSecondPassTask(this, isolate());
auto task = MakeCancelableLambdaTask(
isolate(), [this] { InvokeSecondPassPhantomCallbacksFromTask(); });
V8::GetCurrentPlatform()->CallOnForegroundThread(
reinterpret_cast<v8::Isolate*>(isolate()), task);
reinterpret_cast<v8::Isolate*>(isolate()), task.release());
}
}
return freed_nodes;
......
......@@ -184,7 +184,6 @@ class GlobalHandles {
class NodeBlock;
class NodeIterator;
class PendingPhantomCallback;
class PendingPhantomCallbacksSecondPassTask;
explicit GlobalHandles(Isolate* isolate);
......
......@@ -42,31 +42,18 @@ void ArrayBufferCollector::PerformFreeAllocations() {
allocations_.clear();
}
class ArrayBufferCollector::FreeingTask final : public CancelableTask {
public:
explicit FreeingTask(Heap* heap)
: CancelableTask(heap->isolate()), heap_(heap) {}
~FreeingTask() override = default;
private:
void RunInternal() final {
TRACE_BACKGROUND_GC(
heap_->tracer(),
GCTracer::BackgroundScope::BACKGROUND_ARRAY_BUFFER_FREE);
heap_->array_buffer_collector()->PerformFreeAllocations();
}
Heap* heap_;
};
void ArrayBufferCollector::FreeAllocations() {
// TODO(wez): Remove backing-store from external memory accounting.
heap_->account_external_memory_concurrently_freed();
if (!heap_->IsTearingDown() && !heap_->ShouldReduceMemory() &&
FLAG_concurrent_array_buffer_freeing) {
V8::GetCurrentPlatform()->CallOnWorkerThread(
base::make_unique<FreeingTask>(heap_));
MakeCancelableLambdaTask(heap_->isolate(), [this] {
TRACE_BACKGROUND_GC(
heap_->tracer(),
GCTracer::BackgroundScope::BACKGROUND_ARRAY_BUFFER_FREE);
PerformFreeAllocations();
}));
} else {
// Fallback for when concurrency is disabled/restricted. This is e.g. the
// case when the GC should reduce memory. For such GCs the
......
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