Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(668)

Unified Diff: src/compiler-dispatcher/compiler-dispatcher.cc

Issue 2615603002: Implement async AbortAll for the compiler dispatcher (Closed)
Patch Set: updates Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/compiler-dispatcher/compiler-dispatcher.h ('k') | test/unittests/cancelable-tasks-unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler-dispatcher/compiler-dispatcher.cc
diff --git a/src/compiler-dispatcher/compiler-dispatcher.cc b/src/compiler-dispatcher/compiler-dispatcher.cc
index 782a6ed855ea78a03f7e9829ef6f33b966e515fa..ba5154e0112591bae737245c87cf08e756c65a39 100644
--- a/src/compiler-dispatcher/compiler-dispatcher.cc
+++ b/src/compiler-dispatcher/compiler-dispatcher.cc
@@ -52,13 +52,11 @@ bool DoNextStepOnMainThread(Isolate* isolate, CompilerDispatcherJob* job,
break;
}
- if (job->status() == CompileJobStatus::kFailed) {
- DCHECK(isolate->has_pending_exception());
- if (exception_handling == ExceptionHandling::kSwallow) {
- isolate->clear_pending_exception();
- }
- } else {
- DCHECK(!isolate->has_pending_exception());
+ DCHECK_EQ(job->status() == CompileJobStatus::kFailed,
+ isolate->has_pending_exception());
+ if (job->status() == CompileJobStatus::kFailed &&
+ exception_handling == ExceptionHandling::kSwallow) {
+ isolate->clear_pending_exception();
}
return job->status() != CompileJobStatus::kFailed;
}
@@ -97,6 +95,32 @@ const double kMaxIdleTimeToExpectInMs = 40;
} // namespace
+class CompilerDispatcher::AbortTask : public CancelableTask {
+ public:
+ AbortTask(Isolate* isolate, CancelableTaskManager* task_manager,
+ CompilerDispatcher* dispatcher);
+ ~AbortTask() override;
+
+ // CancelableTask implementation.
+ void RunInternal() override;
+
+ private:
+ CompilerDispatcher* dispatcher_;
+
+ DISALLOW_COPY_AND_ASSIGN(AbortTask);
+};
+
+CompilerDispatcher::AbortTask::AbortTask(Isolate* isolate,
+ CancelableTaskManager* task_manager,
+ CompilerDispatcher* dispatcher)
+ : CancelableTask(isolate, task_manager), dispatcher_(dispatcher) {}
+
+CompilerDispatcher::AbortTask::~AbortTask() {}
+
+void CompilerDispatcher::AbortTask::RunInternal() {
+ dispatcher_->AbortInactiveJobs();
+}
+
class CompilerDispatcher::BackgroundTask : public CancelableTask {
public:
BackgroundTask(Isolate* isolate, CancelableTaskManager* task_manager,
@@ -156,9 +180,12 @@ CompilerDispatcher::CompilerDispatcher(Isolate* isolate, Platform* platform,
max_stack_size_(max_stack_size),
tracer_(new CompilerDispatcherTracer(isolate_)),
task_manager_(new CancelableTaskManager()),
+ abort_(false),
idle_task_scheduled_(false),
num_scheduled_background_tasks_(0),
- main_thread_blocking_on_job_(nullptr) {}
+ main_thread_blocking_on_job_(nullptr),
+ block_for_testing_(false),
+ semaphore_for_testing_(0) {}
CompilerDispatcher::~CompilerDispatcher() {
// To avoid crashing in unit tests due to unfished jobs.
@@ -169,6 +196,11 @@ CompilerDispatcher::~CompilerDispatcher() {
bool CompilerDispatcher::Enqueue(Handle<SharedFunctionInfo> function) {
if (!IsEnabled()) return false;
+ {
+ base::LockGuard<base::Mutex> lock(&mutex_);
+ if (abort_) return false;
+ }
+
// We only handle functions (no eval / top-level code / wasm) that are
// attached to a script.
if (!function->script()->IsScript() || !function->is_function() ||
@@ -223,17 +255,68 @@ bool CompilerDispatcher::FinishNow(Handle<SharedFunctionInfo> function) {
bool result = job->second->status() != CompileJobStatus::kFailed;
job->second->ResetOnMainThread();
jobs_.erase(job);
+ if (jobs_.empty()) {
+ base::LockGuard<base::Mutex> lock(&mutex_);
+ abort_ = false;
+ }
return result;
}
void CompilerDispatcher::AbortAll(BlockingBehavior blocking) {
- // TODO(jochen): Implement support for non-blocking abort.
- DCHECK(blocking == BlockingBehavior::kBlock);
- for (auto& kv : jobs_) {
- WaitForJobIfRunningOnBackground(kv.second.get());
- kv.second->ResetOnMainThread();
+ bool background_tasks_running =
+ task_manager_->TryAbortAll() == CancelableTaskManager::kTaskRunning;
+ if (!background_tasks_running || blocking == BlockingBehavior::kBlock) {
+ for (auto& it : jobs_) {
+ WaitForJobIfRunningOnBackground(it.second.get());
+ it.second->ResetOnMainThread();
+ }
+ jobs_.clear();
+ {
+ base::LockGuard<base::Mutex> lock(&mutex_);
+ DCHECK(pending_background_jobs_.empty());
+ DCHECK(running_background_jobs_.empty());
+ abort_ = false;
+ }
+ return;
+ }
+
+ {
+ base::LockGuard<base::Mutex> lock(&mutex_);
+ abort_ = true;
+ pending_background_jobs_.clear();
+ }
+ AbortInactiveJobs();
+
+ // All running background jobs might already have scheduled idle tasks instead
+ // of abort tasks. Schedule a single abort task here to make sure they get
+ // processed as soon as possible (and not first when we have idle time).
+ ScheduleAbortTask();
+}
+
+void CompilerDispatcher::AbortInactiveJobs() {
+ {
+ base::LockGuard<base::Mutex> lock(&mutex_);
+ // Since we schedule two abort tasks per async abort, we might end up
+ // here with nothing left to do.
+ if (!abort_) return;
+ }
+ for (auto it = jobs_.begin(); it != jobs_.end();) {
+ auto job = it;
+ ++it;
+ {
+ base::LockGuard<base::Mutex> lock(&mutex_);
+ if (running_background_jobs_.find(job->second.get()) !=
+ running_background_jobs_.end()) {
+ continue;
+ }
+ }
+ job->second->ResetOnMainThread();
+ jobs_.erase(job);
+ }
+ if (jobs_.empty()) {
+ base::LockGuard<base::Mutex> lock(&mutex_);
+ abort_ = false;
}
- jobs_.clear();
}
CompilerDispatcher::JobMap::const_iterator CompilerDispatcher::GetJobFor(
@@ -265,6 +348,12 @@ void CompilerDispatcher::ScheduleIdleTaskIfNeeded() {
ScheduleIdleTaskFromAnyThread();
}
+void CompilerDispatcher::ScheduleAbortTask() {
+ v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_);
+ platform_->CallOnForegroundThread(
+ v8_isolate, new AbortTask(isolate_, task_manager_.get(), this));
+}
+
void CompilerDispatcher::ConsiderJobForBackgroundProcessing(
CompilerDispatcherJob* job) {
if (!CanRunOnAnyThread(job)) return;
@@ -304,6 +393,12 @@ void CompilerDispatcher::DoBackgroundWork() {
}
}
if (job == nullptr) return;
+
+ if (V8_UNLIKELY(block_for_testing_.Value())) {
+ block_for_testing_.SetValue(false);
+ semaphore_for_testing_.Wait();
+ }
+
DoNextStepOnBackgroundThread(job);
ScheduleMoreBackgroundTasksIfNeeded();
@@ -315,6 +410,13 @@ void CompilerDispatcher::DoBackgroundWork() {
base::LockGuard<base::Mutex> lock(&mutex_);
running_background_jobs_.erase(job);
+ if (running_background_jobs_.empty() && abort_) {
+ // This is the last background job that finished. The abort task
+ // scheduled by AbortAll might already have ran, so schedule another
+ // one to be on the safe side.
+ ScheduleAbortTask();
+ }
+
if (main_thread_blocking_on_job_ == job) {
main_thread_blocking_on_job_ = nullptr;
main_thread_blocking_signal_.NotifyOne();
@@ -325,9 +427,16 @@ void CompilerDispatcher::DoBackgroundWork() {
}
void CompilerDispatcher::DoIdleWork(double deadline_in_seconds) {
+ bool aborted = false;
{
base::LockGuard<base::Mutex> lock(&mutex_);
idle_task_scheduled_ = false;
+ aborted = abort_;
+ }
+
+ if (aborted) {
+ AbortInactiveJobs();
+ return;
}
// Number of jobs that are unlikely to make progress during any idle callback
« no previous file with comments | « src/compiler-dispatcher/compiler-dispatcher.h ('k') | test/unittests/cancelable-tasks-unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698