// 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 "test/inspector/task-runner.h"

#include "include/libplatform/libplatform.h"
#include "src/flags/flags.h"

#if !defined(_WIN32) && !defined(_WIN64)
#include <unistd.h>  // NOLINT
#endif               // !defined(_WIN32) && !defined(_WIN64)

namespace v8 {
namespace internal {

namespace {

void ReportUncaughtException(v8::Isolate* isolate,
                             const v8::TryCatch& try_catch) {
  CHECK(try_catch.HasCaught());
  v8::HandleScope handle_scope(isolate);
  std::string message =
      *v8::String::Utf8Value(isolate, try_catch.Message()->Get());
  int line = try_catch.Message()
                 ->GetLineNumber(isolate->GetCurrentContext())
                 .FromJust();
  std::string source_line = *v8::String::Utf8Value(
      isolate, try_catch.Message()
                   ->GetSourceLine(isolate->GetCurrentContext())
                   .ToLocalChecked());
  fprintf(stderr, "Unhandled exception: %s @%s[%d]\n", message.data(),
          source_line.data(), line);
}

}  //  namespace

TaskRunner::TaskRunner(IsolateData::SetupGlobalTasks setup_global_tasks,
                       CatchExceptions catch_exceptions,
                       v8::base::Semaphore* ready_semaphore,
                       v8::StartupData* startup_data,
                       WithInspector with_inspector)
    : Thread(Options("Task Runner")),
      setup_global_tasks_(std::move(setup_global_tasks)),
      startup_data_(startup_data),
      with_inspector_(with_inspector),
      catch_exceptions_(catch_exceptions),
      ready_semaphore_(ready_semaphore),
      data_(nullptr),
      process_queue_semaphore_(0),
      nested_loop_count_(0),
      is_terminated_(0) {
  CHECK(Start());
}

TaskRunner::~TaskRunner() { Join(); }

void TaskRunner::Run() {
  data_.reset(new IsolateData(this, std::move(setup_global_tasks_),
                              startup_data_, with_inspector_));
  if (ready_semaphore_) ready_semaphore_->Signal();
  RunMessageLoop(false);
}

void TaskRunner::RunMessageLoop(bool only_protocol) {
  int loop_number = ++nested_loop_count_;
  while (nested_loop_count_ == loop_number && !is_terminated_) {
    std::unique_ptr<TaskRunner::Task> task = GetNext(only_protocol);
    if (!task) return;
    v8::Isolate::Scope isolate_scope(isolate());
    if (catch_exceptions_) {
      v8::TryCatch try_catch(isolate());
      task->Run(data_.get());
      if (try_catch.HasCaught()) {
        ReportUncaughtException(isolate(), try_catch);
        fflush(stdout);
        fflush(stderr);
        _exit(0);
      }
    } else {
      task->Run(data_.get());
    }
    task.reset();
    // Also pump isolate's foreground task queue to ensure progress.
    // This can be removed once https://crbug.com/v8/10747 is fixed.
    // TODO(10748): Enable --stress-incremental-marking after the existing
    // tests are fixed.
    if (!i::FLAG_stress_incremental_marking) {
      while (v8::platform::PumpMessageLoop(
          v8::internal::V8::GetCurrentPlatform(), isolate())) {
      }
    }
  }
}

void TaskRunner::QuitMessageLoop() {
  DCHECK_LT(0, nested_loop_count_);
  --nested_loop_count_;
}

void TaskRunner::Append(std::unique_ptr<Task> task) {
  queue_.Enqueue(std::move(task));
  process_queue_semaphore_.Signal();
}

void TaskRunner::Terminate() {
  is_terminated_++;
  process_queue_semaphore_.Signal();
}

std::unique_ptr<TaskRunner::Task> TaskRunner::GetNext(bool only_protocol) {
  for (;;) {
    if (is_terminated_) return nullptr;
    if (only_protocol) {
      std::unique_ptr<Task> task;
      if (queue_.Dequeue(&task)) {
        if (task->is_priority_task()) return task;
        deferred_queue_.Enqueue(std::move(task));
      }
    } else {
      std::unique_ptr<Task> task;
      if (deferred_queue_.Dequeue(&task)) return task;
      if (queue_.Dequeue(&task)) return task;
    }
    process_queue_semaphore_.Wait();
  }
  return nullptr;
}

}  // namespace internal
}  // namespace v8
