// 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) {
  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(size_t source_size,
                                             const BasicStats& stats) {
  base::MutexGuard guard(&record_mutex_);

  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,
        "%34s %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_.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;

  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 (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
