// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/compiler-dispatcher/compiler-dispatcher.h"

#include "src/ast/ast.h"
#include "src/base/platform/time.h"
#include "src/codegen/compiler.h"
#include "src/flags/flags.h"
#include "src/handles/global-handles.h"
#include "src/objects/objects-inl.h"
#include "src/parsing/parse-info.h"
#include "src/parsing/parser.h"
#include "src/tasks/cancelable-task.h"
#include "src/tasks/task-utils.h"
#include "src/zone/zone-list-inl.h"  // crbug.com/v8/8816

namespace v8 {
namespace internal {

CompilerDispatcher::Job::Job(BackgroundCompileTask* task_arg)
    : task(task_arg), has_run(false), aborted(false) {}

CompilerDispatcher::Job::~Job() = default;

CompilerDispatcher::CompilerDispatcher(Isolate* isolate, Platform* platform,
                                       size_t max_stack_size)
    : isolate_(isolate),
      worker_thread_runtime_call_stats_(
          isolate->counters()->worker_thread_runtime_call_stats()),
      background_compile_timer_(
          isolate->counters()->compile_function_on_background()),
      taskrunner_(platform->GetForegroundTaskRunner(
          reinterpret_cast<v8::Isolate*>(isolate))),
      platform_(platform),
      max_stack_size_(max_stack_size),
      trace_compiler_dispatcher_(FLAG_trace_compiler_dispatcher),
      task_manager_(new CancelableTaskManager()),
      next_job_id_(0),
      shared_to_unoptimized_job_id_(isolate->heap()),
      idle_task_scheduled_(false),
      num_worker_tasks_(0),
      main_thread_blocking_on_job_(nullptr),
      block_for_testing_(false),
      semaphore_for_testing_(0) {
  if (trace_compiler_dispatcher_ && !IsEnabled()) {
    PrintF("CompilerDispatcher: dispatcher is disabled\n");
  }
}

CompilerDispatcher::~CompilerDispatcher() {
  // AbortAll must be called before CompilerDispatcher is destroyed.
  CHECK(task_manager_->canceled());
}

base::Optional<CompilerDispatcher::JobId> CompilerDispatcher::Enqueue(
    const ParseInfo* outer_parse_info, const AstRawString* function_name,
    const FunctionLiteral* function_literal) {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
               "V8.CompilerDispatcherEnqueue");
  RuntimeCallTimerScope runtimeTimer(
      isolate_, RuntimeCallCounterId::kCompileEnqueueOnDispatcher);

  if (!IsEnabled()) return base::nullopt;

  std::unique_ptr<Job> job = std::make_unique<Job>(new BackgroundCompileTask(
      outer_parse_info, function_name, function_literal,
      worker_thread_runtime_call_stats_, background_compile_timer_,
      static_cast<int>(max_stack_size_)));
  JobMap::const_iterator it = InsertJob(std::move(job));
  JobId id = it->first;
  if (trace_compiler_dispatcher_) {
    PrintF("CompilerDispatcher: enqueued job %zu for function literal id %d\n",
           id, function_literal->function_literal_id());
  }

  // Post a a background worker task to perform the compilation on the worker
  // thread.
  {
    base::MutexGuard lock(&mutex_);
    pending_background_jobs_.insert(it->second.get());
  }
  ScheduleMoreWorkerTasksIfNeeded();
  return base::make_optional(id);
}

bool CompilerDispatcher::IsEnabled() const { return FLAG_compiler_dispatcher; }

bool CompilerDispatcher::IsEnqueued(Handle<SharedFunctionInfo> function) const {
  if (jobs_.empty()) return false;
  return GetJobFor(function) != jobs_.end();
}

bool CompilerDispatcher::IsEnqueued(JobId job_id) const {
  return jobs_.find(job_id) != jobs_.end();
}

void CompilerDispatcher::RegisterSharedFunctionInfo(
    JobId job_id, SharedFunctionInfo function) {
  DCHECK_NE(jobs_.find(job_id), jobs_.end());

  if (trace_compiler_dispatcher_) {
    PrintF("CompilerDispatcher: registering ");
    function.ShortPrint();
    PrintF(" with job id %zu\n", job_id);
  }

  // Make a global handle to the function.
  Handle<SharedFunctionInfo> function_handle = Handle<SharedFunctionInfo>::cast(
      isolate_->global_handles()->Create(function));

  // Register mapping.
  auto job_it = jobs_.find(job_id);
  DCHECK_NE(job_it, jobs_.end());
  Job* job = job_it->second.get();
  shared_to_unoptimized_job_id_.Insert(function_handle, job_id);

  {
    base::MutexGuard lock(&mutex_);
    job->function = function_handle;
    if (job->IsReadyToFinalize(lock)) {
      // Schedule an idle task to finalize job if it is ready.
      ScheduleIdleTaskFromAnyThread(lock);
    }
  }
}

void CompilerDispatcher::WaitForJobIfRunningOnBackground(Job* job) {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
               "V8.CompilerDispatcherWaitForBackgroundJob");
  RuntimeCallTimerScope runtimeTimer(
      isolate_, RuntimeCallCounterId::kCompileWaitForDispatcher);

