// 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 <ostream>  // NOLINT(readability/streams)
#include <vector>

#include "src/base/platform/platform.h"
#include "src/diagnostics/compilation-statistics.h"

namespace v8 {
namespace internal {

void CompilationStatistics::RecordPhaseStats(const char* phase_kind_name,
                                             const char* phase_name,
                                             const BasicStats& stats) {
  base::MutexGuard guard(&record_mutex_);

  std::string phase_name_str(phase_name);
  auto it = phase_map_.find(phase_name_str);
  if (it == phase_map_.end()) {
    PhaseStats phase_stats(phase_map_.size(), phase_kind_name);
    it = phase_map_.insert(std::make_pair(phase_name_str, phase_stats)).first;
  }
  it->second.Accumulate(stats);
}

void CompilationStatistics::RecordPhaseKindStats(const char* phase_kind_name,
                                                 const BasicStats& stats) {
  base::MutexGuard guard(&record_mutex_);

  std::string phase_kind_name_str(phase_kind_name);
  auto it = phase_kind_map_.find(phase_kind_name_str);
  if (it == phase_kind_map_.end()) {
    PhaseKindStats phase_kind_stats(phase_kind_map_.size());
    it = phase_kind_map_
             .insert(std::make_pair(phase_kind_name_str, phase_kind_stats))
             .first;
  }
  it->second.Accumulate(stats);
}

void CompilationStatistics::RecordTotalStats(const BasicStats& stats) {
  base::MutexGuard guard(&record_mutex_);
  total_stats_.Accumulate(stats);
}

void CompilationStatistics::BasicStats::Accumulate(const BasicStats& stats) {
  delta_ += stats.delta_;
  total_allocated_bytes_ += stats.total_allocated_bytes_;
  if (stats.absolute_max_allocated_bytes_ > absolute_max_allocated_bytes_) {
    absolute_max_allocated_bytes_ = stats.absolute_max_allocated_bytes_;
    max_allocated_bytes_ = stats.max_allocated_bytes_;
    function_name_ = stats.function_name_;
  }
}

static void WriteLine(std::ostream& os, bool machine_format, const char* name,
                      const CompilationStatistics::BasicStats& stats,
                      const CompilationStatistics::BasicStats& total_stats) {
  const size_t kBufferSize = 128;
  char buffer[kBufferSize];

  double ms = stats.delta_.InMillisecondsF();
  double percent = stats.delta_.PercentOf(total_stats.delta_);
  double size_percent =
      static_cast<double>(stats.total_allocated_bytes_ * 100) /
      static_cast<double>(total_stats.total_allocated_bytes_);
  if (machine_format) {
    base::OS::SNPrintF(buffer, kBufferSize,
                       "\"%s_time\"=%.3f\n\"%s_space\"=%zu", name, ms, name,
                       stats.total_allocated_bytes_);
    os << buffer;
  } else {
    base::OS::SNPrintF(buffer, kBufferSize,
                       "%34s %10.3f (%5.1f%%)  %10zu (%5.1f%%) %10zu %10zu",
                       name, ms, percent, stats.total_allocated_bytes_,
                       size_percent, stats.max_allocated_bytes_,
                       stats.absolute_max_allocated_bytes_);

    os << buffer;
    if (!stats.function_name_.empty()) {
      os << "   " << stats.function_name_.c_str();
    }
    os << std::endl;
  }
}

static void WriteFullLine(std::ostream& os) {
  os << "-----------------------------------------------------------"
        "-----------------------------------------------------------\n";
}

static void WriteHeader(std::ostream& os) {
  WriteFullLine(os);
  os << "                Turbofan phase            Time (ms)    "
     << "                   Space (bytes)             Function\n"
     << "                                                       "
     << "          Total          Max.     Abs. max.\n";
  WriteFullLine(os);
}

static void WritePhaseKindBreak(std::ostream& os) {
  os << "                                   ------------------------"
        "-----------------------------------------------------------\n";
}

std::ostream& operator<<(std::ostream& os, const AsPrintableStatistics& ps) {
  // phase_kind_map_ and phase_map_ don't get mutated, so store a bunch of
  // pointers into them.
  const CompilationStatistics& s = ps.s;

  using SortedPhaseKinds =
      std::vector<CompilationStatistics::PhaseKindMap::const_iterator>;
  SortedPhaseKinds sorted_phase_kinds(s.phase_kind_map_.size());
  for (auto it = s.phase_kind_map_.begin(); it != s.phase_kind_map_.end();
       ++it) {
    sorted_phase_kinds[it->second.insert_order_] = it;
  }

  using SortedPhases =
      std::vector<CompilationStatistics::PhaseMap::const_iterator>;
  SortedPhases sorted_phases(s.phase_map_.size());
  for (auto it = s.phase_map_.begin(); it != s.phase_map_.end(); ++it) {
    sorted_phases[it->second.insert_order_] = it;
  }

  if (!ps.machine_output) WriteHeader(os);
  for (const auto& phase_kind_it : sorted_phase_kinds) {
    const auto& phase_kind_name = phase_kind_it->first;
    if (!ps.machine_output) {
      for (const auto& phase_it : sorted_phases) {
        const auto& phase_stats = phase_it->second;
        if (phase_stats.phase_kind_name_ != phase_kind_name) continue;
        const auto& phase_name = phase_it->first;
        WriteLine(os, ps.machine_output, phase_name.c_str(), phase_stats,
                  s.total_stats_);
      }
      WritePhaseKindBreak(os);
    }
    const auto& phase_kind_stats = phase_kind_it->second;
    WriteLine(os, ps.machine_output, phase_kind_name.c_str(), phase_kind_stats,
              s.total_stats_);
    os << std::endl;
  }

  if (!ps.machine_output) WriteFullLine(os);
  WriteLine(os, ps.machine_output, "totals", s.total_stats_, s.total_stats_);

  return os;
}

}  // namespace internal
}  // namespace v8
