Index: src/compiler-dispatcher/compiler-dispatcher.cc |
diff --git a/src/compiler-dispatcher/compiler-dispatcher.cc b/src/compiler-dispatcher/compiler-dispatcher.cc |
index 47c04b8b44a39792173dd26443179bf137f9745e..5cf10aa3eb8ac012143c4f4b486d0e69c3bcfc1c 100644 |
--- a/src/compiler-dispatcher/compiler-dispatcher.cc |
+++ b/src/compiler-dispatcher/compiler-dispatcher.cc |
@@ -66,80 +66,29 @@ |
job->status() == CompileJobStatus::kFailed; |
} |
-bool CanRunOnAnyThread(CompilerDispatcherJob* job) { |
- return (job->status() == CompileJobStatus::kReadyToParse && |
- job->can_parse_on_background_thread()) || |
- (job->status() == CompileJobStatus::kReadyToCompile && |
- job->can_compile_on_background_thread()); |
-} |
- |
-void DoNextStepOnBackgroundThread(CompilerDispatcherJob* job) { |
- DCHECK(CanRunOnAnyThread(job)); |
- switch (job->status()) { |
- case CompileJobStatus::kReadyToParse: |
- job->Parse(); |
- break; |
- |
- case CompileJobStatus::kReadyToCompile: |
- job->Compile(); |
- break; |
- |
- default: |
- UNREACHABLE(); |
- } |
-} |
- |
// Theoretically we get 50ms of idle time max, however it's unlikely that |
// we'll get all of it so try to be a conservative. |
const double kMaxIdleTimeToExpectInMs = 40; |
} // namespace |
-class CompilerDispatcher::BackgroundTask : public CancelableTask { |
+class CompilerDispatcher::IdleTask : public CancelableIdleTask { |
public: |
- BackgroundTask(Isolate* isolate, CancelableTaskManager* task_manager, |
- CompilerDispatcher* dispatcher); |
- ~BackgroundTask() override; |
- |
- // CancelableTask implementation. |
- void RunInternal() override; |
+ IdleTask(Isolate* isolate, CompilerDispatcher* dispatcher); |
+ ~IdleTask() override; |
+ |
+ // CancelableIdleTask implementation. |
+ void RunInternal(double deadline_in_seconds) override; |
private: |
CompilerDispatcher* dispatcher_; |
- DISALLOW_COPY_AND_ASSIGN(BackgroundTask); |
-}; |
- |
-CompilerDispatcher::BackgroundTask::BackgroundTask( |
- Isolate* isolate, CancelableTaskManager* task_manager, |
- CompilerDispatcher* dispatcher) |
- : CancelableTask(isolate, task_manager), dispatcher_(dispatcher) {} |
- |
-CompilerDispatcher::BackgroundTask::~BackgroundTask() {} |
- |
-void CompilerDispatcher::BackgroundTask::RunInternal() { |
- dispatcher_->DoBackgroundWork(); |
-} |
- |
-class CompilerDispatcher::IdleTask : public CancelableIdleTask { |
- public: |
- IdleTask(Isolate* isolate, 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(Isolate* isolate, |
- CancelableTaskManager* task_manager, |
CompilerDispatcher* dispatcher) |
- : CancelableIdleTask(isolate, task_manager), dispatcher_(dispatcher) {} |
+ : CancelableIdleTask(isolate), dispatcher_(dispatcher) {} |
CompilerDispatcher::IdleTask::~IdleTask() {} |
@@ -153,15 +102,11 @@ |
platform_(platform), |
max_stack_size_(max_stack_size), |
tracer_(new CompilerDispatcherTracer(isolate_)), |
- task_manager_(new CancelableTaskManager()), |
- idle_task_scheduled_(false), |
- num_scheduled_background_tasks_(0), |
- main_thread_blocking_on_job_(nullptr) {} |
+ idle_task_scheduled_(false) {} |
CompilerDispatcher::~CompilerDispatcher() { |
// To avoid crashing in unit tests due to unfished jobs. |
AbortAll(BlockingBehavior::kBlock); |
- task_manager_->CancelAndWait(); |
} |
bool CompilerDispatcher::Enqueue(Handle<SharedFunctionInfo> function) { |
@@ -193,27 +138,12 @@ |
return GetJobFor(function) != jobs_.end(); |
} |
-void CompilerDispatcher::WaitForJobIfRunningOnBackground( |
- CompilerDispatcherJob* job) { |
- base::LockGuard<base::Mutex> lock(&mutex_); |
- if (running_background_jobs_.find(job) == running_background_jobs_.end()) { |
- pending_background_jobs_.erase(job); |
- return; |
- } |
- DCHECK_NULL(main_thread_blocking_on_job_); |
- main_thread_blocking_on_job_ = job; |
- while (main_thread_blocking_on_job_ != nullptr) { |
- main_thread_blocking_signal_.Wait(&mutex_); |
- } |
- DCHECK(pending_background_jobs_.find(job) == pending_background_jobs_.end()); |
- DCHECK(running_background_jobs_.find(job) == running_background_jobs_.end()); |
-} |
- |
bool CompilerDispatcher::FinishNow(Handle<SharedFunctionInfo> function) { |
JobMap::const_iterator job = GetJobFor(function); |
CHECK(job != jobs_.end()); |
- WaitForJobIfRunningOnBackground(job->second.get()); |
+ // TODO(jochen): Check if there's an in-flight background task working on this |
+ // job. |
while (!IsFinished(job->second.get())) { |
DoNextStepOnMainThread(isolate_, job->second.get(), |
ExceptionHandling::kThrow); |
@@ -224,11 +154,23 @@ |
return result; |
} |
+void CompilerDispatcher::Abort(Handle<SharedFunctionInfo> function, |
+ BlockingBehavior blocking) { |
+ USE(blocking); |
+ JobMap::const_iterator job = GetJobFor(function); |
+ CHECK(job != jobs_.end()); |
+ |
+ // TODO(jochen): Check if there's an in-flight background task working on this |
+ // job. |
+ job->second->ResetOnMainThread(); |
+ jobs_.erase(job); |
+} |
+ |
void CompilerDispatcher::AbortAll(BlockingBehavior blocking) { |
- // TODO(jochen): Implement support for non-blocking abort. |
- DCHECK(blocking == BlockingBehavior::kBlock); |
+ USE(blocking); |
+ // TODO(jochen): Check if there's an in-flight background task working on this |
+ // job. |
for (auto& kv : jobs_) { |
- WaitForJobIfRunningOnBackground(kv.second.get()); |
kv.second->ResetOnMainThread(); |
} |
jobs_.clear(); |
@@ -246,87 +188,18 @@ |
return jobs_.end(); |
} |
-void CompilerDispatcher::ScheduleIdleTaskFromAnyThread() { |
+void CompilerDispatcher::ScheduleIdleTaskIfNeeded() { |
v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_); |
DCHECK(platform_->IdleTasksEnabled(v8_isolate)); |
- { |
- base::LockGuard<base::Mutex> lock(&mutex_); |
- if (idle_task_scheduled_) return; |
- idle_task_scheduled_ = true; |
- } |
- platform_->CallIdleOnForegroundThread( |
- v8_isolate, new IdleTask(isolate_, task_manager_.get(), this)); |
-} |
- |
-void CompilerDispatcher::ScheduleIdleTaskIfNeeded() { |
+ if (idle_task_scheduled_) return; |
if (jobs_.empty()) return; |
- ScheduleIdleTaskFromAnyThread(); |
-} |
- |
-void CompilerDispatcher::ConsiderJobForBackgroundProcessing( |
- CompilerDispatcherJob* job) { |
- if (!CanRunOnAnyThread(job)) return; |
- { |
- base::LockGuard<base::Mutex> lock(&mutex_); |
- pending_background_jobs_.insert(job); |
- } |
- ScheduleMoreBackgroundTasksIfNeeded(); |
-} |
- |
-void CompilerDispatcher::ScheduleMoreBackgroundTasksIfNeeded() { |
- if (FLAG_single_threaded) return; |
- { |
- base::LockGuard<base::Mutex> lock(&mutex_); |
- if (pending_background_jobs_.empty()) return; |
- if (platform_->NumberOfAvailableBackgroundThreads() <= |
- num_scheduled_background_tasks_) { |
- return; |
- } |
- ++num_scheduled_background_tasks_; |
- } |
- platform_->CallOnBackgroundThread( |
- new BackgroundTask(isolate_, task_manager_.get(), this), |
- v8::Platform::kShortRunningTask); |
-} |
- |
-void CompilerDispatcher::DoBackgroundWork() { |
- CompilerDispatcherJob* job = nullptr; |
- { |
- base::LockGuard<base::Mutex> lock(&mutex_); |
- --num_scheduled_background_tasks_; |
- if (!pending_background_jobs_.empty()) { |
- auto it = pending_background_jobs_.begin(); |
- job = *it; |
- pending_background_jobs_.erase(it); |
- running_background_jobs_.insert(job); |
- } |
- } |
- if (job == nullptr) return; |
- DoNextStepOnBackgroundThread(job); |
- |
- ScheduleMoreBackgroundTasksIfNeeded(); |
- // Unconditionally schedule an idle task, as all background steps have to be |
- // followed by a main thread step. |
- ScheduleIdleTaskFromAnyThread(); |
- |
- { |
- base::LockGuard<base::Mutex> lock(&mutex_); |
- running_background_jobs_.erase(job); |
- |
- if (main_thread_blocking_on_job_ == job) { |
- main_thread_blocking_on_job_ = nullptr; |
- main_thread_blocking_signal_.NotifyOne(); |
- } |
- } |
- // Don't touch |this| anymore after this point, as it might have been |
- // deleted. |
+ idle_task_scheduled_ = true; |
+ platform_->CallIdleOnForegroundThread(v8_isolate, |
+ new IdleTask(isolate_, this)); |
} |
void CompilerDispatcher::DoIdleWork(double deadline_in_seconds) { |
- { |
- base::LockGuard<base::Mutex> lock(&mutex_); |
- idle_task_scheduled_ = false; |
- } |
+ idle_task_scheduled_ = false; |
// Number of jobs that are unlikely to make progress during any idle callback |
// due to their estimated duration. |
@@ -341,17 +214,6 @@ |
job != jobs_.end() && idle_time_in_seconds > 0.0; |
idle_time_in_seconds = |
deadline_in_seconds - platform_->MonotonicallyIncreasingTime()) { |
- // Don't work on jobs that are being worked on by background tasks. |
- // Similarly, remove jobs we work on from the set of available background |
- // jobs. |
- std::unique_ptr<base::LockGuard<base::Mutex>> lock( |
- new base::LockGuard<base::Mutex>(&mutex_)); |
- if (running_background_jobs_.find(job->second.get()) != |
- running_background_jobs_.end()) { |
- ++job; |
- continue; |
- } |
- auto it = pending_background_jobs_.find(job->second.get()); |
double estimate_in_ms = job->second->EstimateRuntimeOfNextStepInMs(); |
if (idle_time_in_seconds < |
(estimate_in_ms / |
@@ -360,23 +222,14 @@ |
// have managed to finish the job in a large idle task to assess |
// whether we should ask for another idle callback. |
if (estimate_in_ms > kMaxIdleTimeToExpectInMs) ++too_long_jobs; |
- if (it == pending_background_jobs_.end()) { |
- lock.reset(); |
- ConsiderJobForBackgroundProcessing(job->second.get()); |
- } |
++job; |
} else if (IsFinished(job->second.get())) { |
- DCHECK(it == pending_background_jobs_.end()); |
job->second->ResetOnMainThread(); |
job = jobs_.erase(job); |
- continue; |
+ break; |
} else { |
// Do one step, and keep processing the job (as we don't advance the |
// iterator). |
- if (it != pending_background_jobs_.end()) { |
- pending_background_jobs_.erase(it); |
- } |
- lock.reset(); |
DoNextStepOnMainThread(isolate_, job->second.get(), |
ExceptionHandling::kSwallow); |
} |