// Copyright 2014 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 <memory>

#include "src/codegen/optimized-compilation-info.h"
#include "src/compiler/pipeline-statistics.h"
#include "src/compiler/zone-stats.h"
#include "src/objects/shared-function-info.h"
#include "src/objects/string.h"
#include "src/tracing/trace-event.h"

namespace v8 {
namespace internal {
namespace compiler {

namespace {

// We log detailed phase information about the pipeline
// in both the v8.turbofan and the v8.wasm.detailed categories.
constexpr const char kTraceCategory[] =           // --
    TRACE_DISABLED_BY_DEFAULT("v8.turbofan") ","  // --
    TRACE_DISABLED_BY_DEFAULT("v8.wasm.detailed");

}  // namespace

void PipelineStatistics::CommonStats::Begin(
    PipelineStatistics* pipeline_stats) {
  DCHECK(!scope_);
  scope_.reset(new ZoneStats::StatsScope(pipeline_stats->zone_stats_));
  timer_.Start();
  outer_zone_initial_size_ = pipeline_stats->OuterZoneSize();
  allocated_bytes_at_start_ =
      outer_zone_initial_size_ -
      pipeline_stats->total_stats_.outer_zone_initial_size_ +
      pipeline_stats->zone_stats_->GetCurrentAllocatedBytes();
}


void PipelineStatistics::CommonStats::End(
    PipelineStatistics* pipeline_stats,
    CompilationStatistics::BasicStats* diff) {
  DCHECK(scope_);
  diff->function_name_ = pipeline_stats->function_name_;
  diff->delta_ = timer_.Elapsed();
  size_t outer_zone_diff =
      pipeline_stats->OuterZoneSize() - outer_zone_initial_size_;
  diff->max_allocated_bytes_ = outer_zone_diff + scope_->GetMaxAllocatedBytes();
  diff->absolute_max_allocated_bytes_ =
      diff->max_allocated_bytes_ + allocated_bytes_at_start_;
  diff->total_allocated_bytes_ =
      outer_zone_diff + scope_->GetTotalAllocatedBytes();
  scope_.reset();
  timer_.Stop();
}

PipelineStatistics::PipelineStatistics(OptimizedCompilationInfo* info,
                                       CompilationStatistics* compilation_stats,
                                       ZoneStats* zone_stats)
    : outer_zone_(info->zone()),
      zone_stats_(zone_stats),
      compilation_stats_(compilation_stats),
      phase_kind_name_(nullptr),
      phase_name_(nullptr) {
  if (info->has_shared_info()) {
    std::unique_ptr<char[]> name = info->shared_info()->DebugName().ToCString();
    function_name_ = name.get();
  }
  total_stats_.Begin(this);
}


PipelineStatistics::~PipelineStatistics() {
  if (InPhaseKind()) EndPhaseKind();
  CompilationStatistics::BasicStats diff;
  total_stats_.End(this, &diff);
  compilation_stats_->RecordTotalStats(diff);
}


void PipelineStatistics::BeginPhaseKind(const char* phase_kind_name) {
  DCHECK(!InPhase());
  if (InPhaseKind()) EndPhaseKind();
  TRACE_EVENT_BEGIN0(kTraceCategory, phase_kind_name);
  phase_kind_name_ = phase_kind_name;
  phase_kind_stats_.Begin(this);
}

void PipelineStatistics::EndPhaseKind() {
  DCHECK(!InPhase());
  CompilationStatistics::BasicStats diff;
  phase_kind_stats_.End(this, &diff);
  compilation_stats_->RecordPhaseKindStats(phase_kind_name_, diff);
  TRACE_EVENT_END0(kTraceCategory, phase_kind_name_);
}

void PipelineStatistics::BeginPhase(const char* phase_name) {
  TRACE_EVENT_BEGIN0(kTraceCategory, phase_name);
  DCHECK(InPhaseKind());
  phase_name_ = phase_name;
  phase_stats_.Begin(this);
}

void PipelineStatistics::EndPhase() {
  DCHECK(InPhaseKind());
  CompilationStatistics::BasicStats diff;
  phase_stats_.End(this, &diff);
  compilation_stats_->RecordPhaseStats(phase_kind_name_, phase_name_, diff);
  TRACE_EVENT_END0(kTraceCategory, phase_name_);
}

}  // namespace compiler
}  // namespace internal
}  // namespace v8
