// 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-tracer.h"

#include "src/isolate.h"

namespace v8 {
namespace internal {

namespace {

double MonotonicallyIncreasingTimeInMs() {
  return V8::GetCurrentPlatform()->MonotonicallyIncreasingTime() *
         static_cast<double>(base::Time::kMillisecondsPerSecond);
}

const double kEstimatedRuntimeWithoutData = 1.0;

}  // namespace

CompilerDispatcherTracer::Scope::Scope(CompilerDispatcherTracer* tracer,
                                       ScopeID scope_id, size_t num)
    : tracer_(tracer), scope_id_(scope_id), num_(num) {
  start_time_ = MonotonicallyIncreasingTimeInMs();
  // TODO(cbruni): remove once we fully moved to a trace-based system.
  if (V8_UNLIKELY(FLAG_runtime_stats)) {
    RuntimeCallStats::Enter(tracer_->runtime_call_stats_, &timer_,
                            &RuntimeCallStats::CompilerDispatcher);
  }
}

CompilerDispatcherTracer::Scope::~Scope() {
  double elapsed = MonotonicallyIncreasingTimeInMs() - start_time_;
  switch (scope_id_) {
    case ScopeID::kPrepareToParse:
      tracer_->RecordPrepareToParse(elapsed);
      break;
    case ScopeID::kParse:
      tracer_->RecordParse(elapsed, num_);
      break;
    case ScopeID::kFinalizeParsing:
      tracer_->RecordFinalizeParsing(elapsed);
      break;
    case ScopeID::kPrepareToCompile:
      tracer_->RecordPrepareToCompile(elapsed);
      break;
    case ScopeID::kCompile:
      tracer_->RecordCompile(elapsed, num_);
      break;
    case ScopeID::kFinalizeCompiling:
      tracer_->RecordFinalizeCompiling(elapsed);
      break;
  }
  // TODO(cbruni): remove once we fully moved to a trace-based system.
  if (V8_UNLIKELY(FLAG_runtime_stats)) {
    RuntimeCallStats::Leave(tracer_->runtime_call_stats_, &timer_);
  }
}

// static
const char* CompilerDispatcherTracer::Scope::Name(ScopeID scope_id) {
  switch (scope_id) {
    case ScopeID::kPrepareToParse:
      return "V8.BackgroundCompile_PrepareToParse";
    case ScopeID::kParse:
      return "V8.BackgroundCompile_Parse";
    case ScopeID::kFinalizeParsing:
      return "V8.BackgroundCompile_FinalizeParsing";
    case ScopeID::kPrepareToCompile:
      return "V8.BackgroundCompile_PrepareToCompile";
    case ScopeID::kCompile:
      return "V8.BackgroundCompile_Compile";
    case ScopeID::kFinalizeCompiling:
      return "V8.BackgroundCompile_FinalizeCompiling";
  }
  UNREACHABLE();
  return nullptr;
}

CompilerDispatcherTracer::CompilerDispatcherTracer(Isolate* isolate)
    : runtime_call_stats_(nullptr) {
  // isolate might be nullptr during unittests.
  if (isolate) {
    runtime_call_stats_ = isolate->counters()->runtime_call_stats();
  }
}

CompilerDispatcherTracer::~CompilerDispatcherTracer() {}

void CompilerDispatcherTracer::RecordPrepareToParse(double duration_ms) {
  base::LockGuard<base::Mutex> lock(&mutex_);
  prepare_parse_events_.Push(duration_ms);
}

void CompilerDispatcherTracer::RecordParse(double duration_ms,
                                           size_t source_length) {
  base::LockGuard<base::Mutex> lock(&mutex_);
  parse_events_.Push(std::make_pair(source_length, duration_ms));
}

void CompilerDispatcherTracer::RecordFinalizeParsing(double duration_ms) {
  base::LockGuard<base::Mutex> lock(&mutex_);
  finalize_parsing_events_.Push(duration_ms);
}

void CompilerDispatcherTracer::RecordPrepareToCompile(double duration_ms) {
  base::LockGuard<base::Mutex> lock(&mutex_);
  prepare_compile_events_.Push(duration_ms);
}

void CompilerDispatcherTracer::RecordCompile(double duration_ms,
                                             size_t ast_size_in_bytes) {
  base::LockGuard<base::Mutex> lock(&mutex_);
  compile_events_.Push(std::make_pair(ast_size_in_bytes, duration_ms));
}

void CompilerDispatcherTracer::RecordFinalizeCompiling(double duration_ms) {
  base::LockGuard<base::Mutex> lock(&mutex_);
  finalize_compiling_events_.Push(duration_ms);
}

double CompilerDispatcherTracer::EstimatePrepareToParseInMs() const {
  base::LockGuard<base::Mutex> lock(&mutex_);
  return Average(prepare_parse_events_);
}

double CompilerDispatcherTracer::EstimateParseInMs(size_t source_length) const {
  base::LockGuard<base::Mutex> lock(&mutex_);
  return Estimate(parse_events_, source_length);
}

double CompilerDispatcherTracer::EstimateFinalizeParsingInMs() const {
  base::LockGuard<base::Mutex> lock(&mutex_);
  return Average(finalize_parsing_events_);
}

double CompilerDispatcherTracer::EstimatePrepareToCompileInMs() const {
  base::LockGuard<base::Mutex> lock(&mutex_);
  return Average(prepare_compile_events_);
}

double CompilerDispatcherTracer::EstimateCompileInMs(
    size_t ast_size_in_bytes) const {
  base::LockGuard<base::Mutex> lock(&mutex_);
  return Estimate(compile_events_, ast_size_in_bytes);
}

double CompilerDispatcherTracer::EstimateFinalizeCompilingInMs() const {
  base::LockGuard<base::Mutex> lock(&mutex_);
  return Average(finalize_compiling_events_);
}

double CompilerDispatcherTracer::Average(
    const base::RingBuffer<double>& buffer) {
  if (buffer.Count() == 0) return 0.0;
  double sum = buffer.Sum([](double a, double b) { return a + b; }, 0.0);
  return sum / buffer.Count();
}

double CompilerDispatcherTracer::Estimate(
    const base::RingBuffer<std::pair<size_t, double>>& buffer, size_t num) {
  if (buffer.Count() == 0) return kEstimatedRuntimeWithoutData;
  std::pair<size_t, double> sum = buffer.Sum(
      [](std::pair<size_t, double> a, std::pair<size_t, double> b) {
        return std::make_pair(a.first + b.first, a.second + b.second);
      },
      std::make_pair(0, 0.0));
  return num * (sum.second / sum.first);
}

}  // namespace internal
}  // namespace v8
