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