// 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/base/template-utils.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),
      allocator_(isolate->allocator()),
      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 = base::make_unique<Job>(new BackgroundCompileTask(
      allocator_, 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_.Set(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
