aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/test/unittests/compiler-dispatcher/compiler-dispatcher-unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/test/unittests/compiler-dispatcher/compiler-dispatcher-unittest.cc')
-rw-r--r--deps/v8/test/unittests/compiler-dispatcher/compiler-dispatcher-unittest.cc475
1 files changed, 159 insertions, 316 deletions
diff --git a/deps/v8/test/unittests/compiler-dispatcher/compiler-dispatcher-unittest.cc b/deps/v8/test/unittests/compiler-dispatcher/compiler-dispatcher-unittest.cc
index bfc111aed5..0f918e3a07 100644
--- a/deps/v8/test/unittests/compiler-dispatcher/compiler-dispatcher-unittest.cc
+++ b/deps/v8/test/unittests/compiler-dispatcher/compiler-dispatcher-unittest.cc
@@ -13,9 +13,6 @@
#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"
#include "src/compiler.h"
#include "src/flags.h"
#include "src/handles.h"
@@ -88,9 +85,11 @@ class CompilerDispatcherTest : public TestWithNativeContext {
outer_parse_info->zone(), script_scope, FUNCTION_SCOPE);
function_scope->set_start_position(shared->StartPosition());
function_scope->set_end_position(shared->EndPosition());
+ std::vector<void*> pointer_buffer;
+ ScopedPtrList<Statement> statements(&pointer_buffer);
const FunctionLiteral* function_literal =
ast_node_factory.NewFunctionLiteral(
- function_name, function_scope, nullptr, -1, -1, -1,
+ function_name, function_scope, statements, -1, -1, -1,
FunctionLiteral::kNoDuplicateParameters,
FunctionLiteral::kAnonymousExpression,
FunctionLiteral::kShouldEagerCompile, shared->StartPosition(), true,
@@ -115,7 +114,7 @@ class MockPlatform : public v8::Platform {
sem_(0),
tracing_controller_(V8::GetCurrentPlatform()->GetTracingController()) {}
~MockPlatform() override {
- base::LockGuard<base::Mutex> lock(&mutex_);
+ base::MutexGuard lock(&mutex_);
EXPECT_TRUE(foreground_tasks_.empty());
EXPECT_TRUE(worker_tasks_.empty());
EXPECT_TRUE(idle_task_ == nullptr);
@@ -129,7 +128,7 @@ class MockPlatform : public v8::Platform {
}
void CallOnWorkerThread(std::unique_ptr<Task> task) override {
- base::LockGuard<base::Mutex> lock(&mutex_);
+ base::MutexGuard lock(&mutex_);
worker_tasks_.push_back(std::move(task));
}
@@ -139,7 +138,7 @@ class MockPlatform : public v8::Platform {
}
void CallOnForegroundThread(v8::Isolate* isolate, Task* task) override {
- base::LockGuard<base::Mutex> lock(&mutex_);
+ base::MutexGuard lock(&mutex_);
foreground_tasks_.push_back(std::unique_ptr<Task>(task));
}
@@ -150,7 +149,7 @@ class MockPlatform : public v8::Platform {
void CallIdleOnForegroundThread(v8::Isolate* isolate,
IdleTask* task) override {
- base::LockGuard<base::Mutex> lock(&mutex_);
+ base::MutexGuard lock(&mutex_);
ASSERT_TRUE(idle_task_ == nullptr);
idle_task_ = task;
}
@@ -174,7 +173,7 @@ class MockPlatform : public v8::Platform {
time_step_ = time_step;
IdleTask* task;
{
- base::LockGuard<base::Mutex> lock(&mutex_);
+ base::MutexGuard lock(&mutex_);
task = idle_task_;
ASSERT_TRUE(idle_task_ != nullptr);
idle_task_ = nullptr;
@@ -184,24 +183,24 @@ class MockPlatform : public v8::Platform {
}
bool IdleTaskPending() {
- base::LockGuard<base::Mutex> lock(&mutex_);
+ base::MutexGuard lock(&mutex_);
return idle_task_;
}
bool WorkerTasksPending() {
- base::LockGuard<base::Mutex> lock(&mutex_);
+ base::MutexGuard lock(&mutex_);
return !worker_tasks_.empty();
}
bool ForegroundTasksPending() {
- base::LockGuard<base::Mutex> lock(&mutex_);
+ base::MutexGuard lock(&mutex_);
return !foreground_tasks_.empty();
}
void RunWorkerTasksAndBlock(Platform* platform) {
std::vector<std::unique_ptr<Task>> tasks;
{
- base::LockGuard<base::Mutex> lock(&mutex_);
+ base::MutexGuard lock(&mutex_);
tasks.swap(worker_tasks_);
}
platform->CallOnWorkerThread(
@@ -212,7 +211,7 @@ class MockPlatform : public v8::Platform {
void RunWorkerTasks(Platform* platform) {
std::vector<std::unique_ptr<Task>> tasks;
{
- base::LockGuard<base::Mutex> lock(&mutex_);
+ base::MutexGuard lock(&mutex_);
tasks.swap(worker_tasks_);
}
platform->CallOnWorkerThread(
@@ -222,7 +221,7 @@ class MockPlatform : public v8::Platform {
void RunForegroundTasks() {
std::vector<std::unique_ptr<Task>> tasks;
{
- base::LockGuard<base::Mutex> lock(&mutex_);
+ base::MutexGuard lock(&mutex_);
tasks.swap(foreground_tasks_);
}
for (auto& task : tasks) {
@@ -235,7 +234,7 @@ class MockPlatform : public v8::Platform {
void ClearWorkerTasks() {
std::vector<std::unique_ptr<Task>> tasks;
{
- base::LockGuard<base::Mutex> lock(&mutex_);
+ base::MutexGuard lock(&mutex_);
tasks.swap(worker_tasks_);
}
}
@@ -243,13 +242,13 @@ class MockPlatform : public v8::Platform {
void ClearForegroundTasks() {
std::vector<std::unique_ptr<Task>> tasks;
{
- base::LockGuard<base::Mutex> lock(&mutex_);
+ base::MutexGuard lock(&mutex_);
tasks.swap(foreground_tasks_);
}
}
void ClearIdleTask() {
- base::LockGuard<base::Mutex> lock(&mutex_);
+ base::MutexGuard lock(&mutex_);
ASSERT_TRUE(idle_task_ != nullptr);
delete idle_task_;
idle_task_ = nullptr;
@@ -286,7 +285,7 @@ class MockPlatform : public v8::Platform {
: platform_(platform) {}
void PostTask(std::unique_ptr<v8::Task> task) override {
- base::LockGuard<base::Mutex> lock(&platform_->mutex_);
+ base::MutexGuard lock(&platform_->mutex_);
platform_->foreground_tasks_.push_back(std::move(task));
}
@@ -297,7 +296,7 @@ class MockPlatform : public v8::Platform {
void PostIdleTask(std::unique_ptr<IdleTask> task) override {
DCHECK(IdleTasksEnabled());
- base::LockGuard<base::Mutex> lock(&platform_->mutex_);
+ base::MutexGuard lock(&platform_->mutex_);
ASSERT_TRUE(platform_->idle_task_ == nullptr);
platform_->idle_task_ = task.release();
}
@@ -330,6 +329,7 @@ class MockPlatform : public v8::Platform {
TEST_F(CompilerDispatcherTest, Construct) {
MockPlatform platform;
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
+ dispatcher.AbortAll();
}
TEST_F(CompilerDispatcherTest, IsEnqueued) {
@@ -352,12 +352,13 @@ TEST_F(CompilerDispatcherTest, IsEnqueued) {
ASSERT_TRUE(dispatcher.IsEnqueued(*job_id));
ASSERT_TRUE(dispatcher.IsEnqueued(shared));
- dispatcher.AbortAll(BlockingBehavior::kBlock);
+ dispatcher.AbortAll();
ASSERT_FALSE(dispatcher.IsEnqueued(*job_id));
ASSERT_FALSE(dispatcher.IsEnqueued(shared));
- ASSERT_TRUE(platform.IdleTaskPending());
+
+ ASSERT_FALSE(platform.IdleTaskPending());
+ ASSERT_TRUE(platform.WorkerTasksPending());
platform.ClearWorkerTasks();
- platform.ClearIdleTask();
}
TEST_F(CompilerDispatcherTest, FinishNow) {
@@ -377,12 +378,13 @@ TEST_F(CompilerDispatcherTest, FinishNow) {
ASSERT_FALSE(dispatcher.IsEnqueued(*job_id));
ASSERT_FALSE(dispatcher.IsEnqueued(shared));
ASSERT_TRUE(shared->is_compiled());
- ASSERT_TRUE(platform.IdleTaskPending());
+
platform.ClearWorkerTasks();
- platform.ClearIdleTask();
+ ASSERT_FALSE(platform.IdleTaskPending());
+ dispatcher.AbortAll();
}
-TEST_F(CompilerDispatcherTest, IdleTask) {
+TEST_F(CompilerDispatcherTest, CompileAndFinalize) {
MockPlatform platform;
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
@@ -393,11 +395,10 @@ TEST_F(CompilerDispatcherTest, IdleTask) {
base::Optional<CompilerDispatcher::JobId> job_id =
EnqueueUnoptimizedCompileJob(&dispatcher, i_isolate(), shared);
- ASSERT_TRUE(platform.IdleTaskPending());
+ ASSERT_TRUE(platform.WorkerTasksPending());
- // Since time doesn't progress on the MockPlatform, this is enough idle time
- // to finish compiling the function.
- platform.RunIdleTask(1000.0, 0.0);
+ // Run compile steps.
+ platform.RunWorkerTasksAndBlock(V8::GetCurrentPlatform());
// Since we haven't yet registered the SFI for the job, it should still be
// enqueued and waiting.
@@ -405,7 +406,7 @@ TEST_F(CompilerDispatcherTest, IdleTask) {
ASSERT_FALSE(shared->is_compiled());
ASSERT_FALSE(platform.IdleTaskPending());
- // Register SFI, which should schedule another idle task to complete the
+ // Register SFI, which should schedule another idle task to finalize the
// compilation.
dispatcher.RegisterSharedFunctionInfo(*job_id, *shared);
ASSERT_TRUE(platform.IdleTaskPending());
@@ -413,10 +414,12 @@ TEST_F(CompilerDispatcherTest, IdleTask) {
ASSERT_FALSE(dispatcher.IsEnqueued(shared));
ASSERT_TRUE(shared->is_compiled());
- platform.ClearWorkerTasks();
+ ASSERT_FALSE(platform.WorkerTasksPending());
+ ASSERT_FALSE(platform.IdleTaskPending());
+ dispatcher.AbortAll();
}
-TEST_F(CompilerDispatcherTest, IdleTaskSmallIdleTime) {
+TEST_F(CompilerDispatcherTest, IdleTaskNoIdleTime) {
MockPlatform platform;
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
@@ -429,25 +432,24 @@ TEST_F(CompilerDispatcherTest, IdleTaskSmallIdleTime) {
EnqueueUnoptimizedCompileJob(&dispatcher, i_isolate(), shared);
dispatcher.RegisterSharedFunctionInfo(*job_id, *shared);
- ASSERT_TRUE(platform.IdleTaskPending());
+ // Run compile steps.
+ platform.RunWorkerTasksAndBlock(V8::GetCurrentPlatform());
- // The job should be scheduled for the main thread.
+ // Job should be ready to finalize.
ASSERT_EQ(dispatcher.jobs_.size(), 1u);
- ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
- dispatcher.jobs_.begin()->second->status());
+ ASSERT_TRUE(dispatcher.jobs_.begin()->second->has_run);
+ ASSERT_TRUE(platform.IdleTaskPending());
- // Only grant a little idle time and have time advance beyond it in one step.
- platform.RunIdleTask(2.0, 1.0);
+ // Grant no idle time and have time advance beyond it in one step.
+ platform.RunIdleTask(0.0, 1.0);
ASSERT_TRUE(dispatcher.IsEnqueued(shared));
ASSERT_FALSE(shared->is_compiled());
ASSERT_TRUE(platform.IdleTaskPending());
- // The job should be still scheduled for the main thread, but ready for
- // finalization.
+ // Job should be ready to finalize.
ASSERT_EQ(dispatcher.jobs_.size(), 1u);
- ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToFinalize,
- dispatcher.jobs_.begin()->second->status());
+ ASSERT_TRUE(dispatcher.jobs_.begin()->second->has_run);
// Now grant a lot of idle time and freeze time.
platform.RunIdleTask(1000.0, 0.0);
@@ -455,7 +457,58 @@ TEST_F(CompilerDispatcherTest, IdleTaskSmallIdleTime) {
ASSERT_FALSE(dispatcher.IsEnqueued(shared));
ASSERT_TRUE(shared->is_compiled());
ASSERT_FALSE(platform.IdleTaskPending());
- platform.ClearWorkerTasks();
+ ASSERT_FALSE(platform.WorkerTasksPending());
+ dispatcher.AbortAll();
+}
+
+TEST_F(CompilerDispatcherTest, IdleTaskSmallIdleTime) {
+ MockPlatform platform;
+ CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
+
+ Handle<SharedFunctionInfo> shared_1 =
+ test::CreateSharedFunctionInfo(i_isolate(), nullptr);
+ ASSERT_FALSE(shared_1->is_compiled());
+ Handle<SharedFunctionInfo> shared_2 =
+ test::CreateSharedFunctionInfo(i_isolate(), nullptr);
+ ASSERT_FALSE(shared_2->is_compiled());
+
+ base::Optional<CompilerDispatcher::JobId> job_id_1 =
+ EnqueueUnoptimizedCompileJob(&dispatcher, i_isolate(), shared_1);
+ base::Optional<CompilerDispatcher::JobId> job_id_2 =
+ EnqueueUnoptimizedCompileJob(&dispatcher, i_isolate(), shared_2);
+
+ dispatcher.RegisterSharedFunctionInfo(*job_id_1, *shared_1);
+ dispatcher.RegisterSharedFunctionInfo(*job_id_2, *shared_2);
+
+ // Run compile steps.
+ platform.RunWorkerTasksAndBlock(V8::GetCurrentPlatform());
+
+ // Both jobs should be ready to finalize.
+ ASSERT_EQ(dispatcher.jobs_.size(), 2u);
+ ASSERT_TRUE(dispatcher.jobs_.begin()->second->has_run);
+ ASSERT_TRUE((++dispatcher.jobs_.begin())->second->has_run);
+ ASSERT_TRUE(platform.IdleTaskPending());
+
+ // Grant a small anount of idle time and have time advance beyond it in one
+ // step.
+ platform.RunIdleTask(2.0, 1.0);
+
+ // Only one of the jobs should be finalized.
+ ASSERT_EQ(dispatcher.jobs_.size(), 1u);
+ ASSERT_TRUE(dispatcher.jobs_.begin()->second->has_run);
+ ASSERT_NE(dispatcher.IsEnqueued(shared_1), dispatcher.IsEnqueued(shared_2));
+ ASSERT_NE(shared_1->is_compiled(), shared_2->is_compiled());
+ ASSERT_TRUE(platform.IdleTaskPending());
+
+ // Now grant a lot of idle time and freeze time.
+ platform.RunIdleTask(1000.0, 0.0);
+
+ ASSERT_FALSE(dispatcher.IsEnqueued(shared_1) ||
+ dispatcher.IsEnqueued(shared_2));
+ ASSERT_TRUE(shared_1->is_compiled() && shared_2->is_compiled());
+ ASSERT_FALSE(platform.IdleTaskPending());
+ ASSERT_FALSE(platform.WorkerTasksPending());
+ dispatcher.AbortAll();
}
TEST_F(CompilerDispatcherTest, IdleTaskException) {
@@ -478,49 +531,15 @@ TEST_F(CompilerDispatcherTest, IdleTaskException) {
EnqueueUnoptimizedCompileJob(&dispatcher, i_isolate(), shared);
dispatcher.RegisterSharedFunctionInfo(*job_id, *shared);
- // Since time doesn't progress on the MockPlatform, this is enough idle time
- // to finish compiling the function.
+ // Run compile steps and finalize.
+ platform.RunWorkerTasksAndBlock(V8::GetCurrentPlatform());
platform.RunIdleTask(1000.0, 0.0);
ASSERT_FALSE(dispatcher.IsEnqueued(shared));
ASSERT_FALSE(shared->is_compiled());
ASSERT_FALSE(i_isolate()->has_pending_exception());
platform.ClearWorkerTasks();
-}
-
-TEST_F(CompilerDispatcherTest, CompileOnBackgroundThread) {
- MockPlatform platform;
- CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
-
- Handle<SharedFunctionInfo> shared =
- test::CreateSharedFunctionInfo(i_isolate(), nullptr);
- ASSERT_FALSE(shared->is_compiled());
-
- base::Optional<CompilerDispatcher::JobId> job_id =
- EnqueueUnoptimizedCompileJob(&dispatcher, i_isolate(), shared);
- dispatcher.RegisterSharedFunctionInfo(*job_id, *shared);
-
- ASSERT_TRUE(dispatcher.IsEnqueued(shared));
- ASSERT_FALSE(shared->is_compiled());
- ASSERT_EQ(dispatcher.jobs_.size(), 1u);
- ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
- dispatcher.jobs_.begin()->second->status());
- ASSERT_TRUE(platform.WorkerTasksPending());
-
- platform.RunWorkerTasksAndBlock(V8::GetCurrentPlatform());
-
- ASSERT_TRUE(platform.IdleTaskPending());
- ASSERT_FALSE(platform.WorkerTasksPending());
- ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToFinalize,
- dispatcher.jobs_.begin()->second->status());
-
- // Now grant a lot of idle time and freeze time.
- platform.RunIdleTask(1000.0, 0.0);
-
- ASSERT_FALSE(dispatcher.IsEnqueued(shared));
- ASSERT_TRUE(shared->is_compiled());
- ASSERT_FALSE(platform.IdleTaskPending());
- ASSERT_FALSE(platform.WorkerTasksPending());
+ dispatcher.AbortAll();
}
TEST_F(CompilerDispatcherTest, FinishNowWithWorkerTask) {
@@ -536,14 +555,12 @@ TEST_F(CompilerDispatcherTest, FinishNowWithWorkerTask) {
dispatcher.RegisterSharedFunctionInfo(*job_id, *shared);
ASSERT_EQ(dispatcher.jobs_.size(), 1u);
- ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
- dispatcher.jobs_.begin()->second->status());
+ ASSERT_FALSE(dispatcher.jobs_.begin()->second->has_run);
ASSERT_TRUE(dispatcher.IsEnqueued(shared));
ASSERT_FALSE(shared->is_compiled());
ASSERT_EQ(dispatcher.jobs_.size(), 1u);
- ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
- dispatcher.jobs_.begin()->second->status());
+ ASSERT_FALSE(dispatcher.jobs_.begin()->second->has_run);
ASSERT_TRUE(platform.WorkerTasksPending());
// This does not block, but races with the FinishNow() call below.
@@ -555,6 +572,7 @@ TEST_F(CompilerDispatcherTest, FinishNowWithWorkerTask) {
ASSERT_TRUE(shared->is_compiled());
if (platform.IdleTaskPending()) platform.ClearIdleTask();
ASSERT_FALSE(platform.WorkerTasksPending());
+ dispatcher.AbortAll();
}
TEST_F(CompilerDispatcherTest, IdleTaskMultipleJobs) {
@@ -579,15 +597,17 @@ TEST_F(CompilerDispatcherTest, IdleTaskMultipleJobs) {
ASSERT_TRUE(dispatcher.IsEnqueued(shared_1));
ASSERT_TRUE(dispatcher.IsEnqueued(shared_2));
- // Since time doesn't progress on the MockPlatform, this is enough idle time
- // to finish compiling the function.
+ // Run compile steps and finalize.
+ platform.RunWorkerTasksAndBlock(V8::GetCurrentPlatform());
platform.RunIdleTask(1000.0, 0.0);
ASSERT_FALSE(dispatcher.IsEnqueued(shared_1));
ASSERT_FALSE(dispatcher.IsEnqueued(shared_2));
ASSERT_TRUE(shared_1->is_compiled());
ASSERT_TRUE(shared_2->is_compiled());
- platform.ClearWorkerTasks();
+ ASSERT_FALSE(platform.IdleTaskPending());
+ ASSERT_FALSE(platform.WorkerTasksPending());
+ dispatcher.AbortAll();
}
TEST_F(CompilerDispatcherTest, FinishNowException) {
@@ -617,11 +637,12 @@ TEST_F(CompilerDispatcherTest, FinishNowException) {
ASSERT_TRUE(i_isolate()->has_pending_exception());
i_isolate()->clear_pending_exception();
- platform.ClearIdleTask();
+ ASSERT_FALSE(platform.IdleTaskPending());
platform.ClearWorkerTasks();
+ dispatcher.AbortAll();
}
-TEST_F(CompilerDispatcherTest, AsyncAbortAllPendingWorkerTask) {
+TEST_F(CompilerDispatcherTest, AbortJobNotStarted) {
MockPlatform platform;
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
@@ -631,107 +652,27 @@ TEST_F(CompilerDispatcherTest, AsyncAbortAllPendingWorkerTask) {
base::Optional<CompilerDispatcher::JobId> job_id =
EnqueueUnoptimizedCompileJob(&dispatcher, i_isolate(), shared);
- dispatcher.RegisterSharedFunctionInfo(*job_id, *shared);
ASSERT_EQ(dispatcher.jobs_.size(), 1u);
- ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
- dispatcher.jobs_.begin()->second->status());
- ASSERT_TRUE(dispatcher.IsEnqueued(shared));
- ASSERT_FALSE(shared->is_compiled());
- ASSERT_TRUE(platform.WorkerTasksPending());
+ ASSERT_FALSE(dispatcher.jobs_.begin()->second->has_run);
- // The background task hasn't yet started, so we can just cancel it.
- dispatcher.AbortAll(BlockingBehavior::kDontBlock);
- ASSERT_FALSE(platform.ForegroundTasksPending());
-
- ASSERT_FALSE(dispatcher.IsEnqueued(shared));
+ ASSERT_TRUE(dispatcher.IsEnqueued(*job_id));
ASSERT_FALSE(shared->is_compiled());
-
- platform.RunWorkerTasksAndBlock(V8::GetCurrentPlatform());
-
- if (platform.IdleTaskPending()) platform.ClearIdleTask();
- ASSERT_FALSE(platform.WorkerTasksPending());
- ASSERT_FALSE(platform.ForegroundTasksPending());
-}
-
-TEST_F(CompilerDispatcherTest, AsyncAbortAllRunningWorkerTask) {
- MockPlatform platform;
- CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
-
- Handle<SharedFunctionInfo> shared_1 =
- test::CreateSharedFunctionInfo(i_isolate(), nullptr);
- ASSERT_FALSE(shared_1->is_compiled());
- Handle<SharedFunctionInfo> shared_2 =
- test::CreateSharedFunctionInfo(i_isolate(), nullptr);
- ASSERT_FALSE(shared_2->is_compiled());
-
- base::Optional<CompilerDispatcher::JobId> job_id_1 =
- EnqueueUnoptimizedCompileJob(&dispatcher, i_isolate(), shared_1);
- dispatcher.RegisterSharedFunctionInfo(*job_id_1, *shared_1);
-
ASSERT_EQ(dispatcher.jobs_.size(), 1u);
- ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
- dispatcher.jobs_.begin()->second->status());
- ASSERT_TRUE(dispatcher.IsEnqueued(shared_1));
- ASSERT_FALSE(shared_1->is_compiled());
- ASSERT_TRUE(platform.IdleTaskPending());
+ ASSERT_FALSE(dispatcher.jobs_.begin()->second->has_run);
ASSERT_TRUE(platform.WorkerTasksPending());
- // Kick off background tasks and freeze them.
- dispatcher.block_for_testing_.SetValue(true);
- platform.RunWorkerTasks(V8::GetCurrentPlatform());
+ dispatcher.AbortJob(*job_id);
- // Busy loop until the background task started running.
- while (dispatcher.block_for_testing_.Value()) {
- }
- dispatcher.AbortAll(BlockingBehavior::kDontBlock);
- ASSERT_TRUE(platform.ForegroundTasksPending());
-
- // We can't schedule new tasks while we're aborting.
- base::Optional<CompilerDispatcher::JobId> job_id_2 =
- EnqueueUnoptimizedCompileJob(&dispatcher, i_isolate(), shared_2);
- ASSERT_FALSE(job_id_2);
-
- // Run the first AbortTask. Since the background job is still pending, it
- // can't do anything.
- platform.RunForegroundTasks();
- {
- base::LockGuard<base::Mutex> lock(&dispatcher.mutex_);
- ASSERT_TRUE(dispatcher.abort_);
- }
-
- // Release background task.
- dispatcher.semaphore_for_testing_.Signal();
-
- // Busy loop until the background task scheduled another AbortTask task.
- while (!platform.ForegroundTasksPending()) {
- }
-
- platform.RunForegroundTasks();
- ASSERT_TRUE(dispatcher.jobs_.empty());
- {
- base::LockGuard<base::Mutex> lock(&dispatcher.mutex_);
- ASSERT_FALSE(dispatcher.abort_);
- }
-
- ASSERT_TRUE(platform.IdleTaskPending());
- platform.RunIdleTask(5.0, 1.0);
- ASSERT_FALSE(platform.WorkerTasksPending());
- ASSERT_FALSE(platform.ForegroundTasksPending());
-
- // Now it's possible to enqueue new functions again.
- job_id_2 = EnqueueUnoptimizedCompileJob(&dispatcher, i_isolate(), shared_2);
- ASSERT_TRUE(job_id_2);
- ASSERT_TRUE(platform.IdleTaskPending());
- ASSERT_TRUE(platform.WorkerTasksPending());
- ASSERT_FALSE(platform.ForegroundTasksPending());
-
- dispatcher.AbortAll(BlockingBehavior::kBlock);
+ // Aborting removes the job from the queue.
+ ASSERT_FALSE(dispatcher.IsEnqueued(*job_id));
+ ASSERT_FALSE(shared->is_compiled());
+ ASSERT_FALSE(platform.IdleTaskPending());
platform.ClearWorkerTasks();
- platform.ClearIdleTask();
+ dispatcher.AbortAll();
}
-TEST_F(CompilerDispatcherTest, FinishNowDuringAbortAll) {
+TEST_F(CompilerDispatcherTest, AbortJobAlreadyStarted) {
MockPlatform platform;
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
@@ -741,154 +682,59 @@ TEST_F(CompilerDispatcherTest, FinishNowDuringAbortAll) {
base::Optional<CompilerDispatcher::JobId> job_id =
EnqueueUnoptimizedCompileJob(&dispatcher, i_isolate(), shared);
- dispatcher.RegisterSharedFunctionInfo(*job_id, *shared);
- ASSERT_TRUE(dispatcher.IsEnqueued(shared));
+ ASSERT_EQ(dispatcher.jobs_.size(), 1u);
+ ASSERT_FALSE(dispatcher.jobs_.begin()->second->has_run);
+
+ ASSERT_TRUE(dispatcher.IsEnqueued(*job_id));
ASSERT_FALSE(shared->is_compiled());
ASSERT_EQ(dispatcher.jobs_.size(), 1u);
- ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
- dispatcher.jobs_.begin()->second->status());
- ASSERT_TRUE(platform.IdleTaskPending());
+ ASSERT_FALSE(dispatcher.jobs_.begin()->second->has_run);
ASSERT_TRUE(platform.WorkerTasksPending());
- // Kick off background tasks and freeze them.
- dispatcher.block_for_testing_.SetValue(true);
- platform.RunWorkerTasks(V8::GetCurrentPlatform());
-
- // Busy loop until the background task started running.
- while (dispatcher.block_for_testing_.Value()) {
- }
- dispatcher.AbortAll(BlockingBehavior::kDontBlock);
- ASSERT_TRUE(platform.ForegroundTasksPending());
-
- // Run the first AbortTask. Since the background job is still pending, it
- // can't do anything.
- platform.RunForegroundTasks();
+ // Have dispatcher block on the background thread when running the job.
{
base::LockGuard<base::Mutex> lock(&dispatcher.mutex_);
- ASSERT_TRUE(dispatcher.abort_);
+ dispatcher.block_for_testing_.SetValue(true);
}
- // Run the idle task, which should have already been canceled and won't do
- // anything.
- ASSERT_TRUE(platform.IdleTaskPending());
- platform.RunIdleTask(5.0, 1.0);
-
- // While the background thread holds on to a job, it is still enqueued.
- ASSERT_TRUE(dispatcher.IsEnqueued(shared));
-
- // Release background task.
- dispatcher.semaphore_for_testing_.Signal();
-
- // Force the compilation to finish, even while aborting.
- ASSERT_TRUE(dispatcher.FinishNow(shared));
- ASSERT_TRUE(dispatcher.jobs_.empty());
-
- // Busy wait for the background task to finish.
- for (;;) {
- base::LockGuard<base::Mutex> lock(&dispatcher.mutex_);
- if (dispatcher.num_worker_tasks_ == 0) {
- break;
- }
+ // Start background thread and wait until it is about to run the job.
+ platform.RunWorkerTasks(V8::GetCurrentPlatform());
+ while (dispatcher.block_for_testing_.Value()) {
}
- ASSERT_TRUE(platform.ForegroundTasksPending());
- ASSERT_FALSE(platform.IdleTaskPending());
- ASSERT_FALSE(platform.WorkerTasksPending());
+ // Now abort while dispatcher is in the middle of running the job.
+ dispatcher.AbortJob(*job_id);
- platform.RunForegroundTasks();
+ // Unblock background thread, and wait for job to complete.
{
base::LockGuard<base::Mutex> lock(&dispatcher.mutex_);
- ASSERT_FALSE(dispatcher.abort_);
+ dispatcher.main_thread_blocking_on_job_ =
+ dispatcher.jobs_.begin()->second.get();
+ dispatcher.semaphore_for_testing_.Signal();
+ while (dispatcher.main_thread_blocking_on_job_ != nullptr) {
+ dispatcher.main_thread_blocking_signal_.Wait(&dispatcher.mutex_);
+ }
}
-}
-TEST_F(CompilerDispatcherTest, MemoryPressure) {
- MockPlatform platform;
- CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
-
- Handle<SharedFunctionInfo> shared =
- test::CreateSharedFunctionInfo(i_isolate(), nullptr);
+ // Job should have finished running and then been aborted.
+ ASSERT_TRUE(dispatcher.IsEnqueued(*job_id));
ASSERT_FALSE(shared->is_compiled());
+ ASSERT_EQ(dispatcher.jobs_.size(), 1u);
+ ASSERT_TRUE(dispatcher.jobs_.begin()->second->has_run);
+ ASSERT_TRUE(dispatcher.jobs_.begin()->second->aborted);
+ ASSERT_FALSE(platform.WorkerTasksPending());
+ ASSERT_TRUE(platform.IdleTaskPending());
- // Can't enqueue tasks under memory pressure.
- dispatcher.MemoryPressureNotification(v8::MemoryPressureLevel::kCritical,
- true);
- base::Optional<CompilerDispatcher::JobId> job_id =
- EnqueueUnoptimizedCompileJob(&dispatcher, i_isolate(), shared);
- ASSERT_FALSE(job_id);
-
- dispatcher.MemoryPressureNotification(v8::MemoryPressureLevel::kNone, true);
-
- job_id = EnqueueUnoptimizedCompileJob(&dispatcher, i_isolate(), shared);
- ASSERT_TRUE(job_id);
+ // Runt the pending idle task
+ platform.RunIdleTask(1000.0, 0.0);
- // Memory pressure cancels current jobs.
- dispatcher.MemoryPressureNotification(v8::MemoryPressureLevel::kCritical,
- true);
+ // Aborting removes the SFI from the queue.
ASSERT_FALSE(dispatcher.IsEnqueued(*job_id));
- platform.ClearIdleTask();
- platform.ClearWorkerTasks();
-}
-
-namespace {
-
-class PressureNotificationTask : public CancelableTask {
- public:
- PressureNotificationTask(Isolate* isolate, CompilerDispatcher* dispatcher,
- base::Semaphore* sem)
- : CancelableTask(isolate), dispatcher_(dispatcher), sem_(sem) {}
- ~PressureNotificationTask() override = default;
-
- void RunInternal() override {
- dispatcher_->MemoryPressureNotification(v8::MemoryPressureLevel::kCritical,
- false);
- sem_->Signal();
- }
-
- private:
- CompilerDispatcher* dispatcher_;
- base::Semaphore* sem_;
-
- DISALLOW_COPY_AND_ASSIGN(PressureNotificationTask);
-};
-
-} // namespace
-
-TEST_F(CompilerDispatcherTest, MemoryPressureFromBackground) {
- MockPlatform platform;
- CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
-
- Handle<SharedFunctionInfo> shared =
- test::CreateSharedFunctionInfo(i_isolate(), nullptr);
- ASSERT_FALSE(shared->is_compiled());
-
- base::Optional<CompilerDispatcher::JobId> job_id =
- EnqueueUnoptimizedCompileJob(&dispatcher, i_isolate(), shared);
- dispatcher.RegisterSharedFunctionInfo(*job_id, *shared);
-
- base::Semaphore sem(0);
- V8::GetCurrentPlatform()->CallOnWorkerThread(
- base::make_unique<PressureNotificationTask>(i_isolate(), &dispatcher,
- &sem));
-
- sem.Wait();
-
- // A memory pressure task is pending, and running it will cancel the job.
- ASSERT_TRUE(platform.ForegroundTasksPending());
- ASSERT_TRUE(dispatcher.IsEnqueued(shared));
- platform.RunForegroundTasks();
- ASSERT_FALSE(dispatcher.IsEnqueued(shared));
ASSERT_FALSE(shared->is_compiled());
-
- // Since the AbortAll() call is made from a task, AbortAll thinks that there
- // is at least one task running, and fires of an AbortTask to be safe.
- ASSERT_TRUE(platform.ForegroundTasksPending());
- platform.RunForegroundTasks();
- ASSERT_FALSE(platform.ForegroundTasksPending());
-
- platform.ClearIdleTask();
- platform.ClearWorkerTasks();
+ ASSERT_FALSE(platform.IdleTaskPending());
+ ASSERT_FALSE(platform.WorkerTasksPending());
+ dispatcher.AbortAll();
}
TEST_F(CompilerDispatcherTest, CompileLazyFinishesDispatcherJob) {
@@ -972,16 +818,14 @@ TEST_F(CompilerDispatcherTest, CompileMultipleOnBackgroundThread) {
dispatcher.RegisterSharedFunctionInfo(*job_id_2, *shared_2);
ASSERT_EQ(dispatcher.jobs_.size(), 2u);
- ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
- dispatcher.jobs_.begin()->second->status());
- ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
- (++dispatcher.jobs_.begin())->second->status());
+ ASSERT_FALSE(dispatcher.jobs_.begin()->second->has_run);
+ ASSERT_FALSE((++dispatcher.jobs_.begin())->second->has_run);
ASSERT_TRUE(dispatcher.IsEnqueued(shared_1));
ASSERT_TRUE(dispatcher.IsEnqueued(shared_2));
ASSERT_FALSE(shared_1->is_compiled());
ASSERT_FALSE(shared_2->is_compiled());
- ASSERT_TRUE(platform.IdleTaskPending());
+ ASSERT_FALSE(platform.IdleTaskPending());
ASSERT_TRUE(platform.WorkerTasksPending());
platform.RunWorkerTasksAndBlock(V8::GetCurrentPlatform());
@@ -989,10 +833,8 @@ TEST_F(CompilerDispatcherTest, CompileMultipleOnBackgroundThread) {
ASSERT_TRUE(platform.IdleTaskPending());
ASSERT_FALSE(platform.WorkerTasksPending());
ASSERT_EQ(dispatcher.jobs_.size(), 2u);
- ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToFinalize,
- dispatcher.jobs_.begin()->second->status());
- ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToFinalize,
- (++dispatcher.jobs_.begin())->second->status());
+ ASSERT_TRUE(dispatcher.jobs_.begin()->second->has_run);
+ ASSERT_TRUE((++dispatcher.jobs_.begin())->second->has_run);
// Now grant a lot of idle time and freeze time.
platform.RunIdleTask(1000.0, 0.0);
@@ -1002,6 +844,7 @@ TEST_F(CompilerDispatcherTest, CompileMultipleOnBackgroundThread) {
ASSERT_TRUE(shared_1->is_compiled());
ASSERT_TRUE(shared_2->is_compiled());
ASSERT_FALSE(platform.IdleTaskPending());
+ dispatcher.AbortAll();
}
} // namespace internal