// 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 ms / %5.1f %%"
                     "%10u total / %5.1f %% "
                     "%10u max %10u abs_max",
                     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 << "                             Turbofan timing results:\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
