[V8 Platform] Make CallOnWorkerThread use std::unique_ptr

This is done now while embedders have yet to adapt to the new API before
it becomes hard to migrate.

Also renamed variable/methods to use "worker threads" rather than
"background" nomenclature.

Extracted from https://chromium-review.googlesource.com/c/v8/v8/+/978443/7
while resolving the more contentious bits around using task runners.

TBR=rmcilroy@chromium.org

Bug: chromium:817421
Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng
Change-Id: Ie3ddf15a708e829c0f718d89bebf3e96d1990c16
Reviewed-on: https://chromium-review.googlesource.com/980953
Commit-Queue: Gabriel Charette <gab@chromium.org>
Reviewed-by: Gabriel Charette <gab@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52231}
This commit is contained in:
Gabriel Charette 2018-03-26 12:44:23 -04:00 committed by Commit Bot
parent 7e78e45b90
commit 1983f3055d
23 changed files with 179 additions and 168 deletions

View File

@ -2861,12 +2861,12 @@ v8_component("v8_libplatform") {
"include/libplatform/libplatform-export.h",
"include/libplatform/libplatform.h",
"include/libplatform/v8-tracing.h",
"src/libplatform/default-background-task-runner.cc",
"src/libplatform/default-background-task-runner.h",
"src/libplatform/default-foreground-task-runner.cc",
"src/libplatform/default-foreground-task-runner.h",
"src/libplatform/default-platform.cc",
"src/libplatform/default-platform.h",
"src/libplatform/default-worker-threads-task-runner.cc",
"src/libplatform/default-worker-threads-task-runner.h",
"src/libplatform/task-queue.cc",
"src/libplatform/task-queue.h",
"src/libplatform/tracing/trace-buffer.cc",

View File

@ -363,8 +363,7 @@ class Platform {
* thread the task will be run on.
*/
V8_DEPRECATE_SOON(
"ExpectedRuntime is deprecated, use CallOnWorkerThread(Task*) "
"instead.",
"ExpectedRuntime is deprecated, use CallOnWorkerThread() instead.",
virtual void CallOnBackgroundThread(Task* task,
ExpectedRuntime expected_runtime)) {
// An implementation needs to be provided here because this is called by the
@ -381,17 +380,18 @@ class Platform {
* TODO(gab): Make pure virtual when all embedders override this instead of
* CallOnBackgroundThread().
*/
virtual void CallOnWorkerThread(Task* task) {
CallOnBackgroundThread(task, kShortRunningTask);
virtual void CallOnWorkerThread(std::unique_ptr<Task> task) {
CallOnBackgroundThread(task.release(), kShortRunningTask);
}
/**
* Schedules a task that blocks the main thread to be invoked with
* high-priority on a worker thread.
*/
virtual void CallBlockingTaskOnWorkerThread(Task* task) {
// TODO(gab): Make pure-virtual when all embedders override this.
CallOnWorkerThread(task);
virtual void CallBlockingTaskOnWorkerThread(std::unique_ptr<Task> task) {
// Embedders may optionally override this to process these tasks in a high
// priority pool.
CallOnWorkerThread(std::move(task));
}
/**

View File

@ -7,6 +7,7 @@
#include "include/v8-platform.h"
#include "include/v8.h"
#include "src/base/platform/time.h"
#include "src/base/template-utils.h"
#include "src/cancelable-task.h"
#include "src/compilation-info.h"
#include "src/compiler-dispatcher/compiler-dispatcher-job.h"
@ -123,11 +124,11 @@ void CompilerDispatcher::AbortTask::RunInternal() {
dispatcher_->AbortInactiveJobs();
}
class CompilerDispatcher::BackgroundTask : public CancelableTask {
class CompilerDispatcher::WorkerTask : public CancelableTask {
public:
BackgroundTask(Isolate* isolate, CancelableTaskManager* task_manager,
CompilerDispatcher* dispatcher);
~BackgroundTask() override;
WorkerTask(Isolate* isolate, CancelableTaskManager* task_manager,
CompilerDispatcher* dispatcher);
~WorkerTask() override;
// CancelableTask implementation.
void RunInternal() override;
@ -135,17 +136,17 @@ class CompilerDispatcher::BackgroundTask : public CancelableTask {
private:
CompilerDispatcher* dispatcher_;
DISALLOW_COPY_AND_ASSIGN(BackgroundTask);
DISALLOW_COPY_AND_ASSIGN(WorkerTask);
};
CompilerDispatcher::BackgroundTask::BackgroundTask(
Isolate* isolate, CancelableTaskManager* task_manager,
CompilerDispatcher* dispatcher)
CompilerDispatcher::WorkerTask::WorkerTask(Isolate* isolate,
CancelableTaskManager* task_manager,
CompilerDispatcher* dispatcher)
: CancelableTask(task_manager), dispatcher_(dispatcher) {}
CompilerDispatcher::BackgroundTask::~BackgroundTask() {}
CompilerDispatcher::WorkerTask::~WorkerTask() {}
void CompilerDispatcher::BackgroundTask::RunInternal() {
void CompilerDispatcher::WorkerTask::RunInternal() {
dispatcher_->DoBackgroundWork();
}
@ -188,7 +189,7 @@ CompilerDispatcher::CompilerDispatcher(Isolate* isolate, Platform* platform,
memory_pressure_level_(MemoryPressureLevel::kNone),
abort_(false),
idle_task_scheduled_(false),
num_background_tasks_(0),
num_worker_tasks_(0),
main_thread_blocking_on_job_(nullptr),
block_for_testing_(false),
semaphore_for_testing_(0) {
@ -434,7 +435,7 @@ void CompilerDispatcher::AbortInactiveJobs() {
}
if (jobs_.empty()) {
base::LockGuard<base::Mutex> lock(&mutex_);
if (num_background_tasks_ == 0) abort_ = false;
if (num_worker_tasks_ == 0) abort_ = false;
}
}
@ -511,22 +512,22 @@ void CompilerDispatcher::ConsiderJobForBackgroundProcessing(
base::LockGuard<base::Mutex> lock(&mutex_);
pending_background_jobs_.insert(job);
}
ScheduleMoreBackgroundTasksIfNeeded();
ScheduleMoreWorkerTasksIfNeeded();
}
void CompilerDispatcher::ScheduleMoreBackgroundTasksIfNeeded() {
void CompilerDispatcher::ScheduleMoreWorkerTasksIfNeeded() {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.CompilerDispatcherScheduleMoreBackgroundTasksIfNeeded");
"V8.CompilerDispatcherScheduleMoreWorkerTasksIfNeeded");
{
base::LockGuard<base::Mutex> lock(&mutex_);
if (pending_background_jobs_.empty()) return;
if (platform_->NumberOfWorkerThreads() <= num_background_tasks_) {
if (platform_->NumberOfWorkerThreads() <= num_worker_tasks_) {
return;
}
++num_background_tasks_;
++num_worker_tasks_;
}
platform_->CallOnWorkerThread(
new BackgroundTask(isolate_, task_manager_.get(), this));
base::make_unique<WorkerTask>(isolate_, task_manager_.get(), this));
}
void CompilerDispatcher::DoBackgroundWork() {
@ -570,7 +571,7 @@ void CompilerDispatcher::DoBackgroundWork() {
{
base::LockGuard<base::Mutex> lock(&mutex_);
--num_background_tasks_;
--num_worker_tasks_;
if (running_background_jobs_.empty() && abort_) {
// This is the last background job that finished. The abort task
@ -718,7 +719,7 @@ CompilerDispatcher::JobMap::const_iterator CompilerDispatcher::RemoveJob(
it = jobs_.erase(it);
if (jobs_.empty()) {
base::LockGuard<base::Mutex> lock(&mutex_);
if (num_background_tasks_ == 0) abort_ = false;
if (num_worker_tasks_ == 0) abort_ = false;
}
return it;
}

View File

@ -117,16 +117,16 @@ class V8_EXPORT_PRIVATE CompilerDispatcher {
FRIEND_TEST(CompilerDispatcherTest, EnqueueAndStepParsed);
FRIEND_TEST(CompilerDispatcherTest, IdleTaskSmallIdleTime);
FRIEND_TEST(CompilerDispatcherTest, CompileOnBackgroundThread);
FRIEND_TEST(CompilerDispatcherTest, FinishNowWithBackgroundTask);
FRIEND_TEST(CompilerDispatcherTest, AsyncAbortAllPendingBackgroundTask);
FRIEND_TEST(CompilerDispatcherTest, AsyncAbortAllRunningBackgroundTask);
FRIEND_TEST(CompilerDispatcherTest, FinishNowWithWorkerTask);
FRIEND_TEST(CompilerDispatcherTest, AsyncAbortAllPendingWorkerTask);
FRIEND_TEST(CompilerDispatcherTest, AsyncAbortAllRunningWorkerTask);
FRIEND_TEST(CompilerDispatcherTest, FinishNowDuringAbortAll);
FRIEND_TEST(CompilerDispatcherTest, CompileMultipleOnBackgroundThread);
typedef std::map<JobId, std::unique_ptr<CompilerDispatcherJob>> JobMap;
typedef IdentityMap<JobId, FreeStoreAllocationPolicy> SharedToJobIdMap;
class AbortTask;
class BackgroundTask;
class WorkerTask;
class IdleTask;
void WaitForJobIfRunningOnBackground(CompilerDispatcherJob* job);
@ -135,7 +135,7 @@ class V8_EXPORT_PRIVATE CompilerDispatcher {
bool CanEnqueue(Handle<SharedFunctionInfo> function);
JobMap::const_iterator GetJobFor(Handle<SharedFunctionInfo> shared) const;
void ConsiderJobForBackgroundProcessing(CompilerDispatcherJob* job);
void ScheduleMoreBackgroundTasksIfNeeded();
void ScheduleMoreWorkerTasksIfNeeded();
void ScheduleIdleTaskFromAnyThread();
void ScheduleIdleTaskIfNeeded();
void ScheduleAbortTask();
@ -183,8 +183,8 @@ class V8_EXPORT_PRIVATE CompilerDispatcher {
bool idle_task_scheduled_;
// Number of scheduled or running BackgroundTask objects.
int num_background_tasks_;
// Number of scheduled or running WorkerTask objects.
int num_worker_tasks_;
// The set of CompilerDispatcherJobs that can be advanced on any thread.
std::unordered_set<CompilerDispatcherJob*> pending_background_jobs_;

View File

@ -5,6 +5,7 @@
#include "src/compiler-dispatcher/optimizing-compile-dispatcher.h"
#include "src/base/atomicops.h"
#include "src/base/template-utils.h"
#include "src/cancelable-task.h"
#include "src/compilation-info.h"
#include "src/compiler.h"
@ -225,14 +226,14 @@ void OptimizingCompileDispatcher::QueueForOptimization(CompilationJob* job) {
blocked_jobs_++;
} else {
V8::GetCurrentPlatform()->CallOnWorkerThread(
new CompileTask(isolate_, this));
base::make_unique<CompileTask>(isolate_, this));
}
}
void OptimizingCompileDispatcher::Unblock() {
while (blocked_jobs_ > 0) {
V8::GetCurrentPlatform()->CallOnWorkerThread(
new CompileTask(isolate_, this));
base::make_unique<CompileTask>(isolate_, this));
blocked_jobs_--;
}
}

View File

@ -191,11 +191,10 @@ class PredictablePlatform : public Platform {
return platform_->GetForegroundTaskRunner(isolate);
}
void CallOnWorkerThread(Task* task) override {
void CallOnWorkerThread(std::unique_ptr<Task> task) override {
// It's not defined when background tasks are being executed, so we can just
// execute them right away.
task->Run();
delete task;
}
void CallOnForegroundThread(v8::Isolate* isolate, Task* task) override {

View File

@ -4,6 +4,7 @@
#include "src/heap/array-buffer-collector.h"
#include "src/base/template-utils.h"
#include "src/heap/array-buffer-tracker.h"
#include "src/heap/heap-inl.h"
@ -48,8 +49,8 @@ class ArrayBufferCollector::FreeingTask final : public CancelableTask {
void ArrayBufferCollector::FreeAllocationsOnBackgroundThread() {
heap_->account_external_memory_concurrently_freed();
if (!heap_->IsTearingDown() && FLAG_concurrent_array_buffer_freeing) {
FreeingTask* task = new FreeingTask(heap_);
V8::GetCurrentPlatform()->CallOnWorkerThread(task);
V8::GetCurrentPlatform()->CallOnWorkerThread(
base::make_unique<FreeingTask>(heap_));
} else {
// Fallback for when concurrency is disabled/restricted.
FreeAllocations();

View File

@ -8,6 +8,7 @@
#include <unordered_map>
#include "include/v8config.h"
#include "src/base/template-utils.h"
#include "src/heap/gc-tracer.h"
#include "src/heap/heap-inl.h"
#include "src/heap/heap.h"
@ -612,9 +613,10 @@ void ConcurrentMarking::ScheduleTasks() {
task_state_[i].preemption_request.SetValue(false);
is_pending_[i] = true;
++pending_task_count_;
Task* task = new Task(heap_->isolate(), this, &task_state_[i], i);
auto task =
base::make_unique<Task>(heap_->isolate(), this, &task_state_[i], i);
cancelable_id_[i] = task->id();
V8::GetCurrentPlatform()->CallOnWorkerThread(task);
V8::GetCurrentPlatform()->CallOnWorkerThread(std::move(task));
}
}
DCHECK_EQ(task_count_, pending_task_count_);

View File

@ -90,10 +90,11 @@ void ItemParallelJob::Run(std::shared_ptr<Counters> async_counters) {
: 0;
CancelableTaskManager::Id* task_ids =
new CancelableTaskManager::Id[num_tasks];
Task* main_task = nullptr;
std::unique_ptr<Task> main_task;
for (size_t i = 0, start_index = 0; i < num_tasks;
i++, start_index += items_per_task + (i < items_remainder ? 1 : 0)) {
Task* task = tasks_[i];
auto task = std::move(tasks_[i]);
DCHECK(task);
// By definition there are less |items_remainder| to distribute then
// there are tasks processing items so this cannot overflow while we are
@ -105,15 +106,15 @@ void ItemParallelJob::Run(std::shared_ptr<Counters> async_counters) {
: base::Optional<AsyncTimedHistogram>());
task_ids[i] = task->id();
if (i > 0) {
V8::GetCurrentPlatform()->CallBlockingTaskOnWorkerThread(task);
V8::GetCurrentPlatform()->CallBlockingTaskOnWorkerThread(std::move(task));
} else {
main_task = task;
main_task = std::move(task);
}
}
// Contribute on main thread.
DCHECK(main_task);
main_task->Run();
delete main_task;
// Wait for background tasks.
for (size_t i = 0; i < num_tasks; i++) {

View File

@ -126,7 +126,7 @@ class V8_EXPORT_PRIVATE ItemParallelJob {
~ItemParallelJob();
// Adds a task to the job. Transfers ownership to the job.
void AddTask(Task* task) { tasks_.push_back(task); }
void AddTask(Task* task) { tasks_.push_back(std::unique_ptr<Task>(task)); }
// Adds an item to the job. Transfers ownership to the job.
void AddItem(Item* item) { items_.push_back(item); }
@ -140,7 +140,7 @@ class V8_EXPORT_PRIVATE ItemParallelJob {
private:
std::vector<Item*> items_;
std::vector<Task*> tasks_;
std::vector<std::unique_ptr<Task>> tasks_;
CancelableTaskManager* cancelable_task_manager_;
base::Semaphore* pending_tasks_;
DISALLOW_COPY_AND_ASSIGN(ItemParallelJob);

View File

@ -9,6 +9,7 @@
#include "src/base/bits.h"
#include "src/base/macros.h"
#include "src/base/platform/semaphore.h"
#include "src/base/template-utils.h"
#include "src/counters.h"
#include "src/heap/array-buffer-tracker.h"
#include "src/heap/concurrent-marking.h"
@ -349,7 +350,7 @@ void MemoryAllocator::Unmapper::FreeQueuedChunks() {
}
return;
}
UnmapFreeMemoryTask* task = new UnmapFreeMemoryTask(heap_->isolate(), this);
auto task = base::make_unique<UnmapFreeMemoryTask>(heap_->isolate(), this);
if (FLAG_trace_unmapper) {
PrintIsolate(heap_->isolate(),
"Unmapper::FreeQueuedChunks: new task id=%" PRIu64 "\n",
@ -360,7 +361,7 @@ void MemoryAllocator::Unmapper::FreeQueuedChunks() {
DCHECK_GE(active_unmapping_tasks_.Value(), 0);
active_unmapping_tasks_.Increment(1);
task_ids_[pending_unmapping_tasks_++] = task->id();
V8::GetCurrentPlatform()->CallOnWorkerThread(task);
V8::GetCurrentPlatform()->CallOnWorkerThread(std::move(task));
} else {
PerformFreeMemoryOnQueuedChunks<FreeMode::kUncommitPooled>();
}

View File

@ -7,6 +7,7 @@
#include <algorithm>
#include "src/base/macros.h"
#include "src/base/template-utils.h"
#include "src/counters.h"
#include "src/heap/incremental-marking.h"
#include "src/isolate.h"
@ -94,8 +95,8 @@ void StoreBuffer::FlipStoreBuffers() {
if (!task_running_ && FLAG_concurrent_store_buffer) {
task_running_ = true;
Task* task = new Task(heap_->isolate(), this);
V8::GetCurrentPlatform()->CallOnWorkerThread(task);
V8::GetCurrentPlatform()->CallOnWorkerThread(
base::make_unique<Task>(heap_->isolate(), this));
}
}

View File

@ -4,6 +4,7 @@
#include "src/heap/sweeper.h"
#include "src/base/template-utils.h"
#include "src/heap/array-buffer-tracker-inl.h"
#include "src/heap/gc-tracer.h"
#include "src/heap/mark-compact-inl.h"
@ -154,12 +155,12 @@ void Sweeper::StartSweeperTasks() {
ForAllSweepingSpaces([this](AllocationSpace space) {
DCHECK(IsValidSweepingSpace(space));
num_sweeping_tasks_.Increment(1);
SweeperTask* task = new SweeperTask(heap_->isolate(), this,
&pending_sweeper_tasks_semaphore_,
&num_sweeping_tasks_, space);
auto task = base::make_unique<SweeperTask>(
heap_->isolate(), this, &pending_sweeper_tasks_semaphore_,
&num_sweeping_tasks_, space);
DCHECK_LT(num_tasks_, kMaxSweeperTasks);
task_ids_[num_tasks_++] = task->id();
V8::GetCurrentPlatform()->CallOnWorkerThread(task);
V8::GetCurrentPlatform()->CallOnWorkerThread(std::move(task));
});
ScheduleIncrementalSweepingTask();
}
@ -551,11 +552,11 @@ void Sweeper::StartIterabilityTasks() {
DCHECK(!iterability_task_started_);
if (FLAG_concurrent_sweeping && !iterability_list_.empty()) {
IterabilityTask* task = new IterabilityTask(heap_->isolate(), this,
&iterability_task_semaphore_);
auto task = base::make_unique<IterabilityTask>(
heap_->isolate(), this, &iterability_task_semaphore_);
iterability_task_id_ = task->id();
iterability_task_started_ = true;
V8::GetCurrentPlatform()->CallOnWorkerThread(task);
V8::GetCurrentPlatform()->CallOnWorkerThread(std::move(task));
}
}

View File

@ -14,8 +14,8 @@
#include "src/base/platform/platform.h"
#include "src/base/platform/time.h"
#include "src/base/sys-info.h"
#include "src/libplatform/default-background-task-runner.h"
#include "src/libplatform/default-foreground-task-runner.h"
#include "src/libplatform/default-worker-threads-task-runner.h"
namespace v8 {
namespace platform {
@ -96,7 +96,7 @@ DefaultPlatform::DefaultPlatform(
DefaultPlatform::~DefaultPlatform() {
base::LockGuard<base::Mutex> guard(&lock_);
if (background_task_runner_) background_task_runner_->Terminate();
if (worker_threads_task_runner_) worker_threads_task_runner_->Terminate();
for (auto it : foreground_task_runner_map_) {
it.second->Terminate();
}
@ -114,9 +114,9 @@ void DefaultPlatform::SetThreadPoolSize(int thread_pool_size) {
void DefaultPlatform::EnsureBackgroundTaskRunnerInitialized() {
base::LockGuard<base::Mutex> guard(&lock_);
if (!background_task_runner_) {
background_task_runner_ =
std::make_shared<DefaultBackgroundTaskRunner>(thread_pool_size_);
if (!worker_threads_task_runner_) {
worker_threads_task_runner_ =
std::make_shared<DefaultWorkerThreadsTaskRunner>(thread_pool_size_);
}
}
@ -196,11 +196,11 @@ std::shared_ptr<TaskRunner> DefaultPlatform::GetForegroundTaskRunner(
std::shared_ptr<TaskRunner> DefaultPlatform::GetWorkerThreadsTaskRunner(
v8::Isolate*) {
EnsureBackgroundTaskRunnerInitialized();
return background_task_runner_;
return worker_threads_task_runner_;
}
void DefaultPlatform::CallOnWorkerThread(Task* task) {
GetWorkerThreadsTaskRunner(nullptr)->PostTask(std::unique_ptr<Task>(task));
void DefaultPlatform::CallOnWorkerThread(std::unique_ptr<Task> task) {
GetWorkerThreadsTaskRunner(nullptr)->PostTask(std::move(task));
}
void DefaultPlatform::CallOnForegroundThread(v8::Isolate* isolate, Task* task) {

View File

@ -26,7 +26,7 @@ namespace platform {
class Thread;
class WorkerThread;
class DefaultForegroundTaskRunner;
class DefaultBackgroundTaskRunner;
class DefaultWorkerThreadsTaskRunner;
class DefaultPageAllocator;
class V8_PLATFORM_EXPORT DefaultPlatform : public NON_EXPORTED_BASE(Platform) {
@ -60,7 +60,7 @@ class V8_PLATFORM_EXPORT DefaultPlatform : public NON_EXPORTED_BASE(Platform) {
v8::Isolate* isolate) override;
std::shared_ptr<TaskRunner> GetWorkerThreadsTaskRunner(
v8::Isolate* isolate) override;
void CallOnWorkerThread(Task* task) override;
void CallOnWorkerThread(std::unique_ptr<Task> task) override;
void CallOnForegroundThread(v8::Isolate* isolate, Task* task) override;
void CallDelayedOnForegroundThread(Isolate* isolate, Task* task,
double delay_in_seconds) override;
@ -78,7 +78,7 @@ class V8_PLATFORM_EXPORT DefaultPlatform : public NON_EXPORTED_BASE(Platform) {
base::Mutex lock_;
int thread_pool_size_;
IdleTaskSupport idle_task_support_;
std::shared_ptr<DefaultBackgroundTaskRunner> background_task_runner_;
std::shared_ptr<DefaultWorkerThreadsTaskRunner> worker_threads_task_runner_;
std::map<v8::Isolate*, std::shared_ptr<DefaultForegroundTaskRunner>>
foreground_task_runner_map_;

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/libplatform/default-background-task-runner.h"
#include "src/libplatform/default-worker-threads-task-runner.h"
#include "src/base/platform/mutex.h"
#include "src/libplatform/worker-thread.h"
@ -10,19 +10,19 @@
namespace v8 {
namespace platform {
DefaultBackgroundTaskRunner::DefaultBackgroundTaskRunner(
DefaultWorkerThreadsTaskRunner::DefaultWorkerThreadsTaskRunner(
uint32_t thread_pool_size) {
for (uint32_t i = 0; i < thread_pool_size; ++i) {
thread_pool_.push_back(base::make_unique<WorkerThread>(&queue_));
}
}
DefaultBackgroundTaskRunner::~DefaultBackgroundTaskRunner() {
DefaultWorkerThreadsTaskRunner::~DefaultWorkerThreadsTaskRunner() {
// This destructor is needed because we have unique_ptr to the WorkerThreads,
// und the {WorkerThread} class is forward declared in the header file.
}
void DefaultBackgroundTaskRunner::Terminate() {
void DefaultWorkerThreadsTaskRunner::Terminate() {
base::LockGuard<base::Mutex> guard(&lock_);
terminated_ = true;
queue_.Terminate();
@ -30,28 +30,29 @@ void DefaultBackgroundTaskRunner::Terminate() {
thread_pool_.clear();
}
void DefaultBackgroundTaskRunner::PostTask(std::unique_ptr<Task> task) {
void DefaultWorkerThreadsTaskRunner::PostTask(std::unique_ptr<Task> task) {
base::LockGuard<base::Mutex> guard(&lock_);
if (terminated_) return;
queue_.Append(std::move(task));
}
void DefaultBackgroundTaskRunner::PostDelayedTask(std::unique_ptr<Task> task,
double delay_in_seconds) {
void DefaultWorkerThreadsTaskRunner::PostDelayedTask(std::unique_ptr<Task> task,
double delay_in_seconds) {
base::LockGuard<base::Mutex> guard(&lock_);
if (terminated_) return;
// There is no use case for this function on a background thread at the
// There is no use case for this function on a worker thread at the
// moment, but it is still part of the interface.
UNIMPLEMENTED();
}
void DefaultBackgroundTaskRunner::PostIdleTask(std::unique_ptr<IdleTask> task) {
// There are no idle background tasks.
void DefaultWorkerThreadsTaskRunner::PostIdleTask(
std::unique_ptr<IdleTask> task) {
// There are no idle worker tasks.
UNREACHABLE();
}
bool DefaultBackgroundTaskRunner::IdleTasksEnabled() {
// There are no idle background tasks.
bool DefaultWorkerThreadsTaskRunner::IdleTasksEnabled() {
// There are no idle worker tasks.
return false;
}

View File

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_LIBPLATFORM_DEFAULT_BACKGROUND_TASK_RUNNER_H_
#define V8_LIBPLATFORM_DEFAULT_BACKGROUND_TASK_RUNNER_H_
#ifndef V8_LIBPLATFORM_DEFAULT_WORKER_THREADS_TASK_RUNNER_H_
#define V8_LIBPLATFORM_DEFAULT_WORKER_THREADS_TASK_RUNNER_H_
#include "include/v8-platform.h"
#include "src/libplatform/task-queue.h"
@ -14,12 +14,12 @@ namespace platform {
class Thread;
class WorkerThread;
class V8_PLATFORM_EXPORT DefaultBackgroundTaskRunner
class V8_PLATFORM_EXPORT DefaultWorkerThreadsTaskRunner
: public NON_EXPORTED_BASE(TaskRunner) {
public:
DefaultBackgroundTaskRunner(uint32_t thread_pool_size);
DefaultWorkerThreadsTaskRunner(uint32_t thread_pool_size);
~DefaultBackgroundTaskRunner();
~DefaultWorkerThreadsTaskRunner();
void Terminate();
@ -42,4 +42,4 @@ class V8_PLATFORM_EXPORT DefaultBackgroundTaskRunner
} // namespace platform
} // namespace v8
#endif // V8_LIBPLATFORM_DEFAULT_BACKGROUND_TASK_RUNNER_H_
#endif // V8_LIBPLATFORM_DEFAULT_WORKER_THREADS_TASK_RUNNER_H_

View File

@ -690,8 +690,8 @@ class TestPlatform : public v8::Platform {
return old_platform_->GetWorkerThreadsTaskRunner(isolate);
}
void CallOnWorkerThread(v8::Task* task) override {
old_platform_->CallOnWorkerThread(task);
void CallOnWorkerThread(std::unique_ptr<v8::Task> task) override {
old_platform_->CallOnWorkerThread(std::move(task));
}
void CallOnForegroundThread(v8::Isolate* isolate, v8::Task* task) override {

View File

@ -40,8 +40,8 @@ class MockPlatform : public TestPlatform {
virtual ~MockPlatform() {
delete task_;
i::V8::SetPlatformForTesting(old_platform_);
for (Task* task : worker_tasks_) {
old_platform_->CallOnWorkerThread(task);
for (auto& task : worker_tasks_) {
old_platform_->CallOnWorkerThread(std::move(task));
}
worker_tasks_.clear();
}
@ -50,8 +50,8 @@ class MockPlatform : public TestPlatform {
task_ = task;
}
void CallOnWorkerThread(Task* task) override {
worker_tasks_.push_back(task);
void CallOnWorkerThread(std::unique_ptr<Task> task) override {
worker_tasks_.push_back(std::move(task));
}
bool IdleTasksEnabled(v8::Isolate* isolate) override { return false; }
@ -67,7 +67,7 @@ class MockPlatform : public TestPlatform {
private:
Task* task_;
std::vector<Task*> worker_tasks_;
std::vector<std::unique_ptr<Task>> worker_tasks_;
v8::Platform* old_platform_;
};

View File

@ -44,8 +44,8 @@ class MockPlatform final : public TestPlatform {
task_runner_->PostTask(std::unique_ptr<Task>(task));
}
void CallOnWorkerThread(v8::Task* task) override {
task_runner_->PostTask(std::unique_ptr<Task>(task));
void CallOnWorkerThread(std::unique_ptr<v8::Task> task) override {
task_runner_->PostTask(std::move(task));
}
bool IdleTasksEnabled(v8::Isolate* isolate) override { return false; }

View File

@ -9,6 +9,7 @@
#include "include/v8.h"
#include "src/base/macros.h"
#include "src/base/platform/semaphore.h"
#include "src/base/template-utils.h"
#include "src/execution.h"
#include "src/isolate.h"
#include "src/v8.h"
@ -61,7 +62,7 @@ TEST_F(IsolateTest, MemoryPressureNotificationBackground) {
base::Semaphore semaphore(0);
internal::V8::GetCurrentPlatform()->CallOnWorkerThread(
new MemoryPressureTask(isolate(), &semaphore));
base::make_unique<MemoryPressureTask>(isolate(), &semaphore));
semaphore.Wait();

View File

@ -10,6 +10,7 @@
#include "src/api.h"
#include "src/ast/ast-value-factory.h"
#include "src/base/platform/semaphore.h"
#include "src/base/template-utils.h"
#include "src/compiler-dispatcher/compiler-dispatcher-job.h"
#include "src/compiler-dispatcher/compiler-dispatcher-tracer.h"
#include "src/compiler-dispatcher/unoptimized-compile-job.h"
@ -93,7 +94,7 @@ class MockPlatform : public v8::Platform {
~MockPlatform() override {
base::LockGuard<base::Mutex> lock(&mutex_);
EXPECT_TRUE(foreground_tasks_.empty());
EXPECT_TRUE(background_tasks_.empty());
EXPECT_TRUE(worker_tasks_.empty());
EXPECT_TRUE(idle_task_ == nullptr);
}
@ -111,14 +112,14 @@ class MockPlatform : public v8::Platform {
return std::make_shared<MockTaskRunner>(this, is_foreground_task_runner);
}
void CallOnWorkerThread(Task* task) override {
void CallOnWorkerThread(std::unique_ptr<Task> task) override {
base::LockGuard<base::Mutex> lock(&mutex_);
background_tasks_.push_back(task);
worker_tasks_.push_back(std::move(task));
}
void CallOnForegroundThread(v8::Isolate* isolate, Task* task) override {
base::LockGuard<base::Mutex> lock(&mutex_);
foreground_tasks_.push_back(task);
foreground_tasks_.push_back(std::unique_ptr<Task>(task));
}
void CallDelayedOnForegroundThread(v8::Isolate* isolate, Task* task,
@ -166,9 +167,9 @@ class MockPlatform : public v8::Platform {
return idle_task_;
}
bool BackgroundTasksPending() {
bool WorkerTasksPending() {
base::LockGuard<base::Mutex> lock(&mutex_);
return !background_tasks_.empty();
return !worker_tasks_.empty();
}
bool ForegroundTasksPending() {
@ -176,57 +177,54 @@ class MockPlatform : public v8::Platform {
return !foreground_tasks_.empty();
}
void RunBackgroundTasksAndBlock(Platform* platform) {
std::vector<Task*> tasks;
void RunWorkerTasksAndBlock(Platform* platform) {
std::vector<std::unique_ptr<Task>> tasks;
{
base::LockGuard<base::Mutex> lock(&mutex_);
tasks.swap(background_tasks_);
tasks.swap(worker_tasks_);
}
platform->CallOnWorkerThread(new TaskWrapper(this, tasks, true));
platform->CallOnWorkerThread(
base::make_unique<TaskWrapper>(this, std::move(tasks), true));
sem_.Wait();
}
void RunBackgroundTasks(Platform* platform) {
std::vector<Task*> tasks;
void RunWorkerTasks(Platform* platform) {
std::vector<std::unique_ptr<Task>> tasks;
{
base::LockGuard<base::Mutex> lock(&mutex_);
tasks.swap(background_tasks_);
tasks.swap(worker_tasks_);
}
platform->CallOnWorkerThread(new TaskWrapper(this, tasks, false));
platform->CallOnWorkerThread(
base::make_unique<TaskWrapper>(this, std::move(tasks), false));
}
void RunForegroundTasks() {
std::vector<Task*> tasks;
std::vector<std::unique_ptr<Task>> tasks;
{
base::LockGuard<base::Mutex> lock(&mutex_);
tasks.swap(foreground_tasks_);
}
for (auto& task : tasks) {
task->Run();
delete task;
// Reset |task| before running the next one.
task.reset();
}
}
void ClearBackgroundTasks() {
std::vector<Task*> tasks;
void ClearWorkerTasks() {
std::vector<std::unique_ptr<Task>> tasks;
{
base::LockGuard<base::Mutex> lock(&mutex_);
tasks.swap(background_tasks_);
}
for (auto& task : tasks) {
delete task;
tasks.swap(worker_tasks_);
}
}
void ClearForegroundTasks() {
std::vector<Task*> tasks;
std::vector<std::unique_ptr<Task>> tasks;
{
base::LockGuard<base::Mutex> lock(&mutex_);
tasks.swap(foreground_tasks_);
}
for (auto& task : tasks) {
delete task;
}
}
void ClearIdleTask() {
@ -239,22 +237,23 @@ class MockPlatform : public v8::Platform {
private:
class TaskWrapper : public Task {
public:
TaskWrapper(MockPlatform* platform, const std::vector<Task*>& tasks,
bool signal)
: platform_(platform), tasks_(tasks), signal_(signal) {}
TaskWrapper(MockPlatform* platform,
std::vector<std::unique_ptr<Task>> tasks, bool signal)
: platform_(platform), tasks_(std::move(tasks)), signal_(signal) {}
~TaskWrapper() = default;
void Run() override {
for (auto& task : tasks_) {
task->Run();
delete task;
// Reset |task| before running the next one.
task.reset();
}
if (signal_) platform_->sem_.Signal();
}
private:
MockPlatform* platform_;
std::vector<Task*> tasks_;
std::vector<std::unique_ptr<Task>> tasks_;
bool signal_;
DISALLOW_COPY_AND_ASSIGN(TaskWrapper);
@ -269,9 +268,9 @@ class MockPlatform : public v8::Platform {
void PostTask(std::unique_ptr<v8::Task> task) override {
base::LockGuard<base::Mutex> lock(&platform_->mutex_);
if (is_foreground_task_runner_) {
platform_->foreground_tasks_.push_back(task.release());
platform_->foreground_tasks_.push_back(std::move(task));
} else {
platform_->background_tasks_.push_back(task.release());
platform_->worker_tasks_.push_back(std::move(task));
}
}
@ -304,8 +303,8 @@ class MockPlatform : public v8::Platform {
base::Mutex mutex_;
IdleTask* idle_task_;
std::vector<Task*> background_tasks_;
std::vector<Task*> foreground_tasks_;
std::vector<std::unique_ptr<Task>> worker_tasks_;
std::vector<std::unique_ptr<Task>> foreground_tasks_;
base::Semaphore sem_;
@ -383,7 +382,7 @@ TEST_F(CompilerDispatcherTest, FinishAllNow) {
ASSERT_TRUE(shared[i]->is_compiled());
}
platform.ClearIdleTask();
platform.ClearBackgroundTasks();
platform.ClearWorkerTasks();
}
TEST_F(CompilerDispatcherTest, IdleTask) {
@ -497,12 +496,12 @@ TEST_F(CompilerDispatcherTest, CompileOnBackgroundThread) {
ASSERT_TRUE(dispatcher.IsEnqueued(shared));
ASSERT_FALSE(shared->is_compiled());
ASSERT_FALSE(platform.IdleTaskPending());
ASSERT_TRUE(platform.BackgroundTasksPending());
ASSERT_TRUE(platform.WorkerTasksPending());
platform.RunBackgroundTasksAndBlock(V8::GetCurrentPlatform());
platform.RunWorkerTasksAndBlock(V8::GetCurrentPlatform());
ASSERT_TRUE(platform.IdleTaskPending());
ASSERT_FALSE(platform.BackgroundTasksPending());
ASSERT_FALSE(platform.WorkerTasksPending());
ASSERT_EQ(UnoptimizedCompileJob::Status::kCompiled,
dispatcher.jobs_.begin()->second->status());
@ -514,7 +513,7 @@ TEST_F(CompilerDispatcherTest, CompileOnBackgroundThread) {
ASSERT_FALSE(platform.IdleTaskPending());
}
TEST_F(CompilerDispatcherTest, FinishNowWithBackgroundTask) {
TEST_F(CompilerDispatcherTest, FinishNowWithWorkerTask) {
MockPlatform platform;
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
@ -540,17 +539,17 @@ TEST_F(CompilerDispatcherTest, FinishNowWithBackgroundTask) {
ASSERT_TRUE(dispatcher.IsEnqueued(shared));
ASSERT_FALSE(shared->is_compiled());
ASSERT_FALSE(platform.IdleTaskPending());
ASSERT_TRUE(platform.BackgroundTasksPending());
ASSERT_TRUE(platform.WorkerTasksPending());
// This does not block, but races with the FinishNow() call below.
platform.RunBackgroundTasks(V8::GetCurrentPlatform());
platform.RunWorkerTasks(V8::GetCurrentPlatform());
ASSERT_TRUE(dispatcher.FinishNow(shared));
// Finishing removes the SFI from the queue.
ASSERT_FALSE(dispatcher.IsEnqueued(shared));
ASSERT_TRUE(shared->is_compiled());
if (platform.IdleTaskPending()) platform.ClearIdleTask();
ASSERT_FALSE(platform.BackgroundTasksPending());
ASSERT_FALSE(platform.WorkerTasksPending());
}
TEST_F(CompilerDispatcherTest, IdleTaskMultipleJobs) {
@ -608,7 +607,7 @@ TEST_F(CompilerDispatcherTest, FinishNowException) {
platform.ClearIdleTask();
}
TEST_F(CompilerDispatcherTest, AsyncAbortAllPendingBackgroundTask) {
TEST_F(CompilerDispatcherTest, AsyncAbortAllPendingWorkerTask) {
MockPlatform platform;
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
@ -634,7 +633,7 @@ TEST_F(CompilerDispatcherTest, AsyncAbortAllPendingBackgroundTask) {
ASSERT_TRUE(dispatcher.IsEnqueued(shared));
ASSERT_FALSE(shared->is_compiled());
ASSERT_FALSE(platform.IdleTaskPending());
ASSERT_TRUE(platform.BackgroundTasksPending());
ASSERT_TRUE(platform.WorkerTasksPending());
// The background task hasn't yet started, so we can just cancel it.
dispatcher.AbortAll(BlockingBehavior::kDontBlock);
@ -643,14 +642,14 @@ TEST_F(CompilerDispatcherTest, AsyncAbortAllPendingBackgroundTask) {
ASSERT_FALSE(dispatcher.IsEnqueued(shared));
ASSERT_FALSE(shared->is_compiled());
platform.RunBackgroundTasksAndBlock(V8::GetCurrentPlatform());
platform.RunWorkerTasksAndBlock(V8::GetCurrentPlatform());
if (platform.IdleTaskPending()) platform.ClearIdleTask();
ASSERT_FALSE(platform.BackgroundTasksPending());
ASSERT_FALSE(platform.WorkerTasksPending());
ASSERT_FALSE(platform.ForegroundTasksPending());
}
TEST_F(CompilerDispatcherTest, AsyncAbortAllRunningBackgroundTask) {
TEST_F(CompilerDispatcherTest, AsyncAbortAllRunningWorkerTask) {
MockPlatform platform;
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
@ -680,11 +679,11 @@ TEST_F(CompilerDispatcherTest, AsyncAbortAllRunningBackgroundTask) {
ASSERT_TRUE(dispatcher.IsEnqueued(shared1));
ASSERT_FALSE(shared1->is_compiled());
ASSERT_FALSE(platform.IdleTaskPending());
ASSERT_TRUE(platform.BackgroundTasksPending());
ASSERT_TRUE(platform.WorkerTasksPending());
// Kick off background tasks and freeze them.
dispatcher.block_for_testing_.SetValue(true);
platform.RunBackgroundTasks(V8::GetCurrentPlatform());
platform.RunWorkerTasks(V8::GetCurrentPlatform());
// Busy loop until the background task started running.
while (dispatcher.block_for_testing_.Value()) {
@ -719,13 +718,13 @@ TEST_F(CompilerDispatcherTest, AsyncAbortAllRunningBackgroundTask) {
ASSERT_TRUE(platform.IdleTaskPending());
platform.RunIdleTask(5.0, 1.0);
ASSERT_FALSE(platform.BackgroundTasksPending());
ASSERT_FALSE(platform.WorkerTasksPending());
ASSERT_FALSE(platform.ForegroundTasksPending());
// Now it's possible to enqueue new functions again.
ASSERT_TRUE(dispatcher.Enqueue(shared2));
ASSERT_TRUE(platform.IdleTaskPending());
ASSERT_FALSE(platform.BackgroundTasksPending());
ASSERT_FALSE(platform.WorkerTasksPending());
ASSERT_FALSE(platform.ForegroundTasksPending());
platform.ClearIdleTask();
}
@ -756,11 +755,11 @@ TEST_F(CompilerDispatcherTest, FinishNowDuringAbortAll) {
ASSERT_TRUE(dispatcher.IsEnqueued(shared));
ASSERT_FALSE(shared->is_compiled());
ASSERT_FALSE(platform.IdleTaskPending());
ASSERT_TRUE(platform.BackgroundTasksPending());
ASSERT_TRUE(platform.WorkerTasksPending());
// Kick off background tasks and freeze them.
dispatcher.block_for_testing_.SetValue(true);
platform.RunBackgroundTasks(V8::GetCurrentPlatform());
platform.RunWorkerTasks(V8::GetCurrentPlatform());
// Busy loop until the background task started running.
while (dispatcher.block_for_testing_.Value()) {
@ -789,14 +788,14 @@ TEST_F(CompilerDispatcherTest, FinishNowDuringAbortAll) {
// Busy wait for the background task to finish.
for (;;) {
base::LockGuard<base::Mutex> lock(&dispatcher.mutex_);
if (dispatcher.num_background_tasks_ == 0) {
if (dispatcher.num_worker_tasks_ == 0) {
break;
}
}
ASSERT_TRUE(platform.ForegroundTasksPending());
ASSERT_TRUE(platform.IdleTaskPending());
ASSERT_FALSE(platform.BackgroundTasksPending());
ASSERT_FALSE(platform.WorkerTasksPending());
platform.RunForegroundTasks();
{
@ -866,7 +865,8 @@ TEST_F(CompilerDispatcherTest, MemoryPressureFromBackground) {
ASSERT_TRUE(dispatcher.Enqueue(shared));
base::Semaphore sem(0);
V8::GetCurrentPlatform()->CallOnWorkerThread(
new PressureNotificationTask(i_isolate(), &dispatcher, &sem));
base::make_unique<PressureNotificationTask>(i_isolate(), &dispatcher,
&sem));
sem.Wait();
@ -901,7 +901,7 @@ TEST_F(CompilerDispatcherTest, EnqueueJob) {
ASSERT_TRUE(platform.IdleTaskPending());
platform.ClearIdleTask();
ASSERT_FALSE(platform.BackgroundTasksPending());
ASSERT_FALSE(platform.WorkerTasksPending());
}
TEST_F(CompilerDispatcherTest, EnqueueAndStep) {
@ -921,8 +921,8 @@ TEST_F(CompilerDispatcherTest, EnqueueAndStep) {
ASSERT_TRUE(platform.IdleTaskPending());
platform.ClearIdleTask();
ASSERT_TRUE(platform.BackgroundTasksPending());
platform.ClearBackgroundTasks();
ASSERT_TRUE(platform.WorkerTasksPending());
platform.ClearWorkerTasks();
}
TEST_F(CompilerDispatcherTest, CompileLazyFinishesDispatcherJob) {
@ -991,9 +991,9 @@ TEST_F(CompilerDispatcherTest, EnqueueAndStepTwice) {
dispatcher.jobs_.begin()->second->status());
ASSERT_TRUE(platform.IdleTaskPending());
ASSERT_TRUE(platform.BackgroundTasksPending());
ASSERT_TRUE(platform.WorkerTasksPending());
platform.ClearIdleTask();
platform.ClearBackgroundTasks();
platform.ClearWorkerTasks();
}
TEST_F(CompilerDispatcherTest, CompileMultipleOnBackgroundThread) {
@ -1033,12 +1033,12 @@ TEST_F(CompilerDispatcherTest, CompileMultipleOnBackgroundThread) {
ASSERT_FALSE(shared1->is_compiled());
ASSERT_FALSE(shared2->is_compiled());
ASSERT_FALSE(platform.IdleTaskPending());
ASSERT_TRUE(platform.BackgroundTasksPending());
ASSERT_TRUE(platform.WorkerTasksPending());
platform.RunBackgroundTasksAndBlock(V8::GetCurrentPlatform());
platform.RunWorkerTasksAndBlock(V8::GetCurrentPlatform());
ASSERT_TRUE(platform.IdleTaskPending());
ASSERT_FALSE(platform.BackgroundTasksPending());
ASSERT_FALSE(platform.WorkerTasksPending());
ASSERT_EQ(dispatcher.jobs_.size(), 2u);
ASSERT_EQ(UnoptimizedCompileJob::Status::kCompiled,
dispatcher.jobs_.begin()->second->status());

View File

@ -9,6 +9,7 @@
#include "src/ast/ast.h"
#include "src/ast/scopes.h"
#include "src/base/platform/semaphore.h"
#include "src/base/template-utils.h"
#include "src/compiler-dispatcher/compiler-dispatcher-job.h"
#include "src/compiler-dispatcher/compiler-dispatcher-tracer.h"
#include "src/compiler-dispatcher/unoptimized-compile-job.h"
@ -226,9 +227,9 @@ TEST_F(UnoptimizedCompileJobTest, CompileOnBackgroundThread) {
ASSERT_FALSE(job->IsFailed());
base::Semaphore semaphore(0);
CompileTask* background_task = new CompileTask(job.get(), &semaphore);
auto background_task = base::make_unique<CompileTask>(job.get(), &semaphore);
ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kPrepared, job);
V8::GetCurrentPlatform()->CallOnWorkerThread(background_task);
V8::GetCurrentPlatform()->CallOnWorkerThread(std::move(background_task));
semaphore.Wait();
job->FinalizeOnMainThread(isolate());
ASSERT_FALSE(job->IsFailed());