11cb0ef41Sopenharmony_ci// Copyright 2016 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/ic/ic-stats.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include "src/init/v8.h"
81cb0ef41Sopenharmony_ci#include "src/logging/counters.h"
91cb0ef41Sopenharmony_ci#include "src/objects/objects-inl.h"
101cb0ef41Sopenharmony_ci#include "src/tracing/trace-event.h"
111cb0ef41Sopenharmony_ci#include "src/tracing/traced-value.h"
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_cinamespace v8 {
141cb0ef41Sopenharmony_cinamespace internal {
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_cibase::LazyInstance<ICStats>::type ICStats::instance_ =
171cb0ef41Sopenharmony_ci    LAZY_INSTANCE_INITIALIZER;
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_ciICStats::ICStats() : ic_infos_(MAX_IC_INFO), pos_(0) {
201cb0ef41Sopenharmony_ci  base::Relaxed_Store(&enabled_, 0);
211cb0ef41Sopenharmony_ci}
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_civoid ICStats::Begin() {
241cb0ef41Sopenharmony_ci  if (V8_LIKELY(!TracingFlags::is_ic_stats_enabled())) return;
251cb0ef41Sopenharmony_ci  base::Relaxed_Store(&enabled_, 1);
261cb0ef41Sopenharmony_ci}
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_civoid ICStats::End() {
291cb0ef41Sopenharmony_ci  if (base::Relaxed_Load(&enabled_) != 1) return;
301cb0ef41Sopenharmony_ci  ++pos_;
311cb0ef41Sopenharmony_ci  if (pos_ == MAX_IC_INFO) {
321cb0ef41Sopenharmony_ci    Dump();
331cb0ef41Sopenharmony_ci  }
341cb0ef41Sopenharmony_ci  base::Relaxed_Store(&enabled_, 0);
351cb0ef41Sopenharmony_ci}
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_civoid ICStats::Reset() {
381cb0ef41Sopenharmony_ci  for (auto ic_info : ic_infos_) {
391cb0ef41Sopenharmony_ci    ic_info.Reset();
401cb0ef41Sopenharmony_ci  }
411cb0ef41Sopenharmony_ci  pos_ = 0;
421cb0ef41Sopenharmony_ci}
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_civoid ICStats::Dump() {
451cb0ef41Sopenharmony_ci  auto value = v8::tracing::TracedValue::Create();
461cb0ef41Sopenharmony_ci  value->BeginArray("data");
471cb0ef41Sopenharmony_ci  for (int i = 0; i < pos_; ++i) {
481cb0ef41Sopenharmony_ci    ic_infos_[i].AppendToTracedValue(value.get());
491cb0ef41Sopenharmony_ci  }
501cb0ef41Sopenharmony_ci  value->EndArray();
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci  TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("v8.ic_stats"), "V8.ICStats",
531cb0ef41Sopenharmony_ci                       TRACE_EVENT_SCOPE_THREAD, "ic-stats", std::move(value));
541cb0ef41Sopenharmony_ci  Reset();
551cb0ef41Sopenharmony_ci}
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ciconst char* ICStats::GetOrCacheScriptName(Script script) {
581cb0ef41Sopenharmony_ci  Address script_ptr = script.ptr();
591cb0ef41Sopenharmony_ci  if (script_name_map_.find(script_ptr) != script_name_map_.end()) {
601cb0ef41Sopenharmony_ci    return script_name_map_[script_ptr].get();
611cb0ef41Sopenharmony_ci  }
621cb0ef41Sopenharmony_ci  Object script_name_raw = script.name();
631cb0ef41Sopenharmony_ci  if (script_name_raw.IsString()) {
641cb0ef41Sopenharmony_ci    String script_name = String::cast(script_name_raw);
651cb0ef41Sopenharmony_ci    char* c_script_name =
661cb0ef41Sopenharmony_ci        script_name.ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL)
671cb0ef41Sopenharmony_ci            .release();
681cb0ef41Sopenharmony_ci    script_name_map_.insert(
691cb0ef41Sopenharmony_ci        std::make_pair(script_ptr, std::unique_ptr<char[]>(c_script_name)));
701cb0ef41Sopenharmony_ci    return c_script_name;
711cb0ef41Sopenharmony_ci  }
721cb0ef41Sopenharmony_ci  script_name_map_.insert(
731cb0ef41Sopenharmony_ci      std::make_pair(script_ptr, std::unique_ptr<char[]>(nullptr)));
741cb0ef41Sopenharmony_ci  return nullptr;
751cb0ef41Sopenharmony_ci}
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ciconst char* ICStats::GetOrCacheFunctionName(JSFunction function) {
781cb0ef41Sopenharmony_ci  Address function_ptr = function.ptr();
791cb0ef41Sopenharmony_ci  // Lookup the function name or add a null unique_ptr if no entry exists.
801cb0ef41Sopenharmony_ci  std::unique_ptr<char[]>& function_name = function_name_map_[function_ptr];
811cb0ef41Sopenharmony_ci  if (!function_name) {
821cb0ef41Sopenharmony_ci    ic_infos_[pos_].is_optimized = function.HasAttachedOptimizedCode();
831cb0ef41Sopenharmony_ci    // Update the map entry with the actual debug name.
841cb0ef41Sopenharmony_ci    function_name = function.shared().DebugNameCStr();
851cb0ef41Sopenharmony_ci  }
861cb0ef41Sopenharmony_ci  return function_name.get();
871cb0ef41Sopenharmony_ci}
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ciICInfo::ICInfo()
901cb0ef41Sopenharmony_ci    : function_name(nullptr),
911cb0ef41Sopenharmony_ci      script_offset(0),
921cb0ef41Sopenharmony_ci      script_name(nullptr),
931cb0ef41Sopenharmony_ci      line_num(-1),
941cb0ef41Sopenharmony_ci      column_num(-1),
951cb0ef41Sopenharmony_ci      is_constructor(false),
961cb0ef41Sopenharmony_ci      is_optimized(false),
971cb0ef41Sopenharmony_ci      map(nullptr),
981cb0ef41Sopenharmony_ci      is_dictionary_map(false),
991cb0ef41Sopenharmony_ci      number_of_own_descriptors(0) {}
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_civoid ICInfo::Reset() {
1021cb0ef41Sopenharmony_ci  type.clear();
1031cb0ef41Sopenharmony_ci  function_name = nullptr;
1041cb0ef41Sopenharmony_ci  script_offset = 0;
1051cb0ef41Sopenharmony_ci  script_name = nullptr;
1061cb0ef41Sopenharmony_ci  line_num = -1;
1071cb0ef41Sopenharmony_ci  column_num = -1;
1081cb0ef41Sopenharmony_ci  is_constructor = false;
1091cb0ef41Sopenharmony_ci  is_optimized = false;
1101cb0ef41Sopenharmony_ci  state.clear();
1111cb0ef41Sopenharmony_ci  map = nullptr;
1121cb0ef41Sopenharmony_ci  is_dictionary_map = false;
1131cb0ef41Sopenharmony_ci  number_of_own_descriptors = 0;
1141cb0ef41Sopenharmony_ci  instance_type.clear();
1151cb0ef41Sopenharmony_ci}
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_civoid ICInfo::AppendToTracedValue(v8::tracing::TracedValue* value) const {
1181cb0ef41Sopenharmony_ci  value->BeginDictionary();
1191cb0ef41Sopenharmony_ci  value->SetString("type", type);
1201cb0ef41Sopenharmony_ci  if (function_name) {
1211cb0ef41Sopenharmony_ci    value->SetString("functionName", function_name);
1221cb0ef41Sopenharmony_ci    if (is_optimized) {
1231cb0ef41Sopenharmony_ci      value->SetInteger("optimized", is_optimized);
1241cb0ef41Sopenharmony_ci    }
1251cb0ef41Sopenharmony_ci  }
1261cb0ef41Sopenharmony_ci  if (script_offset) value->SetInteger("offset", script_offset);
1271cb0ef41Sopenharmony_ci  if (script_name) value->SetString("scriptName", script_name);
1281cb0ef41Sopenharmony_ci  if (line_num != -1) value->SetInteger("lineNum", line_num);
1291cb0ef41Sopenharmony_ci  if (column_num != -1) value->SetInteger("columnNum", column_num);
1301cb0ef41Sopenharmony_ci  if (is_constructor) value->SetInteger("constructor", is_constructor);
1311cb0ef41Sopenharmony_ci  if (!state.empty()) value->SetString("state", state);
1321cb0ef41Sopenharmony_ci  if (map) {
1331cb0ef41Sopenharmony_ci    // V8 cannot represent integer above 2^53 - 1 in JavaScript from JSON,
1341cb0ef41Sopenharmony_ci    // thus `map` should be converted to a string rather than an integer.
1351cb0ef41Sopenharmony_ci    std::stringstream ss;
1361cb0ef41Sopenharmony_ci    ss << map;
1371cb0ef41Sopenharmony_ci    value->SetString("map", ss.str());
1381cb0ef41Sopenharmony_ci  }
1391cb0ef41Sopenharmony_ci  if (map) value->SetInteger("dict", is_dictionary_map);
1401cb0ef41Sopenharmony_ci  if (map) value->SetInteger("own", number_of_own_descriptors);
1411cb0ef41Sopenharmony_ci  if (!instance_type.empty()) value->SetString("instanceType", instance_type);
1421cb0ef41Sopenharmony_ci  value->EndDictionary();
1431cb0ef41Sopenharmony_ci}
1441cb0ef41Sopenharmony_ci
1451cb0ef41Sopenharmony_ci}  // namespace internal
1461cb0ef41Sopenharmony_ci}  // namespace v8
147