  base::MutexGuard 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) {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
               "V8.CompilerDispatcherFinishNow");
  RuntimeCallTimerScope runtimeTimer(
      isolate_, RuntimeCallCounterId::kCompileFinishNowOnDispatcher);
  if (trace_compiler_dispatcher_) {
    PrintF("CompilerDispatcher: finishing ");
    function->ShortPrint();
    PrintF(" now\n");
  }

  JobMap::const_iterator it = GetJobFor(function);
  CHECK(it != jobs_.end());
  Job* job = it->second.get();
  WaitForJobIfRunningOnBackground(job);

  if (!job->has_run) {
    job->task->Run();
    job->has_run = true;
  }

  DCHECK(job->IsReadyToFinalize(&mutex_));
  DCHECK(!job->aborted);
  bool success = Compiler::FinalizeBackgroundCompileTask(
      job->task.get(), function, isolate_, Compiler::KEEP_EXCEPTION);

  DCHECK_NE(success, isolate_->has_pending_exception());
  RemoveJob(it);
  return success;
}

void CompilerDispatcher::AbortJob(JobId job_id) {
  if (trace_compiler_dispatcher_) {
    PrintF("CompilerDispatcher: aborted job %zu\n", job_id);
  }
  JobMap::const_iterator job_it = jobs_.find(job_id);
  Job* job = job_it->second.get();

  base::LockGuard<base::Mutex> lock(&mutex_);
  pending_background_jobs_.erase(job);
  if (running_background_jobs_.find(job) == running_background_jobs_.end()) {
    RemoveJob(job_it);
  } else {
    // Job is currently running on the background thread, wait until it's done
    // and remove job then.
    job->aborted = true;
  }
}

void CompilerDispatcher::AbortAll() {
  task_manager_->TryAbortAll();

  for (auto& it : jobs_) {
    WaitForJobIfRunningOnBackground(it.second.get());
    if (trace_compiler_dispatcher_) {
      PrintF("CompilerDispatcher: aborted job %zu\n", it.first);
    }
  }
  jobs_.clear();
  shared_to_unoptimized_job_id_.Clear();
  {
    base::MutexGuard lock(&mutex_);
    DCHECK(pending_background_jobs_.empty());
    DCHECK(running_background_jobs_.empty());
  }

  task_manager_->CancelAndWait();
}

CompilerDispatcher::JobMap::const_iterator CompilerDispatcher::GetJobFor(
    Handle<SharedFunctionInfo> shared) const {
  JobId* job_id_ptr = shared_to_unoptimized_job_id_.Find(shared);
  JobMap::const_iterator job = jobs_.end();
  if (job_id_ptr) {
    job = jobs_.find(*job_id_ptr);
  }
  return job;
}

void CompilerDispatcher::ScheduleIdleTaskFromAnyThread(
    const base::MutexGuard&) {
  if (!taskrunner_->IdleTasksEnabled()) return;
  if (idle_task_scheduled_) return;

  idle_task_scheduled_ = true;
  taskrunner_->PostIdleTask(MakeCancelableIdleTask(
      task_manager_.get(),
      [this](double deadline_in_seconds) { DoIdleWork(deadline_in_seconds); }));
}

void CompilerDispatcher::ScheduleMoreWorkerTasksIfNeeded() {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
               "V8.CompilerDispatcherScheduleMoreWorkerTasksIfNeeded");
  {
    base::MutexGuard lock(&mutex_);
    if (pending_background_jobs_.empty()) return;
    if (platform_->NumberOfWorkerThreads() <= num_worker_tasks_) {
      return;
    }
    ++num_worker_tasks_;
  }
  platform_->CallOnWorkerThread(
      MakeCancelableTask(task_manager_.get(), [this] { DoBackgroundWork(); }));
}

