Commit 72575d3c authored by Ross McIlroy's avatar Ross McIlroy Committed by Commit Bot

[Compile] Move stepping logic from compilation job to compiler dispatcher.

Now that UnoptimizedCompileJob only has three stages, move the logic for
stepping between these stages out of UnoptimizedCompileJob and back into
CompilerDispatcher.

BUG=v8:5203

Change-Id: I3bb776e14ef9da801dc9792e9e643b8026135060
Reviewed-on: https://chromium-review.googlesource.com/774743Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Commit-Queue: Ross McIlroy <rmcilroy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49422}
parent 024414d4
......@@ -11,7 +11,7 @@ namespace internal {
const UnoptimizedCompileJob* CompilerDispatcherJob::AsUnoptimizedCompileJob()
const {
DCHECK_EQ(type(), kUnoptimizedCompile);
DCHECK_EQ(type(), Type::kUnoptimizedCompile);
return static_cast<const UnoptimizedCompileJob*>(this);
}
......
......@@ -17,42 +17,73 @@ class UnoptimizedCompileJob;
class V8_EXPORT_PRIVATE CompilerDispatcherJob {
public:
enum Type { kUnoptimizedCompile };
enum class Type { kUnoptimizedCompile };
enum class Status {
kInitial,
kPrepared,
kCompiled,
kHasErrorsToReport,
kDone,
kFailed,
};
CompilerDispatcherJob(Type type) : type_(type), status_(Status::kInitial) {}
virtual ~CompilerDispatcherJob() {}
virtual Type type() const = 0;
Type type() const { return type_; }
// Returns the current status of the compile
Status status() const { return status_; }
// Returns true if this CompilerDispatcherJob has finished (either with a
// success or a failure).
virtual bool IsFinished() = 0;
bool IsFinished() const {
return status() == Status::kDone || status() == Status::kFailed;
}
// Returns true if this CompilerDispatcherJob has failed.
virtual bool IsFailed() = 0;
bool IsFailed() const { return status() == Status::kFailed; }
// Return true if the next step can be run on any thread, that is when both
// StepNextOnMainThread and StepNextOnBackgroundThread could be used for the
// next step.
virtual bool CanStepNextOnAnyThread() = 0;
// Return true if the next step can be run on any thread.
bool NextStepCanRunOnAnyThread() const {
return status() == Status::kPrepared;
}
// Casts to implementations.
const UnoptimizedCompileJob* AsUnoptimizedCompileJob() const;
// Step the job forward by one state on the main thread.
virtual void StepNextOnMainThread(Isolate* isolate) = 0;
// Transition from kInitial to kPrepared. Must only be invoked on the
// main thread.
virtual void PrepareOnMainThread(Isolate* isolate) = 0;
// Step the job forward by one state on a background thread.
virtual void StepNextOnBackgroundThread() = 0;
// Transition from kPrepared to kCompiled (or kReportErrors).
virtual void Compile(bool on_background_thread) = 0;
// Transition from any state to kInitial and free all resources.
// Transition from kCompiled to kDone (or kFailed). Must only be invoked on
// the main thread.
virtual void FinalizeOnMainThread(Isolate* isolate) = 0;
// Transition from kReportErrors to kFailed. Must only be invoked on the main
// thread.
virtual void ReportErrorsOnMainThread(Isolate* isolate) = 0;
// Free all resources. Must only be invoked on the main thread.
virtual void ResetOnMainThread(Isolate* isolate) = 0;
// Estimate how long the next step will take using the tracer.
virtual double EstimateRuntimeOfNextStepInMs() const = 0;
// Even though the name does not imply this, ShortPrint() must only be invoked
// on the main thread.
// Print short description of job. Must only be invoked on the main thread.
virtual void ShortPrintOnMainThread() = 0;
// Casts to implementations.
const UnoptimizedCompileJob* AsUnoptimizedCompileJob() const;
protected:
void set_status(Status status) { status_ = status; }
private:
Type type_;
Status status_;
};
} // namespace internal
......
......@@ -27,7 +27,23 @@ bool DoNextStepOnMainThread(Isolate* isolate, CompilerDispatcherJob* job,
DCHECK(ThreadId::Current().Equals(isolate->thread_id()));
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.CompilerDispatcherForgroundStep");
job->StepNextOnMainThread(isolate);
switch (job->status()) {
case CompilerDispatcherJob::Status::kInitial:
job->PrepareOnMainThread(isolate);
break;
case CompilerDispatcherJob::Status::kPrepared:
job->Compile(false);
break;
case CompilerDispatcherJob::Status::kCompiled:
job->FinalizeOnMainThread(isolate);
break;
case CompilerDispatcherJob::Status::kHasErrorsToReport:
job->ReportErrorsOnMainThread(isolate);
break;
case CompilerDispatcherJob::Status::kFailed:
case CompilerDispatcherJob::Status::kDone:
UNREACHABLE();
}
DCHECK_EQ(job->IsFailed(), isolate->has_pending_exception());
if (job->IsFailed() && exception_handling == ExceptionHandling::kSwallow) {
......@@ -37,10 +53,16 @@ bool DoNextStepOnMainThread(Isolate* isolate, CompilerDispatcherJob* job,
}
void DoNextStepOnBackgroundThread(CompilerDispatcherJob* job) {
DCHECK(job->CanStepNextOnAnyThread());
DCHECK(job->NextStepCanRunOnAnyThread());
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.CompilerDispatcherBackgroundStep");
job->StepNextOnBackgroundThread();
switch (job->status()) {
case CompilerDispatcherJob::Status::kPrepared:
job->Compile(true);
break;
default:
UNREACHABLE();
}
}
// Theoretically we get 50ms of idle time max, however it's unlikely that
......@@ -484,7 +506,7 @@ void CompilerDispatcher::ScheduleAbortTask() {
void CompilerDispatcher::ConsiderJobForBackgroundProcessing(
CompilerDispatcherJob* job) {
if (!job->CanStepNextOnAnyThread()) return;
if (!job->NextStepCanRunOnAnyThread()) return;
{
base::LockGuard<base::Mutex> lock(&mutex_);
pending_background_jobs_.insert(job);
......@@ -667,7 +689,8 @@ CompilerDispatcher::JobMap::const_iterator CompilerDispatcher::InsertJob(
CompilerDispatcherJob* inserted_job = it->second.get();
// Maps unoptimized jobs' SFIs to their job id.
if (inserted_job->type() == CompilerDispatcherJob::kUnoptimizedCompile) {
if (inserted_job->type() ==
CompilerDispatcherJob::Type::kUnoptimizedCompile) {
Handle<SharedFunctionInfo> shared =
inserted_job->AsUnoptimizedCompileJob()->shared();
if (!shared.is_null()) {
......@@ -684,7 +707,7 @@ CompilerDispatcher::JobMap::const_iterator CompilerDispatcher::RemoveJob(
job->ResetOnMainThread(isolate_);
// Unmaps unoptimized jobs' SFIs to their job id.
if (job->type() == CompilerDispatcherJob::kUnoptimizedCompile) {
if (job->type() == CompilerDispatcherJob::Type::kUnoptimizedCompile) {
Handle<SharedFunctionInfo> shared =
job->AsUnoptimizedCompileJob()->shared();
if (!shared.is_null()) {
......
......@@ -67,7 +67,7 @@ UnoptimizedCompileJob::UnoptimizedCompileJob(Isolate* isolate,
CompilerDispatcherTracer* tracer,
Handle<SharedFunctionInfo> shared,
size_t max_stack_size)
: status_(Status::kInitial),
: CompilerDispatcherJob(Type::kUnoptimizedCompile),
main_thread_id_(isolate->thread_id().ToInteger()),
tracer_(tracer),
allocator_(isolate->allocator()),
......@@ -90,8 +90,7 @@ UnoptimizedCompileJob::UnoptimizedCompileJob(Isolate* isolate,
}
UnoptimizedCompileJob::~UnoptimizedCompileJob() {
DCHECK(status_ == Status::kInitial ||
status_ == Status::kDone);
DCHECK(status() == Status::kInitial || status() == Status::kDone);
if (!shared_.is_null()) {
DCHECK_EQ(ThreadId::Current().ToInteger(), main_thread_id_);
i::GlobalHandles::Destroy(Handle<Object>::cast(shared_).location());
......@@ -107,50 +106,6 @@ bool UnoptimizedCompileJob::IsAssociatedWith(
return *shared_ == *shared;
}
void UnoptimizedCompileJob::StepNextOnMainThread(Isolate* isolate) {
DCHECK_EQ(isolate->thread_id().ToInteger(), main_thread_id_);
// Ensure we are in the correct context for the job.
SaveContext save(isolate);
if (has_context()) {
isolate->set_context(context());
} else {
// Phases which can run off the main thread by definition can't execute any
// JS code, and so we don't need to enter their context.
DCHECK(CanStepNextOnAnyThread());
}
switch (status()) {
case Status::kInitial:
return PrepareOnMainThread(isolate);
case Status::kReadyToCompile:
return Compile(false);
case Status::kCompiled:
return FinalizeOnMainThread(isolate);
case Status::kReportErrors:
return ReportErrorsOnMainThread(isolate);
case Status::kFailed:
case Status::kDone:
return;
}
UNREACHABLE();
}
void UnoptimizedCompileJob::StepNextOnBackgroundThread() {
DCHECK(CanStepNextOnAnyThread());
switch (status()) {
case Status::kReadyToCompile:
return Compile(true);
default:
UNREACHABLE();
}
}
void UnoptimizedCompileJob::PrepareOnMainThread(Isolate* isolate) {
DCHECK_EQ(ThreadId::Current().ToInteger(), main_thread_id_);
DCHECK_EQ(isolate->thread_id().ToInteger(), main_thread_id_);
......@@ -261,11 +216,11 @@ void UnoptimizedCompileJob::PrepareOnMainThread(Isolate* isolate) {
Handle<String> name(shared_->name());
parse_info_->set_function_name(
parse_info_->ast_value_factory()->GetString(name));
status_ = Status::kReadyToCompile;
set_status(Status::kPrepared);
}
void UnoptimizedCompileJob::Compile(bool on_background_thread) {
DCHECK_EQ(status(), Status::kReadyToCompile);
DCHECK_EQ(status(), Status::kPrepared);
COMPILER_DISPATCHER_TRACE_SCOPE_WITH_NUM(
tracer_, kCompile,
parse_info_->end_position() - parse_info_->start_position());
......@@ -285,13 +240,13 @@ void UnoptimizedCompileJob::Compile(bool on_background_thread) {
if (parse_info_->literal() == nullptr) {
// Parser sets error in pending error handler.
status_ = Status::kReportErrors;
set_status(Status::kHasErrorsToReport);
return;
}
if (!Compiler::Analyze(parse_info_.get())) {
parse_info_->pending_error_handler()->set_stack_overflow();
status_ = Status::kReportErrors;
set_status(Status::kHasErrorsToReport);
return;
}
......@@ -300,17 +255,17 @@ void UnoptimizedCompileJob::Compile(bool on_background_thread) {
if (!compilation_job_.get()) {
parse_info_->pending_error_handler()->set_stack_overflow();
status_ = Status::kReportErrors;
set_status(Status::kHasErrorsToReport);
return;
}
if (compilation_job_->ExecuteJob() != CompilationJob::SUCCEEDED) {
parse_info_->pending_error_handler()->set_stack_overflow();
status_ = Status::kReportErrors;
set_status(Status::kHasErrorsToReport);
return;
}
status_ = Status::kCompiled;
set_status(Status::kCompiled);
}
void UnoptimizedCompileJob::FinalizeOnMainThread(Isolate* isolate) {
......@@ -343,31 +298,35 @@ void UnoptimizedCompileJob::FinalizeOnMainThread(Isolate* isolate) {
!Compiler::FinalizeCompilationJob(compilation_job_.release(),
isolate)) {
if (!isolate->has_pending_exception()) isolate->StackOverflow();
status_ = Status::kFailed;
set_status(Status::kFailed);
return;
}
}
ResetDataOnMainThread(isolate);
status_ = Status::kDone;
set_status(Status::kDone);
}
void UnoptimizedCompileJob::ReportErrorsOnMainThread(Isolate* isolate) {
DCHECK_EQ(ThreadId::Current().ToInteger(), main_thread_id_);
DCHECK_EQ(isolate->thread_id().ToInteger(), main_thread_id_);
DCHECK_EQ(status(), Status::kReportErrors);
DCHECK_EQ(status(), Status::kHasErrorsToReport);
if (trace_compiler_dispatcher_jobs_) {
PrintF("UnoptimizedCompileJob[%p]: Reporting Errors\n",
static_cast<void*>(this));
}
// Ensure we report errors in the correct context for the job.
SaveContext save(isolate);
isolate->set_context(context());
Handle<Script> script(Script::cast(shared_->script()), isolate);
parse_info_->pending_error_handler()->ReportErrors(
isolate, script, parse_info_->ast_value_factory());
ResetDataOnMainThread(isolate);
status_ = Status::kFailed;
set_status(Status::kFailed);
}
void UnoptimizedCompileJob::ResetDataOnMainThread(Isolate* isolate) {
......@@ -399,20 +358,20 @@ void UnoptimizedCompileJob::ResetOnMainThread(Isolate* isolate) {
}
ResetDataOnMainThread(isolate);
status_ = Status::kInitial;
set_status(Status::kInitial);
}
double UnoptimizedCompileJob::EstimateRuntimeOfNextStepInMs() const {
switch (status()) {
case Status::kInitial:
return tracer_->EstimatePrepareInMs();
case Status::kReadyToCompile:
case Status::kPrepared:
return tracer_->EstimateCompileInMs(parse_info_->end_position() -
parse_info_->start_position());
case Status::kCompiled:
return tracer_->EstimateFinalizeInMs();
case Status::kReportErrors:
case Status::kHasErrorsToReport:
case Status::kFailed:
case Status::kDone:
return 0.0;
......
......@@ -32,66 +32,35 @@ class Utf16CharacterStream;
class V8_EXPORT_PRIVATE UnoptimizedCompileJob : public CompilerDispatcherJob {
public:
enum class Status {
kInitial,
kReadyToCompile,
kCompiled,
kReportErrors,
kDone,
kFailed,
};
// Creates a UnoptimizedCompileJob in the initial state.
UnoptimizedCompileJob(Isolate* isolate, CompilerDispatcherTracer* tracer,
Handle<SharedFunctionInfo> shared,
size_t max_stack_size);
~UnoptimizedCompileJob() override;
Type type() const override { return kUnoptimizedCompile; }
Handle<SharedFunctionInfo> shared() const { return shared_; }
// Returns true if this UnoptimizedCompileJob was created for the given
// function.
bool IsAssociatedWith(Handle<SharedFunctionInfo> shared) const;
bool IsFinished() override {
return status() == Status::kDone || status() == Status::kFailed;
}
bool IsFailed() override { return status() == Status::kFailed; }
// Return true if the next step can be run on any thread, that is when both
// StepNextOnMainThread and StepNextOnBackgroundThread could be used for the
// next step.
bool CanStepNextOnAnyThread() override {
return status() == Status::kReadyToCompile;
}
// Step the job forward by one state on the main thread.
void StepNextOnMainThread(Isolate* isolate) override;
// Step the job forward by one state on a background thread.
void StepNextOnBackgroundThread() override;
// Transition from any state to kInitial and free all resources.
// CompilerDispatcherJob implementation.
void PrepareOnMainThread(Isolate* isolate) override;
void Compile(bool on_background_thread) override;
void FinalizeOnMainThread(Isolate* isolate) override;
void ReportErrorsOnMainThread(Isolate* isolate) override;
void ResetOnMainThread(Isolate* isolate) override;
// Estimate how long the next step will take using the tracer.
double EstimateRuntimeOfNextStepInMs() const override;
void ShortPrintOnMainThread() override;
private:
friend class CompilerDispatcherTest;
friend class UnoptimizedCompileJobTest;
bool has_context() const { return !context_.is_null(); }
Context* context() { return *context_; }
void ResetDataOnMainThread(Isolate* isolate);
Status status() const { return status_; }
Context* context() { return *context_; }
Status status_;
int main_thread_id_;
CompilerDispatcherTracer* tracer_;
AccountingAllocator* allocator_;
......@@ -112,21 +81,6 @@ class V8_EXPORT_PRIVATE UnoptimizedCompileJob : public CompilerDispatcherJob {
bool trace_compiler_dispatcher_jobs_;
// Transition from kInitial to kReadyToCompile
void PrepareOnMainThread(Isolate* isolate);
// Transition from kReadyToCompile to kCompiled (or kReportErrors).
void Compile(bool on_background_thread);
// Transition from kCompiled to kDone (or kFailed).
void FinalizeOnMainThread(Isolate* isolate);
// Transition from kReportErrors to kFailed.
void ReportErrorsOnMainThread(Isolate* isolate);
// Free all resources.
void ResetDataOnMainThread(Isolate* isolate);
DISALLOW_COPY_AND_ASSIGN(UnoptimizedCompileJob);
};
......
......@@ -76,17 +76,6 @@ class CompilerDispatcherTest : public TestWithNativeContext {
CompilerDispatcherTestFlags::RestoreFlags();
}
static UnoptimizedCompileJob::Status GetUnoptimizedJobStatus(
const CompilerDispatcherJob* job) {
CHECK_EQ(CompilerDispatcherJob::kUnoptimizedCompile, job->type());
return job->AsUnoptimizedCompileJob()->status();
}
static UnoptimizedCompileJob::Status GetUnoptimizedJobStatus(
const std::unique_ptr<CompilerDispatcherJob>& job) {
return GetUnoptimizedJobStatus(job.get());
}
private:
DISALLOW_COPY_AND_ASSIGN(CompilerDispatcherTest);
};
......@@ -386,7 +375,7 @@ TEST_F(CompilerDispatcherTest, IdleTaskSmallIdleTime) {
// The job should be scheduled for the main thread.
ASSERT_EQ(dispatcher.jobs_.size(), 1u);
ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
dispatcher.jobs_.begin()->second->status());
// Only grant a little idle time and have time advance beyond it in one step.
platform.RunIdleTask(2.0, 1.0);
......@@ -398,8 +387,8 @@ TEST_F(CompilerDispatcherTest, IdleTaskSmallIdleTime) {
// The job should be still scheduled for the main thread, but ready for
// parsing.
ASSERT_EQ(dispatcher.jobs_.size(), 1u);
ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToCompile,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kPrepared,
dispatcher.jobs_.begin()->second->status());
// Now grant a lot of idle time and freeze time.
platform.RunIdleTask(1000.0, 0.0);
......@@ -450,14 +439,14 @@ TEST_F(CompilerDispatcherTest, CompileOnBackgroundThread) {
ASSERT_EQ(dispatcher.jobs_.size(), 1u);
ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
dispatcher.jobs_.begin()->second->status());
// Make compiling super expensive, and advance job as much as possible on the
// foreground thread.
dispatcher.tracer_->RecordCompile(50000.0, 1);
platform.RunIdleTask(10.0, 0.0);
ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToCompile,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kPrepared,
dispatcher.jobs_.begin()->second->status());
ASSERT_TRUE(dispatcher.IsEnqueued(shared));
ASSERT_FALSE(shared->is_compiled());
......@@ -469,7 +458,7 @@ TEST_F(CompilerDispatcherTest, CompileOnBackgroundThread) {
ASSERT_TRUE(platform.IdleTaskPending());
ASSERT_FALSE(platform.BackgroundTasksPending());
ASSERT_EQ(UnoptimizedCompileJob::Status::kCompiled,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
dispatcher.jobs_.begin()->second->status());
// Now grant a lot of idle time and freeze time.
platform.RunIdleTask(1000.0, 0.0);
......@@ -493,14 +482,14 @@ TEST_F(CompilerDispatcherTest, FinishNowWithBackgroundTask) {
ASSERT_EQ(dispatcher.jobs_.size(), 1u);
ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
dispatcher.jobs_.begin()->second->status());
// Make compiling super expensive, and advance job as much as possible on the
// foreground thread.
dispatcher.tracer_->RecordCompile(50000.0, 1);
platform.RunIdleTask(10.0, 0.0);
ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToCompile,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kPrepared,
dispatcher.jobs_.begin()->second->status());
ASSERT_TRUE(dispatcher.IsEnqueued(shared));
ASSERT_FALSE(shared->is_compiled());
......@@ -587,14 +576,14 @@ TEST_F(CompilerDispatcherTest, AsyncAbortAllPendingBackgroundTask) {
ASSERT_EQ(dispatcher.jobs_.size(), 1u);
ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
dispatcher.jobs_.begin()->second->status());
// Make compiling super expensive, and advance job as much as possible on the
// foreground thread.
dispatcher.tracer_->RecordCompile(50000.0, 1);
platform.RunIdleTask(10.0, 0.0);
ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToCompile,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kPrepared,
dispatcher.jobs_.begin()->second->status());
ASSERT_TRUE(dispatcher.IsEnqueued(shared));
ASSERT_FALSE(shared->is_compiled());
......@@ -633,14 +622,14 @@ TEST_F(CompilerDispatcherTest, AsyncAbortAllRunningBackgroundTask) {
ASSERT_EQ(dispatcher.jobs_.size(), 1u);
ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
dispatcher.jobs_.begin()->second->status());
// Make compiling super expensive, and advance job as much as possible on the
// foreground thread.
dispatcher.tracer_->RecordCompile(50000.0, 1);
platform.RunIdleTask(10.0, 0.0);
ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToCompile,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kPrepared,
dispatcher.jobs_.begin()->second->status());
ASSERT_TRUE(dispatcher.IsEnqueued(shared1));
ASSERT_FALSE(shared1->is_compiled());
......@@ -709,14 +698,14 @@ TEST_F(CompilerDispatcherTest, FinishNowDuringAbortAll) {
ASSERT_EQ(dispatcher.jobs_.size(), 1u);
ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
dispatcher.jobs_.begin()->second->status());
// Make compiling super expensive, and advance job as much as possible on the
// foreground thread.
dispatcher.tracer_->RecordCompile(50000.0, 1);
platform.RunIdleTask(10.0, 0.0);
ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToCompile,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kPrepared,
dispatcher.jobs_.begin()->second->status());
ASSERT_TRUE(dispatcher.IsEnqueued(shared));
ASSERT_FALSE(shared->is_compiled());
......@@ -882,8 +871,8 @@ TEST_F(CompilerDispatcherTest, EnqueueAndStep) {
ASSERT_TRUE(dispatcher.EnqueueAndStep(shared));
ASSERT_TRUE(dispatcher.IsEnqueued(shared));
ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToCompile,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kPrepared,
dispatcher.jobs_.begin()->second->status());
ASSERT_TRUE(platform.IdleTaskPending());
platform.ClearIdleTask();
......@@ -948,13 +937,13 @@ TEST_F(CompilerDispatcherTest, EnqueueAndStepTwice) {
ASSERT_FALSE(dispatcher.IsEnqueued(shared));
ASSERT_TRUE(dispatcher.EnqueueAndStep(shared));
ASSERT_TRUE(dispatcher.IsEnqueued(shared));
ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToCompile,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kPrepared,
dispatcher.jobs_.begin()->second->status());
// EnqueueAndStep of the same function again (shouldn't step the job.
ASSERT_TRUE(dispatcher.EnqueueAndStep(shared));
ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToCompile,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kPrepared,
dispatcher.jobs_.begin()->second->status());
ASSERT_TRUE(platform.IdleTaskPending());
ASSERT_TRUE(platform.BackgroundTasksPending());
......@@ -980,19 +969,19 @@ TEST_F(CompilerDispatcherTest, CompileMultipleOnBackgroundThread) {
ASSERT_EQ(dispatcher.jobs_.size(), 2u);
ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
dispatcher.jobs_.begin()->second->status());
ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
GetUnoptimizedJobStatus((++dispatcher.jobs_.begin())->second));
(++dispatcher.jobs_.begin())->second->status());
// Make compiling super expensive, and advance job as much as possible on the
// foreground thread.
dispatcher.tracer_->RecordCompile(50000.0, 1);
platform.RunIdleTask(10.0, 0.0);
ASSERT_EQ(dispatcher.jobs_.size(), 2u);
ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToCompile,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToCompile,
GetUnoptimizedJobStatus((++dispatcher.jobs_.begin())->second));
ASSERT_EQ(UnoptimizedCompileJob::Status::kPrepared,
dispatcher.jobs_.begin()->second->status());
ASSERT_EQ(UnoptimizedCompileJob::Status::kPrepared,
(++dispatcher.jobs_.begin())->second->status());
ASSERT_TRUE(dispatcher.IsEnqueued(shared1));
ASSERT_TRUE(dispatcher.IsEnqueued(shared2));
......@@ -1007,9 +996,9 @@ TEST_F(CompilerDispatcherTest, CompileMultipleOnBackgroundThread) {
ASSERT_FALSE(platform.BackgroundTasksPending());
ASSERT_EQ(dispatcher.jobs_.size(), 2u);
ASSERT_EQ(UnoptimizedCompileJob::Status::kCompiled,
GetUnoptimizedJobStatus(dispatcher.jobs_.begin()->second));
dispatcher.jobs_.begin()->second->status());
ASSERT_EQ(UnoptimizedCompileJob::Status::kCompiled,
GetUnoptimizedJobStatus((++dispatcher.jobs_.begin())->second));
(++dispatcher.jobs_.begin())->second->status());
// Now grant a lot of idle time and freeze time.
platform.RunIdleTask(1000.0, 0.0);
......
......@@ -43,15 +43,6 @@ class UnoptimizedCompileJobTest : public TestWithNativeContext {
save_flags_ = nullptr;
}
static UnoptimizedCompileJob::Status GetStatus(UnoptimizedCompileJob* job) {
return job->status();
}
static UnoptimizedCompileJob::Status GetStatus(
const std::unique_ptr<UnoptimizedCompileJob>& job) {
return GetStatus(job.get());
}
static Variable* LookupVariableByName(UnoptimizedCompileJob* job,
const char* name) {
const AstRawString* name_raw_string =
......@@ -68,7 +59,7 @@ class UnoptimizedCompileJobTest : public TestWithNativeContext {
SaveFlags* UnoptimizedCompileJobTest::save_flags_ = nullptr;
#define ASSERT_JOB_STATUS(STATUS, JOB) ASSERT_EQ(STATUS, GetStatus(JOB))
#define ASSERT_JOB_STATUS(STATUS, JOB) ASSERT_EQ(STATUS, JOB->status())
TEST_F(UnoptimizedCompileJobTest, Construct) {
std::unique_ptr<UnoptimizedCompileJob> job(new UnoptimizedCompileJob(
......@@ -81,18 +72,18 @@ TEST_F(UnoptimizedCompileJobTest, StateTransitions) {
isolate(), tracer(), test::CreateSharedFunctionInfo(isolate(), nullptr),
FLAG_stack_size));
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kInitial, job);
job->StepNextOnMainThread(isolate());
ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kInitial, job);
job->PrepareOnMainThread(isolate());
ASSERT_FALSE(job->IsFailed());
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kReadyToCompile, job);
job->StepNextOnMainThread(isolate());
ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kPrepared, job);
job->Compile(false);
ASSERT_FALSE(job->IsFailed());
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kCompiled, job);
job->StepNextOnMainThread(isolate());
ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kCompiled, job);
job->FinalizeOnMainThread(isolate());
ASSERT_FALSE(job->IsFailed());
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kDone, job);
ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kDone, job);
job->ResetOnMainThread(isolate());
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kInitial, job);
ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kInitial, job);
}
TEST_F(UnoptimizedCompileJobTest, SyntaxError) {
......@@ -101,19 +92,19 @@ TEST_F(UnoptimizedCompileJobTest, SyntaxError) {
isolate(), tracer(), test::CreateSharedFunctionInfo(isolate(), &script),
FLAG_stack_size));
job->StepNextOnMainThread(isolate());
job->PrepareOnMainThread(isolate());
ASSERT_FALSE(job->IsFailed());
job->StepNextOnMainThread(isolate());
job->Compile(false);
ASSERT_FALSE(job->IsFailed());
job->StepNextOnMainThread(isolate());
job->ReportErrorsOnMainThread(isolate());
ASSERT_TRUE(job->IsFailed());
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kFailed, job);
ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kFailed, job);
ASSERT_TRUE(isolate()->has_pending_exception());
isolate()->clear_pending_exception();
job->ResetOnMainThread(isolate());
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kInitial, job);
ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kInitial, job);
}
TEST_F(UnoptimizedCompileJobTest, CompileAndRun) {
......@@ -130,19 +121,19 @@ TEST_F(UnoptimizedCompileJobTest, CompileAndRun) {
std::unique_ptr<UnoptimizedCompileJob> job(new UnoptimizedCompileJob(
isolate(), tracer(), handle(f->shared()), FLAG_stack_size));
job->StepNextOnMainThread(isolate());
job->PrepareOnMainThread(isolate());
ASSERT_FALSE(job->IsFailed());
job->StepNextOnMainThread(isolate());
job->Compile(false);
ASSERT_FALSE(job->IsFailed());
job->StepNextOnMainThread(isolate());
job->FinalizeOnMainThread(isolate());
ASSERT_FALSE(job->IsFailed());
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kDone, job);
ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kDone, job);
Smi* value = Smi::cast(*RunJS("f(100);"));
ASSERT_TRUE(value == Smi::FromInt(160));
job->ResetOnMainThread(isolate());
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kInitial, job);
ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kInitial, job);
}
TEST_F(UnoptimizedCompileJobTest, CompileFailureToAnalyse) {
......@@ -160,18 +151,18 @@ TEST_F(UnoptimizedCompileJobTest, CompileFailureToAnalyse) {
isolate(), tracer(), test::CreateSharedFunctionInfo(isolate(), &script),
100));
job->StepNextOnMainThread(isolate());
job->PrepareOnMainThread(isolate());
ASSERT_FALSE(job->IsFailed());
job->StepNextOnMainThread(isolate());
job->Compile(false);
ASSERT_FALSE(job->IsFailed());
job->StepNextOnMainThread(isolate());
job->ReportErrorsOnMainThread(isolate());
ASSERT_TRUE(job->IsFailed());
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kFailed, job);
ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kFailed, job);
ASSERT_TRUE(isolate()->has_pending_exception());
isolate()->clear_pending_exception();
job->ResetOnMainThread(isolate());
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kInitial, job);
ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kInitial, job);
}
TEST_F(UnoptimizedCompileJobTest, CompileFailureToFinalize) {
......@@ -186,18 +177,18 @@ TEST_F(UnoptimizedCompileJobTest, CompileFailureToFinalize) {
isolate(), tracer(), test::CreateSharedFunctionInfo(isolate(), &script),
50));
job->StepNextOnMainThread(isolate());
job->PrepareOnMainThread(isolate());
ASSERT_FALSE(job->IsFailed());
job->StepNextOnMainThread(isolate());
job->Compile(false);
ASSERT_FALSE(job->IsFailed());
job->StepNextOnMainThread(isolate());
job->ReportErrorsOnMainThread(isolate());
ASSERT_TRUE(job->IsFailed());
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kFailed, job);
ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kFailed, job);
ASSERT_TRUE(isolate()->has_pending_exception());
isolate()->clear_pending_exception();
job->ResetOnMainThread(isolate());
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kInitial, job);
ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kInitial, job);
}
class CompileTask : public Task {
......@@ -207,7 +198,7 @@ class CompileTask : public Task {
~CompileTask() override {}
void Run() override {
job_->StepNextOnBackgroundThread();
job_->Compile(true);
ASSERT_FALSE(job_->IsFailed());
semaphore_->Signal();
}
......@@ -231,21 +222,21 @@ TEST_F(UnoptimizedCompileJobTest, CompileOnBackgroundThread) {
isolate(), tracer(), test::CreateSharedFunctionInfo(isolate(), &script),
100));
job->StepNextOnMainThread(isolate());
job->PrepareOnMainThread(isolate());
ASSERT_FALSE(job->IsFailed());
base::Semaphore semaphore(0);
CompileTask* background_task = new CompileTask(job.get(), &semaphore);
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kReadyToCompile, job);
ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kPrepared, job);
V8::GetCurrentPlatform()->CallOnBackgroundThread(background_task,
Platform::kShortRunningTask);
semaphore.Wait();
job->StepNextOnMainThread(isolate());
job->FinalizeOnMainThread(isolate());
ASSERT_FALSE(job->IsFailed());
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kDone, job);
ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kDone, job);
job->ResetOnMainThread(isolate());
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kInitial, job);
ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kInitial, job);
}
TEST_F(UnoptimizedCompileJobTest, LazyInnerFunctions) {
......@@ -260,21 +251,23 @@ TEST_F(UnoptimizedCompileJobTest, LazyInnerFunctions) {
std::unique_ptr<UnoptimizedCompileJob> job(new UnoptimizedCompileJob(
isolate(), tracer(), handle(f->shared()), FLAG_stack_size));
job->StepNextOnMainThread(isolate());
job->PrepareOnMainThread(isolate());
ASSERT_FALSE(job->IsFailed());
job->StepNextOnMainThread(isolate());
job->Compile(false);
ASSERT_FALSE(job->IsFailed());
job->StepNextOnMainThread(isolate());
job->FinalizeOnMainThread(isolate());
ASSERT_FALSE(job->IsFailed());
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kDone, job);
ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kDone, job);
Handle<JSFunction> e = RunJS<JSFunction>("f();");
ASSERT_FALSE(e->shared()->is_compiled());
job->ResetOnMainThread(isolate());
ASSERT_JOB_STATUS(UnoptimizedCompileJob::Status::kInitial, job);
ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kInitial, job);
}
#undef ASSERT_JOB_STATUS
} // namespace internal
} // namespace v8
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