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

namespace v8 {
namespace internal {

void CompilationStatistics::RecordPhaseStats(const char* phase_kind_name,
                                             const char* phase_name,
                                             const BasicStats& stats) {
  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) {
  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(size_t source_size,
                                             const BasicStats& stats) {
  source_size += source_size;
  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, 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_);
  base::OS::SNPrintF(buffer, kBufferSize, "%28s %10.3f (%5.1f%%)  %10" PRIuS
                                          " (%5.1f%%) %10" PRIuS " %10" PRIuS,
                     name, ms, percent, stats.total_allocated_bytes_,
                     size_percent, stats.max_allocated_bytes_,
                     stats.absolute_max_allocated_bytes_);

  os << buffer;
  if (stats.function_name_.size() > 0) {
    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 << "             Turbonfan 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 CompilationStatistics& s) {
  // phase_kind_map_ and phase_map_ don't get mutated, so store a bunch of
  // pointers into them.

  typedef std::vector<CompilationStatistics::PhaseKindMap::const_iterator>
      SortedPhaseKinds;
  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;
  }

  typedef std::vector<CompilationStatistics::PhaseMap::const_iterator>
      SortedPhases;
  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;
  }

  WriteHeader(os);
  for (auto phase_kind_it : sorted_phase_kinds) {
    const auto& phase_kind_name = phase_kind_it->first;
    for (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, phase_name.c_str(), phase_stats, s.total_stats_);
    }
    WritePhaseKindBreak(os);
    const auto& phase_kind_stats = phase_kind_it->second;
    WriteLine(os, phase_kind_name.c_str(), phase_kind_stats, s.total_stats_);
    os << std::endl;
  }
  WriteFullLine(os);
  WriteLine(os, "totals", s.total_stats_, s.total_stats_);

  return os;
}

}  // namespace internal
}  // namespace v8
