// 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 "src/diagnostics/basic-block-profiler.h"

#include <algorithm>
#include <numeric>
#include <sstream>

#include "src/base/lazy-instance.h"

namespace v8 {
namespace internal {

DEFINE_LAZY_LEAKY_OBJECT_GETTER(BasicBlockProfiler, BasicBlockProfiler::Get)

BasicBlockProfiler::Data::Data(size_t n_blocks)
    : n_blocks_(n_blocks),
      block_rpo_numbers_(n_blocks_),
      counts_(n_blocks_, 0) {}

static void InsertIntoString(std::ostringstream* os, std::string* string) {
  string->insert(0, os->str());
}

static void InsertIntoString(const char* data, std::string* string) {
  string->insert(0, data);
}

void BasicBlockProfiler::Data::SetCode(std::ostringstream* os) {
  InsertIntoString(os, &code_);
}

void BasicBlockProfiler::Data::SetFunctionName(std::unique_ptr<char[]> name) {
  InsertIntoString(name.get(), &function_name_);
}

void BasicBlockProfiler::Data::SetSchedule(std::ostringstream* os) {
  InsertIntoString(os, &schedule_);
}

void BasicBlockProfiler::Data::SetBlockRpoNumber(size_t offset,
                                                 int32_t block_rpo) {
  DCHECK(offset < n_blocks_);
  block_rpo_numbers_[offset] = block_rpo;
}

intptr_t BasicBlockProfiler::Data::GetCounterAddress(size_t offset) {
  DCHECK(offset < n_blocks_);
  return reinterpret_cast<intptr_t>(&(counts_[offset]));
}

void BasicBlockProfiler::Data::ResetCounts() {
  for (size_t i = 0; i < n_blocks_; ++i) {
    counts_[i] = 0;
  }
}

BasicBlockProfiler::Data* BasicBlockProfiler::NewData(size_t n_blocks) {
  base::MutexGuard lock(&data_list_mutex_);
  Data* data = new Data(n_blocks);
  data_list_.push_back(data);
  return data;
}

BasicBlockProfiler::~BasicBlockProfiler() {
  for (DataList::iterator i = data_list_.begin(); i != data_list_.end(); ++i) {
    delete (*i);
  }
}

void BasicBlockProfiler::ResetCounts() {
  for (DataList::iterator i = data_list_.begin(); i != data_list_.end(); ++i) {
    (*i)->ResetCounts();
  }
}

std::ostream& operator<<(std::ostream& os, const BasicBlockProfiler& p) {
  os << "---- Start Profiling Data ----" << std::endl;
  using iterator = BasicBlockProfiler::DataList::const_iterator;
  for (iterator i = p.data_list_.begin(); i != p.data_list_.end(); ++i) {
    os << **i;
  }
  os << "---- End Profiling Data ----" << std::endl;
  return os;
}

std::ostream& operator<<(std::ostream& os, const BasicBlockProfiler::Data& d) {
  int block_count_sum = std::accumulate(d.counts_.begin(), d.counts_.end(), 0);
  if (block_count_sum == 0) return os;
  const char* name = "unknown function";
  if (!d.function_name_.empty()) {
    name = d.function_name_.c_str();
  }
  if (!d.schedule_.empty()) {
    os << "schedule for " << name << " (B0 entered " << d.counts_[0]
       << " times)" << std::endl;
    os << d.schedule_.c_str() << std::endl;
  }
  os << "block counts for " << name << ":" << std::endl;
  std::vector<std::pair<int32_t, uint32_t>> pairs;
  pairs.reserve(d.n_blocks_);
  for (size_t i = 0; i < d.n_blocks_; ++i) {
    pairs.push_back(std::make_pair(d.block_rpo_numbers_[i], d.counts_[i]));
  }
  std::sort(pairs.begin(), pairs.end(),
            [=](std::pair<int32_t, uint32_t> left,
                std::pair<int32_t, uint32_t> right) {
              if (right.second == left.second) return left.first < right.first;
              return right.second < left.second;
            });
  for (auto it : pairs) {
    if (it.second == 0) break;
    os << "block B" << it.first << " : " << it.second << std::endl;
  }
  os << std::endl;
  if (!d.code_.empty()) {
    os << d.code_.c_str() << std::endl;
  }
  return os;
}

}  // namespace internal
}  // namespace v8