void CompilerDispatcher::DoBackgroundWork() {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
               "V8.CompilerDispatcherDoBackgroundWork");
  for (;;) {
    Job* job = nullptr;
    {
      base::MutexGuard lock(&mutex_);
      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) break;

    if (V8_UNLIKELY(block_for_testing_.Value())) {
      block_for_testing_.SetValue(false);
      semaphore_for_testing_.Wait();
    }

    if (trace_compiler_dispatcher_) {
      PrintF("CompilerDispatcher: doing background work\n");
    }

    job->task->Run();

    {
      base::MutexGuard lock(&mutex_);
      running_background_jobs_.erase(job);

      job->has_run = true;
      if (job->IsReadyToFinalize(lock)) {
        // Schedule an idle task to finalize the compilation on the main thread
        // if the job has a shared function info registered.
        ScheduleIdleTaskFromAnyThread(lock);
      }

      if (main_thread_blocking_on_job_ == job) {
        main_thread_blocking_on_job_ = nullptr;
        main_thread_blocking_signal_.NotifyOne();
      }
    }
  }

  {
    base::MutexGuard lock(&mutex_);
    --num_worker_tasks_;
  }
  // Don't touch |this| anymore after this point, as it might have been
  // deleted.
}

void CompilerDispatcher::DoIdleWork(double deadline_in_seconds) {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
               "V8.CompilerDispatcherDoIdleWork");
  {
    base::MutexGuard lock(&mutex_);
    idle_task_scheduled_ = false;
  }

  if (trace_compiler_dispatcher_) {
    PrintF("CompilerDispatcher: received %0.1lfms of idle time\n",
           (deadline_in_seconds - platform_->MonotonicallyIncreasingTime()) *
               static_cast<double>(base::Time::kMillisecondsPerSecond));
  }
  while (deadline_in_seconds > platform_->MonotonicallyIncreasingTime()) {
    // Find a job which is pending finalization and has a shared function info
    CompilerDispatcher::JobMap::const_iterator it;
    {
      base::MutexGuard lock(&mutex_);
      for (it = jobs_.cbegin(); it != jobs_.cend(); ++it) {
        if (it->second->IsReadyToFinalize(lock)) break;
      }
      // Since we hold the lock here, we can be sure no jobs have become ready
      // for finalization while we looped through the list.
      if (it == jobs_.cend()) return;

      DCHECK(it->second->IsReadyToFinalize(lock));
      DCHECK_EQ(running_background_jobs_.find(it->second.get()),
                running_background_jobs_.end());
      DCHECK_EQ(pending_background_jobs_.find(it->second.get()),
                pending_background_jobs_.end());
    }

    Job* job = it->second.get();
    if (!job->aborted) {
      Compiler::FinalizeBackgroundCompileTask(
          job->task.get(), job->function.ToHandleChecked(), isolate_,
          Compiler::CLEAR_EXCEPTION);
    }
    RemoveJob(it);
  }

  // We didn't return above so there still might be jobs to finalize.
  {
    base::MutexGuard lock(&mutex_);
    ScheduleIdleTaskFromAnyThread(lock);
  }
}

CompilerDispatcher::JobMap::const_iterator CompilerDispatcher::InsertJob(
    std::unique_ptr<Job> job) {
  bool added;
  JobMap::const_iterator it;
  std::tie(it, added) =
      jobs_.insert(std::make_pair(next_job_id_++, std::move(job)));
  DCHECK(added);
  return it;
}

CompilerDispatcher::JobMap::const_iterator CompilerDispatcher::RemoveJob(
    CompilerDispatcher::JobMap::const_iterator it) {
  Job* job = it->second.get();

  DCHECK_EQ(running_background_jobs_.find(job), running_background_jobs_.end());
  DCHECK_EQ(pending_background_jobs_.find(job), pending_background_jobs_.end());

  // Delete SFI associated with job if its been registered.
  Handle<SharedFunctionInfo> function;
  if (job->function.ToHandle(&function)) {
    GlobalHandles::Destroy(function.location());
  }

  // Delete job.
  return jobs_.erase(it);
}

}  // namespace internal
}  // namespace v8
