// 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, 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\"=%" PRIuS, name, ms, name,
                       stats.total_allocated_bytes_);
    os << buffer;
  } else {
    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 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;

  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;
  }

  if (!ps.machine_output) WriteHeader(os);
  for (auto phase_kind_it : sorted_phase_kinds) {
    const auto& phase_kind_name = phase_kind_it->first;
    if (!ps.machine_output) {
      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, 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
