// Copyright 2016 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/ic/ic-stats.h"

#include "src/init/v8.h"
#include "src/logging/counters.h"
#include "src/objects/objects-inl.h"
#include "src/tracing/trace-event.h"
#include "src/tracing/traced-value.h"

namespace v8 {
namespace internal {

base::LazyInstance<ICStats>::type ICStats::instance_ =
    LAZY_INSTANCE_INITIALIZER;

ICStats::ICStats() : ic_infos_(MAX_IC_INFO), pos_(0) {
  base::Relaxed_Store(&enabled_, 0);
}

void ICStats::Begin() {
  if (V8_LIKELY(!TracingFlags::is_ic_stats_enabled())) return;
  base::Relaxed_Store(&enabled_, 1);
}

void ICStats::End() {
  if (base::Relaxed_Load(&enabled_) != 1) return;
  ++pos_;
  if (pos_ == MAX_IC_INFO) {
    Dump();
  }
  base::Relaxed_Store(&enabled_, 0);
}

void ICStats::Reset() {
  for (auto ic_info : ic_infos_) {
    ic_info.Reset();
  }
  pos_ = 0;
}

void ICStats::Dump() {
  auto value = v8::tracing::TracedValue::Create();
  value->BeginArray("data");
  for (int i = 0; i < pos_; ++i) {
    ic_infos_[i].AppendToTracedValue(value.get());
  }
  value->EndArray();

  TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("v8.ic_stats"), "V8.ICStats",
                       TRACE_EVENT_SCOPE_THREAD, "ic-stats", std::move(value));
  Reset();
}

const char* ICStats::GetOrCacheScriptName(Script script) {
  Address script_ptr = script.ptr();
  if (script_name_map_.find(script_ptr) != script_name_map_.end()) {
    return script_name_map_[script_ptr].get();
  }
  Object script_name_raw = script.name();
  if (script_name_raw.IsString()) {
    String script_name = String::cast(script_name_raw);
    char* c_script_name =
        script_name.ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL)
            .release();
    script_name_map_.insert(
        std::make_pair(script_ptr, std::unique_ptr<char[]>(c_script_name)));
    return c_script_name;
  } else {
    script_name_map_.insert(
        std::make_pair(script_ptr, std::unique_ptr<char[]>(nullptr)));
    return nullptr;
  }
  return nullptr;
}

const char* ICStats::GetOrCacheFunctionName(JSFunction function) {
  Address function_ptr = function.ptr();
  if (function_name_map_.find(function_ptr) != function_name_map_.end()) {
    return function_name_map_[function_ptr].get();
  }
  SharedFunctionInfo shared = function.shared();
  ic_infos_[pos_].is_optimized = function.IsOptimized();
  char* function_name = shared.DebugName().ToCString().release();
  function_name_map_.insert(
      std::make_pair(function_ptr, std::unique_ptr<char[]>(function_name)));
  return function_name;
}

ICInfo::ICInfo()
    : function_name(nullptr),
      script_offset(0),
      script_name(nullptr),
      line_num(-1),
      is_constructor(false),
      is_optimized(false),
      map(nullptr),
      is_dictionary_map(false),
      number_of_own_descriptors(0) {}

void ICInfo::Reset() {
  type.clear();
  function_name = nullptr;
  script_offset = 0;
  script_name = nullptr;
  line_num = -1;
  is_constructor = false;
  is_optimized = false;
  state.clear();
  map = nullptr;
  is_dictionary_map = false;
  number_of_own_descriptors = 0;
  instance_type.clear();
}

void ICInfo::AppendToTracedValue(v8::tracing::TracedValue* value) const {
  value->BeginDictionary();
  value->SetString("type", type);
  if (function_name) {
    value->SetString("functionName", function_name);
    if (is_optimized) {
      value->SetInteger("optimized", is_optimized);
    }
  }
  if (script_offset) value->SetInteger("offset", script_offset);
  if (script_name) value->SetString("scriptName", script_name);
  if (line_num != -1) value->SetInteger("lineNum", line_num);
  if (is_constructor) value->SetInteger("constructor", is_constructor);
  if (!state.empty()) value->SetString("state", state);
  if (map) {
    // V8 cannot represent integer above 2^53 - 1 in JavaScript from JSON,
    // thus `map` should be converted to a string rather than an integer.
    std::stringstream ss;
    ss << map;
    value->SetString("map", ss.str());
  }
  if (map) value->SetInteger("dict", is_dictionary_map);
  if (map) value->SetInteger("own", number_of_own_descriptors);
  if (!instance_type.empty()) value->SetString("instanceType", instance_type);
  value->EndDictionary();
}

}  // namespace internal
}  // namespace v8
