Commit 1e0d18dc authored by Etienne Pierre-doray's avatar Etienne Pierre-doray Committed by V8 LUCI CQ

[task] Expose CreateJob in v8::Platform

CreateJob() is similar to PostJob() but doesn't schedule anything
until Join() or Notify*() is called.
This allows
- CreateJob().Join() without too many worker.
- Early 'empty' CreateJob() for initialization
  without causing spurious calls to GetMaxConcurrency()

Bug: chromium:1287665
Change-Id: I8fd8b139392ad30218f0cf8f580b2d76f1078777
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3668842Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Commit-Queue: Etienne Pierre-Doray <etiennep@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81166}
parent 8bd3a441
...@@ -1056,17 +1056,33 @@ class Platform { ...@@ -1056,17 +1056,33 @@ class Platform {
* thread (A=>B/B=>A deadlock) and [2] JobTask::Run or * thread (A=>B/B=>A deadlock) and [2] JobTask::Run or
* JobTask::GetMaxConcurrency may be invoked synchronously from JobHandle * JobTask::GetMaxConcurrency may be invoked synchronously from JobHandle
* (B=>JobHandle::foo=>B deadlock). * (B=>JobHandle::foo=>B deadlock).
*/
virtual std::unique_ptr<JobHandle> PostJob(
TaskPriority priority, std::unique_ptr<JobTask> job_task) {
auto handle = CreateJob(priority, std::move(job_task));
handle->NotifyConcurrencyIncrease();
return handle;
}
/**
* Creates and returns a JobHandle associated with a Job. Unlike PostJob(),
* this doesn't immediately schedules |worker_task| to run; the Job is then
* scheduled by calling either NotifyConcurrencyIncrease() or Join().
* *
* A sufficient PostJob() implementation that uses the default Job provided in * A sufficient CreateJob() implementation that uses the default Job provided
* libplatform looks like: * in libplatform looks like:
* std::unique_ptr<JobHandle> PostJob( * std::unique_ptr<JobHandle> CreateJob(
* TaskPriority priority, std::unique_ptr<JobTask> job_task) override { * TaskPriority priority, std::unique_ptr<JobTask> job_task) override {
* return v8::platform::NewDefaultJobHandle( * return v8::platform::NewDefaultJobHandle(
* this, priority, std::move(job_task), NumberOfWorkerThreads()); * this, priority, std::move(job_task), NumberOfWorkerThreads());
* } * }
*
* TODO(etiennep): Make pure virtual once custom embedders implement it.
*/ */
virtual std::unique_ptr<JobHandle> PostJob( virtual std::unique_ptr<JobHandle> CreateJob(
TaskPriority priority, std::unique_ptr<JobTask> job_task) = 0; TaskPriority priority, std::unique_ptr<JobTask> job_task) {
return nullptr;
}
/** /**
* Monotonically increasing time in seconds from an arbitrary fixed point in * Monotonically increasing time in seconds from an arbitrary fixed point in
......
...@@ -77,6 +77,16 @@ class PredictablePlatform final : public Platform { ...@@ -77,6 +77,16 @@ class PredictablePlatform final : public Platform {
TaskPriority priority, std::unique_ptr<JobTask> job_task) override { TaskPriority priority, std::unique_ptr<JobTask> job_task) override {
// Do not call {platform_->PostJob} here, as this would create a job that // Do not call {platform_->PostJob} here, as this would create a job that
// posts tasks directly to the underlying default platform. // posts tasks directly to the underlying default platform.
std::unique_ptr<JobHandle> handle =
CreateJob(priority, std::move(job_task));
handle->NotifyConcurrencyIncrease();
return handle;
}
std::unique_ptr<JobHandle> CreateJob(
TaskPriority priority, std::unique_ptr<JobTask> job_task) override {
// Do not call {platform_->PostJob} here, as this would create a job that
// posts tasks directly to the underlying default platform.
return platform::NewDefaultJobHandle(this, priority, std::move(job_task), return platform::NewDefaultJobHandle(this, priority, std::move(job_task),
NumberOfWorkerThreads()); NumberOfWorkerThreads());
} }
...@@ -190,6 +200,11 @@ class DelayedTasksPlatform final : public Platform { ...@@ -190,6 +200,11 @@ class DelayedTasksPlatform final : public Platform {
return platform_->PostJob(priority, MakeDelayedJob(std::move(job_task))); return platform_->PostJob(priority, MakeDelayedJob(std::move(job_task)));
} }
std::unique_ptr<JobHandle> CreateJob(
TaskPriority priority, std::unique_ptr<JobTask> job_task) override {
return platform_->CreateJob(priority, MakeDelayedJob(std::move(job_task)));
}
double MonotonicallyIncreasingTime() override { double MonotonicallyIncreasingTime() override {
return platform_->MonotonicallyIncreasingTime(); return platform_->MonotonicallyIncreasingTime();
} }
......
...@@ -214,9 +214,7 @@ void DefaultJobState::UpdatePriority(TaskPriority priority) { ...@@ -214,9 +214,7 @@ void DefaultJobState::UpdatePriority(TaskPriority priority) {
} }
DefaultJobHandle::DefaultJobHandle(std::shared_ptr<DefaultJobState> state) DefaultJobHandle::DefaultJobHandle(std::shared_ptr<DefaultJobState> state)
: state_(std::move(state)) { : state_(std::move(state)) {}
state_->NotifyConcurrencyIncrease();
}
DefaultJobHandle::~DefaultJobHandle() { DCHECK_EQ(nullptr, state_); } DefaultJobHandle::~DefaultJobHandle() { DCHECK_EQ(nullptr, state_); }
......
...@@ -229,6 +229,13 @@ bool DefaultPlatform::IdleTasksEnabled(Isolate* isolate) { ...@@ -229,6 +229,13 @@ bool DefaultPlatform::IdleTasksEnabled(Isolate* isolate) {
std::unique_ptr<JobHandle> DefaultPlatform::PostJob( std::unique_ptr<JobHandle> DefaultPlatform::PostJob(
TaskPriority priority, std::unique_ptr<JobTask> job_task) { TaskPriority priority, std::unique_ptr<JobTask> job_task) {
std::unique_ptr<JobHandle> handle = CreateJob(priority, std::move(job_task));
handle->NotifyConcurrencyIncrease();
return handle;
}
std::unique_ptr<JobHandle> DefaultPlatform::CreateJob(
TaskPriority priority, std::unique_ptr<JobTask> job_task) {
size_t num_worker_threads = NumberOfWorkerThreads(); size_t num_worker_threads = NumberOfWorkerThreads();
if (priority == TaskPriority::kBestEffort && num_worker_threads > 2) { if (priority == TaskPriority::kBestEffort && num_worker_threads > 2) {
num_worker_threads = 2; num_worker_threads = 2;
......
...@@ -63,6 +63,8 @@ class V8_PLATFORM_EXPORT DefaultPlatform : public NON_EXPORTED_BASE(Platform) { ...@@ -63,6 +63,8 @@ class V8_PLATFORM_EXPORT DefaultPlatform : public NON_EXPORTED_BASE(Platform) {
bool IdleTasksEnabled(Isolate* isolate) override; bool IdleTasksEnabled(Isolate* isolate) override;
std::unique_ptr<JobHandle> PostJob( std::unique_ptr<JobHandle> PostJob(
TaskPriority priority, std::unique_ptr<JobTask> job_state) override; TaskPriority priority, std::unique_ptr<JobTask> job_state) override;
std::unique_ptr<JobHandle> CreateJob(
TaskPriority priority, std::unique_ptr<JobTask> job_state) override;
double MonotonicallyIncreasingTime() override; double MonotonicallyIncreasingTime() override;
double CurrentClockTimeMillis() override; double CurrentClockTimeMillis() override;
v8::TracingController* GetTracingController() override; v8::TracingController* GetTracingController() override;
......
...@@ -498,6 +498,11 @@ std::unique_ptr<v8::JobHandle> TestPlatform::PostJob( ...@@ -498,6 +498,11 @@ std::unique_ptr<v8::JobHandle> TestPlatform::PostJob(
return CcTest::default_platform()->PostJob(priority, std::move(job_task)); return CcTest::default_platform()->PostJob(priority, std::move(job_task));
} }
std::unique_ptr<v8::JobHandle> TestPlatform::CreateJob(
v8::TaskPriority priority, std::unique_ptr<v8::JobTask> job_task) {
return CcTest::default_platform()->CreateJob(priority, std::move(job_task));
}
double TestPlatform::MonotonicallyIncreasingTime() { double TestPlatform::MonotonicallyIncreasingTime() {
return CcTest::default_platform()->MonotonicallyIncreasingTime(); return CcTest::default_platform()->MonotonicallyIncreasingTime();
} }
......
...@@ -731,6 +731,9 @@ class TestPlatform : public v8::Platform { ...@@ -731,6 +731,9 @@ class TestPlatform : public v8::Platform {
std::unique_ptr<v8::JobHandle> PostJob( std::unique_ptr<v8::JobHandle> PostJob(
v8::TaskPriority priority, v8::TaskPriority priority,
std::unique_ptr<v8::JobTask> job_task) override; std::unique_ptr<v8::JobTask> job_task) override;
std::unique_ptr<v8::JobHandle> CreateJob(
v8::TaskPriority priority,
std::unique_ptr<v8::JobTask> job_task) override;
double MonotonicallyIncreasingTime() override; double MonotonicallyIncreasingTime() override;
double CurrentClockTimeMillis() override; double CurrentClockTimeMillis() override;
bool IdleTasksEnabled(v8::Isolate* isolate) override; bool IdleTasksEnabled(v8::Isolate* isolate) override;
......
...@@ -37,6 +37,14 @@ class MockPlatform final : public TestPlatform { ...@@ -37,6 +37,14 @@ class MockPlatform final : public TestPlatform {
std::unique_ptr<v8::JobHandle> PostJob( std::unique_ptr<v8::JobHandle> PostJob(
v8::TaskPriority priority, v8::TaskPriority priority,
std::unique_ptr<v8::JobTask> job_task) override { std::unique_ptr<v8::JobTask> job_task) override {
auto job_handle = CreateJob(priority, std::move(job_task));
job_handle->NotifyConcurrencyIncrease();
return job_handle;
}
std::unique_ptr<v8::JobHandle> CreateJob(
v8::TaskPriority priority,
std::unique_ptr<v8::JobTask> job_task) override {
auto orig_job_handle = v8::platform::NewDefaultJobHandle( auto orig_job_handle = v8::platform::NewDefaultJobHandle(
this, priority, std::move(job_task), 1); this, priority, std::move(job_task), 1);
auto job_handle = auto job_handle =
......
...@@ -34,6 +34,14 @@ class MockPlatform final : public TestPlatform { ...@@ -34,6 +34,14 @@ class MockPlatform final : public TestPlatform {
std::unique_ptr<v8::JobHandle> PostJob( std::unique_ptr<v8::JobHandle> PostJob(
v8::TaskPriority priority, v8::TaskPriority priority,
std::unique_ptr<v8::JobTask> job_task) override { std::unique_ptr<v8::JobTask> job_task) override {
auto job_handle = CreateJob(priority, std::move(job_task));
job_handle->NotifyConcurrencyIncrease();
return job_handle;
}
std::unique_ptr<v8::JobHandle> CreateJob(
v8::TaskPriority priority,
std::unique_ptr<v8::JobTask> job_task) override {
auto orig_job_handle = v8::platform::NewDefaultJobHandle( auto orig_job_handle = v8::platform::NewDefaultJobHandle(
this, priority, std::move(job_task), 1); this, priority, std::move(job_task), 1);
auto job_handle = auto job_handle =
......
...@@ -106,8 +106,7 @@ class DeferredPostJob { ...@@ -106,8 +106,7 @@ class DeferredPostJob {
if (real_handle()) { if (real_handle()) {
real_handle()->NotifyConcurrencyIncrease(); real_handle()->NotifyConcurrencyIncrease();
} }
// No need to defer the NotifyConcurrencyIncrease, we'll automatically owner_->NotifyConcurrencyIncrease();
// check concurrency when posting the job.
} }
void Cancel() final { void Cancel() final {
set_cancelled(); set_cancelled();
...@@ -137,7 +136,7 @@ class DeferredPostJob { ...@@ -137,7 +136,7 @@ class DeferredPostJob {
if (deferred_handle_) deferred_handle_->ClearOwner(); if (deferred_handle_) deferred_handle_->ClearOwner();
} }
std::unique_ptr<JobHandle> DeferPostJob(TaskPriority priority, std::unique_ptr<JobHandle> CreateJob(TaskPriority priority,
std::unique_ptr<JobTask> job_task) { std::unique_ptr<JobTask> job_task) {
DCHECK_NULL(job_task_); DCHECK_NULL(job_task_);
job_task_ = std::move(job_task); job_task_ = std::move(job_task);
...@@ -145,12 +144,17 @@ class DeferredPostJob { ...@@ -145,12 +144,17 @@ class DeferredPostJob {
return std::make_unique<DeferredJobHandle>(this); return std::make_unique<DeferredJobHandle>(this);
} }
void NotifyConcurrencyIncrease() { do_post_ = true; }
bool IsPending() { return job_task_ != nullptr; } bool IsPending() { return job_task_ != nullptr; }
void Clear() { job_task_.reset(); } void Clear() { job_task_.reset(); }
void DoRealPostJob(Platform* platform) { void DoRealPostJob(Platform* platform) {
if (do_post_)
real_handle_ = platform->PostJob(priority_, std::move(job_task_)); real_handle_ = platform->PostJob(priority_, std::move(job_task_));
else
real_handle_ = platform->CreateJob(priority_, std::move(job_task_));
if (was_cancelled_) { if (was_cancelled_) {
real_handle_->Cancel(); real_handle_->Cancel();
} }
...@@ -180,6 +184,7 @@ class DeferredPostJob { ...@@ -180,6 +184,7 @@ class DeferredPostJob {
std::unique_ptr<JobHandle> real_handle_ = nullptr; std::unique_ptr<JobHandle> real_handle_ = nullptr;
bool was_cancelled_ = false; bool was_cancelled_ = false;
bool do_post_ = false;
}; };
class MockPlatform : public v8::Platform { class MockPlatform : public v8::Platform {
...@@ -217,7 +222,14 @@ class MockPlatform : public v8::Platform { ...@@ -217,7 +222,14 @@ class MockPlatform : public v8::Platform {
std::unique_ptr<JobHandle> PostJob( std::unique_ptr<JobHandle> PostJob(
TaskPriority priority, std::unique_ptr<JobTask> job_task) override { TaskPriority priority, std::unique_ptr<JobTask> job_task) override {
return deferred_post_job_.DeferPostJob(priority, std::move(job_task)); auto handle = deferred_post_job_.CreateJob(priority, std::move(job_task));
deferred_post_job_.NotifyConcurrencyIncrease();
return handle;
}
std::unique_ptr<JobHandle> CreateJob(
TaskPriority priority, std::unique_ptr<JobTask> job_task) override {
return deferred_post_job_.CreateJob(priority, std::move(job_task));
} }
double MonotonicallyIncreasingTime() override { double MonotonicallyIncreasingTime() override {
......
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