Commit ff3b948c authored by Leszek Swirski's avatar Leszek Swirski Committed by Commit Bot

[compiler-dispatcher] Move stepping logic to job

Instead of having the "next step" state machine logic in the compiler
dispatcher, move it to the compiler dispatcher job. This is a
prerequisite to having more generic jobs with slightly different state
sets, such as an optimizing compile job.

Bug: v8:6537
Change-Id: Ib7319222f26dbc0e2afc95573b06d813825afde3
Reviewed-on: https://chromium-review.googlesource.com/554751
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#46396}
parent aa5852a2
...@@ -179,6 +179,50 @@ bool CompilerDispatcherJob::IsAssociatedWith( ...@@ -179,6 +179,50 @@ bool CompilerDispatcherJob::IsAssociatedWith(
return *shared_ == *shared; return *shared_ == *shared;
} }
void CompilerDispatcherJob::StepNextOnMainThread() {
switch (status()) {
case CompileJobStatus::kInitial:
return PrepareToParseOnMainThread();
case CompileJobStatus::kReadyToParse:
return Parse();
case CompileJobStatus::kParsed:
return FinalizeParsingOnMainThread();
case CompileJobStatus::kReadyToAnalyze:
return AnalyzeOnMainThread();
case CompileJobStatus::kAnalyzed:
return PrepareToCompileOnMainThread();
case CompileJobStatus::kReadyToCompile:
return Compile();
case CompileJobStatus::kCompiled:
return FinalizeCompilingOnMainThread();
case CompileJobStatus::kFailed:
case CompileJobStatus::kDone:
return;
}
UNREACHABLE();
}
void CompilerDispatcherJob::StepNextOnBackgroundThread() {
DCHECK(CanStepNextOnAnyThread());
switch (status()) {
case CompileJobStatus::kReadyToParse:
return Parse();
case CompileJobStatus::kReadyToCompile:
return Compile();
default:
UNREACHABLE();
}
}
void CompilerDispatcherJob::PrepareToParseOnMainThread() { void CompilerDispatcherJob::PrepareToParseOnMainThread() {
DCHECK(ThreadId::Current().Equals(isolate_->thread_id())); DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
DCHECK(status() == CompileJobStatus::kInitial); DCHECK(status() == CompileJobStatus::kInitial);
...@@ -315,7 +359,7 @@ void CompilerDispatcherJob::Parse() { ...@@ -315,7 +359,7 @@ void CompilerDispatcherJob::Parse() {
} }
} }
bool CompilerDispatcherJob::FinalizeParsingOnMainThread() { void CompilerDispatcherJob::FinalizeParsingOnMainThread() {
DCHECK(ThreadId::Current().Equals(isolate_->thread_id())); DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
DCHECK(status() == CompileJobStatus::kParsed); DCHECK(status() == CompileJobStatus::kParsed);
COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kFinalizeParsing); COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kFinalizeParsing);
...@@ -367,11 +411,9 @@ bool CompilerDispatcherJob::FinalizeParsingOnMainThread() { ...@@ -367,11 +411,9 @@ bool CompilerDispatcherJob::FinalizeParsingOnMainThread() {
character_stream_.reset(); character_stream_.reset();
} }
parse_info_->set_deferred_handles(scope.Detach()); parse_info_->set_deferred_handles(scope.Detach());
return status_ != CompileJobStatus::kFailed;
} }
bool CompilerDispatcherJob::AnalyzeOnMainThread() { void CompilerDispatcherJob::AnalyzeOnMainThread() {
DCHECK(ThreadId::Current().Equals(isolate_->thread_id())); DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
DCHECK(status() == CompileJobStatus::kReadyToAnalyze); DCHECK(status() == CompileJobStatus::kReadyToAnalyze);
COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kAnalyze); COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kAnalyze);
...@@ -393,11 +435,9 @@ bool CompilerDispatcherJob::AnalyzeOnMainThread() { ...@@ -393,11 +435,9 @@ bool CompilerDispatcherJob::AnalyzeOnMainThread() {
} }
} }
compile_info_->set_deferred_handles(scope.Detach()); compile_info_->set_deferred_handles(scope.Detach());
return status_ != CompileJobStatus::kFailed;
} }
bool CompilerDispatcherJob::PrepareToCompileOnMainThread() { void CompilerDispatcherJob::PrepareToCompileOnMainThread() {
DCHECK(ThreadId::Current().Equals(isolate_->thread_id())); DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
DCHECK(status() == CompileJobStatus::kAnalyzed); DCHECK(status() == CompileJobStatus::kAnalyzed);
COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kPrepareToCompile); COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kPrepareToCompile);
...@@ -407,12 +447,11 @@ bool CompilerDispatcherJob::PrepareToCompileOnMainThread() { ...@@ -407,12 +447,11 @@ bool CompilerDispatcherJob::PrepareToCompileOnMainThread() {
if (!compile_job_.get()) { if (!compile_job_.get()) {
if (!isolate_->has_pending_exception()) isolate_->StackOverflow(); if (!isolate_->has_pending_exception()) isolate_->StackOverflow();
status_ = CompileJobStatus::kFailed; status_ = CompileJobStatus::kFailed;
return false; return;
} }
CHECK(compile_job_->can_execute_on_background_thread()); CHECK(compile_job_->can_execute_on_background_thread());
status_ = CompileJobStatus::kReadyToCompile; status_ = CompileJobStatus::kReadyToCompile;
return true;
} }
void CompilerDispatcherJob::Compile() { void CompilerDispatcherJob::Compile() {
...@@ -437,7 +476,7 @@ void CompilerDispatcherJob::Compile() { ...@@ -437,7 +476,7 @@ void CompilerDispatcherJob::Compile() {
status_ = CompileJobStatus::kCompiled; status_ = CompileJobStatus::kCompiled;
} }
bool CompilerDispatcherJob::FinalizeCompilingOnMainThread() { void CompilerDispatcherJob::FinalizeCompilingOnMainThread() {
DCHECK(ThreadId::Current().Equals(isolate_->thread_id())); DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
DCHECK(status() == CompileJobStatus::kCompiled); DCHECK(status() == CompileJobStatus::kCompiled);
COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kFinalizeCompiling); COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kFinalizeCompiling);
...@@ -452,7 +491,7 @@ bool CompilerDispatcherJob::FinalizeCompilingOnMainThread() { ...@@ -452,7 +491,7 @@ bool CompilerDispatcherJob::FinalizeCompilingOnMainThread() {
!Compiler::FinalizeCompilationJob(compile_job_.release())) { !Compiler::FinalizeCompilationJob(compile_job_.release())) {
if (!isolate_->has_pending_exception()) isolate_->StackOverflow(); if (!isolate_->has_pending_exception()) isolate_->StackOverflow();
status_ = CompileJobStatus::kFailed; status_ = CompileJobStatus::kFailed;
return false; return;
} }
} }
...@@ -462,7 +501,6 @@ bool CompilerDispatcherJob::FinalizeCompilingOnMainThread() { ...@@ -462,7 +501,6 @@ bool CompilerDispatcherJob::FinalizeCompilingOnMainThread() {
parse_info_.reset(); parse_info_.reset();
status_ = CompileJobStatus::kDone; status_ = CompileJobStatus::kDone;
return true;
} }
void CompilerDispatcherJob::ResetOnMainThread() { void CompilerDispatcherJob::ResetOnMainThread() {
......
...@@ -76,8 +76,6 @@ class V8_EXPORT_PRIVATE CompilerDispatcherJob { ...@@ -76,8 +76,6 @@ class V8_EXPORT_PRIVATE CompilerDispatcherJob {
size_t max_stack_size); size_t max_stack_size);
~CompilerDispatcherJob(); ~CompilerDispatcherJob();
CompileJobStatus status() const { return status_; }
bool has_context() const { return !context_.is_null(); } bool has_context() const { return !context_.is_null(); }
Context* context() { return *context_; } Context* context() { return *context_; }
...@@ -87,31 +85,26 @@ class V8_EXPORT_PRIVATE CompilerDispatcherJob { ...@@ -87,31 +85,26 @@ class V8_EXPORT_PRIVATE CompilerDispatcherJob {
// function. // function.
bool IsAssociatedWith(Handle<SharedFunctionInfo> shared) const; bool IsAssociatedWith(Handle<SharedFunctionInfo> shared) const;
// Transition from kInitial to kReadyToParse. bool IsFinished() {
void PrepareToParseOnMainThread(); return status() == CompileJobStatus::kDone ||
status() == CompileJobStatus::kFailed;
// Transition from kReadyToParse to kParsed (or kDone if there is }
// finish_callback).
void Parse();
// Transition from kParsed to kReadyToAnalyze (or kFailed). Returns false
// when transitioning to kFailed. In that case, an exception is pending.
bool FinalizeParsingOnMainThread();
// Transition from kReadyToAnalyze to kAnalyzed (or kFailed). Returns bool IsFailed() { return status() == CompileJobStatus::kFailed; }
// false when transitioning to kFailed. In that case, an exception is pending.
bool AnalyzeOnMainThread();
// Transition from kAnalyzed to kReadyToCompile (or kFailed). Returns // Return true if the next step can be run on any thread, that is when both
// false when transitioning to kFailed. In that case, an exception is pending. // StepNextOnMainThread and StepNextOnBackgroundThread could be used for the
bool PrepareToCompileOnMainThread(); // next step.
bool CanStepNextOnAnyThread() {
return status() == CompileJobStatus::kReadyToParse ||
status() == CompileJobStatus::kReadyToCompile;
}
// Transition from kReadyToCompile to kCompiled. // Step the job forward by one state on the main thread.
void Compile(); void StepNextOnMainThread();
// Transition from kCompiled to kDone (or kFailed). Returns false when // Step the job forward by one state on a background thread.
// transitioning to kFailed. In that case, an exception is pending. void StepNextOnBackgroundThread();
bool FinalizeCompilingOnMainThread();
// Transition from any state to kInitial and free all resources. // Transition from any state to kInitial and free all resources.
void ResetOnMainThread(); void ResetOnMainThread();
...@@ -124,7 +117,10 @@ class V8_EXPORT_PRIVATE CompilerDispatcherJob { ...@@ -124,7 +117,10 @@ class V8_EXPORT_PRIVATE CompilerDispatcherJob {
void ShortPrint(); void ShortPrint();
private: private:
FRIEND_TEST(CompilerDispatcherJobTest, ScopeChain); friend class CompilerDispatcherTest;
friend class CompilerDispatcherJobTest;
CompileJobStatus status() const { return status_; }
CompileJobStatus status_; CompileJobStatus status_;
Isolate* isolate_; Isolate* isolate_;
...@@ -152,6 +148,28 @@ class V8_EXPORT_PRIVATE CompilerDispatcherJob { ...@@ -152,6 +148,28 @@ class V8_EXPORT_PRIVATE CompilerDispatcherJob {
bool trace_compiler_dispatcher_jobs_; bool trace_compiler_dispatcher_jobs_;
// Transition from kInitial to kReadyToParse.
void PrepareToParseOnMainThread();
// Transition from kReadyToParse to kParsed (or kDone if there is
// finish_callback).
void Parse();
// Transition from kParsed to kReadyToAnalyze (or kFailed).
void FinalizeParsingOnMainThread();
// Transition from kReadyToAnalyze to kAnalyzed (or kFailed).
void AnalyzeOnMainThread();
// Transition from kAnalyzed to kReadyToCompile (or kFailed).
void PrepareToCompileOnMainThread();
// Transition from kReadyToCompile to kCompiled.
void Compile();
// Transition from kCompiled to kDone (or kFailed).
void FinalizeCompilingOnMainThread();
DISALLOW_COPY_AND_ASSIGN(CompilerDispatcherJob); DISALLOW_COPY_AND_ASSIGN(CompilerDispatcherJob);
}; };
......
...@@ -21,16 +21,6 @@ namespace { ...@@ -21,16 +21,6 @@ namespace {
enum class ExceptionHandling { kSwallow, kThrow }; enum class ExceptionHandling { kSwallow, kThrow };
bool IsFinished(CompilerDispatcherJob* job) {
return job->status() == CompileJobStatus::kDone ||
job->status() == CompileJobStatus::kFailed;
}
bool CanRunOnAnyThread(CompilerDispatcherJob* job) {
return job->status() == CompileJobStatus::kReadyToParse ||
job->status() == CompileJobStatus::kReadyToCompile;
}
bool DoNextStepOnMainThread(Isolate* isolate, CompilerDispatcherJob* job, bool DoNextStepOnMainThread(Isolate* isolate, CompilerDispatcherJob* job,
ExceptionHandling exception_handling) { ExceptionHandling exception_handling) {
DCHECK(ThreadId::Current().Equals(isolate->thread_id())); DCHECK(ThreadId::Current().Equals(isolate->thread_id()));
...@@ -42,69 +32,23 @@ bool DoNextStepOnMainThread(Isolate* isolate, CompilerDispatcherJob* job, ...@@ -42,69 +32,23 @@ bool DoNextStepOnMainThread(Isolate* isolate, CompilerDispatcherJob* job,
if (job->has_context()) { if (job->has_context()) {
isolate->set_context(job->context()); isolate->set_context(job->context());
} else { } else {
DCHECK(CanRunOnAnyThread(job)); DCHECK(job->CanStepNextOnAnyThread());
} }
switch (job->status()) { job->StepNextOnMainThread();
case CompileJobStatus::kInitial:
job->PrepareToParseOnMainThread();
break;
case CompileJobStatus::kReadyToParse:
job->Parse();
break;
case CompileJobStatus::kParsed:
job->FinalizeParsingOnMainThread();
break;
case CompileJobStatus::kReadyToAnalyze:
job->AnalyzeOnMainThread();
break;
case CompileJobStatus::kAnalyzed:
job->PrepareToCompileOnMainThread();
break;
case CompileJobStatus::kReadyToCompile: DCHECK_EQ(job->IsFailed(), isolate->has_pending_exception());
job->Compile(); if (job->IsFailed() && exception_handling == ExceptionHandling::kSwallow) {
break;
case CompileJobStatus::kCompiled:
job->FinalizeCompilingOnMainThread();
break;
case CompileJobStatus::kFailed:
case CompileJobStatus::kDone:
break;
}
DCHECK_EQ(job->status() == CompileJobStatus::kFailed,
isolate->has_pending_exception());
if (job->status() == CompileJobStatus::kFailed &&
exception_handling == ExceptionHandling::kSwallow) {
isolate->clear_pending_exception(); isolate->clear_pending_exception();
} }
return job->status() != CompileJobStatus::kFailed; return job->IsFailed();
} }
void DoNextStepOnBackgroundThread(CompilerDispatcherJob* job) { void DoNextStepOnBackgroundThread(CompilerDispatcherJob* job) {
DCHECK(CanRunOnAnyThread(job)); DCHECK(job->CanStepNextOnAnyThread());
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.CompilerDispatcherBackgroundStep"); "V8.CompilerDispatcherBackgroundStep");
job->StepNextOnBackgroundThread();
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 // Theoretically we get 50ms of idle time max, however it's unlikely that
...@@ -277,7 +221,7 @@ bool CompilerDispatcher::CanEnqueue(Handle<SharedFunctionInfo> function) { ...@@ -277,7 +221,7 @@ bool CompilerDispatcher::CanEnqueue(Handle<SharedFunctionInfo> function) {
CompilerDispatcher::JobId CompilerDispatcher::Enqueue( CompilerDispatcher::JobId CompilerDispatcher::Enqueue(
std::unique_ptr<CompilerDispatcherJob> job) { std::unique_ptr<CompilerDispatcherJob> job) {
DCHECK(!IsFinished(job.get())); DCHECK(!job->IsFinished());
bool added; bool added;
JobMap::const_iterator it; JobMap::const_iterator it;
std::tie(it, added) = std::tie(it, added) =
...@@ -293,7 +237,7 @@ CompilerDispatcher::JobId CompilerDispatcher::Enqueue( ...@@ -293,7 +237,7 @@ CompilerDispatcher::JobId CompilerDispatcher::Enqueue(
CompilerDispatcher::JobId CompilerDispatcher::EnqueueAndStep( CompilerDispatcher::JobId CompilerDispatcher::EnqueueAndStep(
std::unique_ptr<CompilerDispatcherJob> job) { std::unique_ptr<CompilerDispatcherJob> job) {
DCHECK(!IsFinished(job.get())); DCHECK(!job->IsFinished());
bool added; bool added;
JobMap::const_iterator it; JobMap::const_iterator it;
std::tie(it, added) = std::tie(it, added) =
...@@ -461,10 +405,10 @@ bool CompilerDispatcher::FinishNow(CompilerDispatcherJob* job) { ...@@ -461,10 +405,10 @@ bool CompilerDispatcher::FinishNow(CompilerDispatcherJob* job) {
PrintF(" now\n"); PrintF(" now\n");
} }
WaitForJobIfRunningOnBackground(job); WaitForJobIfRunningOnBackground(job);
while (!IsFinished(job)) { while (!job->IsFinished()) {
DoNextStepOnMainThread(isolate_, job, ExceptionHandling::kThrow); DoNextStepOnMainThread(isolate_, job, ExceptionHandling::kThrow);
} }
return job->status() != CompileJobStatus::kFailed; return !job->IsFailed();
} }
bool CompilerDispatcher::FinishNow(Handle<SharedFunctionInfo> function) { bool CompilerDispatcher::FinishNow(Handle<SharedFunctionInfo> function) {
...@@ -489,7 +433,7 @@ void CompilerDispatcher::FinishAllNow() { ...@@ -489,7 +433,7 @@ void CompilerDispatcher::FinishAllNow() {
pending_background_jobs_.erase(job); pending_background_jobs_.erase(job);
} }
if (!is_running_in_background) { if (!is_running_in_background) {
while (!IsFinished(job)) { while (!job->IsFinished()) {
DoNextStepOnMainThread(isolate_, job, ExceptionHandling::kThrow); DoNextStepOnMainThread(isolate_, job, ExceptionHandling::kThrow);
} }
it = RemoveIfFinished(it); it = RemoveIfFinished(it);
...@@ -638,7 +582,7 @@ void CompilerDispatcher::ScheduleAbortTask() { ...@@ -638,7 +582,7 @@ void CompilerDispatcher::ScheduleAbortTask() {
void CompilerDispatcher::ConsiderJobForBackgroundProcessing( void CompilerDispatcher::ConsiderJobForBackgroundProcessing(
CompilerDispatcherJob* job) { CompilerDispatcherJob* job) {
if (!CanRunOnAnyThread(job)) return; if (!job->CanStepNextOnAnyThread()) return;
{ {
base::LockGuard<base::Mutex> lock(&mutex_); base::LockGuard<base::Mutex> lock(&mutex_);
pending_background_jobs_.insert(job); pending_background_jobs_.insert(job);
...@@ -773,7 +717,7 @@ void CompilerDispatcher::DoIdleWork(double deadline_in_seconds) { ...@@ -773,7 +717,7 @@ void CompilerDispatcher::DoIdleWork(double deadline_in_seconds) {
ConsiderJobForBackgroundProcessing(job->second.get()); ConsiderJobForBackgroundProcessing(job->second.get());
} }
++job; ++job;
} else if (IsFinished(job->second.get())) { } else if (job->second->IsFinished()) {
DCHECK(it == pending_background_jobs_.end()); DCHECK(it == pending_background_jobs_.end());
lock.reset(); lock.reset();
job = RemoveJob(job); job = RemoveJob(job);
...@@ -794,12 +738,12 @@ void CompilerDispatcher::DoIdleWork(double deadline_in_seconds) { ...@@ -794,12 +738,12 @@ void CompilerDispatcher::DoIdleWork(double deadline_in_seconds) {
CompilerDispatcher::JobMap::const_iterator CompilerDispatcher::RemoveIfFinished( CompilerDispatcher::JobMap::const_iterator CompilerDispatcher::RemoveIfFinished(
JobMap::const_iterator job) { JobMap::const_iterator job) {
if (!IsFinished(job->second.get())) { if (!job->second->IsFinished()) {
return job; return job;
} }
if (trace_compiler_dispatcher_) { if (trace_compiler_dispatcher_) {
bool result = job->second->status() != CompileJobStatus::kFailed; bool result = !job->second->IsFailed();
PrintF("CompilerDispatcher: finished working on "); PrintF("CompilerDispatcher: finished working on ");
job->second->ShortPrint(); job->second->ShortPrint();
PrintF(": %s\n", result ? "success" : "failure"); PrintF(": %s\n", result ? "success" : "failure");
......
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