Line data Source code
1 : // Copyright 2016 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/ic/ic-stats.h"
6 :
7 : #include "src/flags.h"
8 : #include "src/objects-inl.h"
9 : #include "src/tracing/trace-event.h"
10 : #include "src/tracing/traced-value.h"
11 : #include "src/v8.h"
12 :
13 : namespace v8 {
14 : namespace internal {
15 :
16 : base::LazyInstance<ICStats>::type ICStats::instance_ =
17 : LAZY_INSTANCE_INITIALIZER;
18 :
19 0 : ICStats::ICStats() : ic_infos_(MAX_IC_INFO), pos_(0) {
20 0 : base::Relaxed_Store(&enabled_, 0);
21 0 : }
22 :
23 0 : void ICStats::Begin() {
24 0 : if (V8_LIKELY(!FLAG_ic_stats)) return;
25 0 : base::Relaxed_Store(&enabled_, 1);
26 : }
27 :
28 0 : void ICStats::End() {
29 0 : if (base::Relaxed_Load(&enabled_) != 1) return;
30 0 : ++pos_;
31 0 : if (pos_ == MAX_IC_INFO) {
32 0 : Dump();
33 : }
34 : base::Relaxed_Store(&enabled_, 0);
35 : }
36 :
37 0 : void ICStats::Reset() {
38 0 : for (auto ic_info : ic_infos_) {
39 0 : ic_info.Reset();
40 0 : }
41 0 : pos_ = 0;
42 0 : }
43 :
44 0 : void ICStats::Dump() {
45 0 : auto value = v8::tracing::TracedValue::Create();
46 0 : value->BeginArray("data");
47 0 : for (int i = 0; i < pos_; ++i) {
48 0 : ic_infos_[i].AppendToTracedValue(value.get());
49 : }
50 0 : value->EndArray();
51 :
52 0 : TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("v8.ic_stats"), "V8.ICStats",
53 : TRACE_EVENT_SCOPE_THREAD, "ic-stats", std::move(value));
54 0 : Reset();
55 0 : }
56 :
57 0 : const char* ICStats::GetOrCacheScriptName(Script script) {
58 0 : Address script_ptr = script.ptr();
59 0 : if (script_name_map_.find(script_ptr) != script_name_map_.end()) {
60 0 : return script_name_map_[script_ptr].get();
61 : }
62 0 : Object script_name_raw = script->name();
63 0 : if (script_name_raw->IsString()) {
64 0 : String script_name = String::cast(script_name_raw);
65 : char* c_script_name =
66 : script_name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL)
67 0 : .release();
68 : script_name_map_.insert(
69 0 : std::make_pair(script_ptr, std::unique_ptr<char[]>(c_script_name)));
70 : return c_script_name;
71 : } else {
72 : script_name_map_.insert(
73 0 : std::make_pair(script_ptr, std::unique_ptr<char[]>(nullptr)));
74 0 : return nullptr;
75 : }
76 : return nullptr;
77 : }
78 :
79 0 : const char* ICStats::GetOrCacheFunctionName(JSFunction function) {
80 0 : Address function_ptr = function.ptr();
81 0 : if (function_name_map_.find(function_ptr) != function_name_map_.end()) {
82 0 : return function_name_map_[function_ptr].get();
83 : }
84 0 : SharedFunctionInfo shared = function->shared();
85 0 : ic_infos_[pos_].is_optimized = function->IsOptimized();
86 0 : char* function_name = shared->DebugName()->ToCString().release();
87 : function_name_map_.insert(
88 0 : std::make_pair(function_ptr, std::unique_ptr<char[]>(function_name)));
89 0 : return function_name;
90 : }
91 :
92 0 : ICInfo::ICInfo()
93 : : function_name(nullptr),
94 : script_offset(0),
95 : script_name(nullptr),
96 : line_num(-1),
97 : is_constructor(false),
98 : is_optimized(false),
99 : map(nullptr),
100 : is_dictionary_map(false),
101 0 : number_of_own_descriptors(0) {}
102 :
103 0 : void ICInfo::Reset() {
104 0 : type.clear();
105 0 : function_name = nullptr;
106 0 : script_offset = 0;
107 0 : script_name = nullptr;
108 0 : line_num = -1;
109 0 : is_constructor = false;
110 0 : is_optimized = false;
111 0 : state.clear();
112 0 : map = nullptr;
113 0 : is_dictionary_map = false;
114 0 : number_of_own_descriptors = 0;
115 0 : instance_type.clear();
116 0 : }
117 :
118 0 : void ICInfo::AppendToTracedValue(v8::tracing::TracedValue* value) const {
119 0 : value->BeginDictionary();
120 : value->SetString("type", type);
121 0 : if (function_name) {
122 0 : value->SetString("functionName", function_name);
123 0 : if (is_optimized) {
124 0 : value->SetInteger("optimized", is_optimized);
125 : }
126 : }
127 0 : if (script_offset) value->SetInteger("offset", script_offset);
128 0 : if (script_name) value->SetString("scriptName", script_name);
129 0 : if (line_num != -1) value->SetInteger("lineNum", line_num);
130 0 : if (is_constructor) value->SetInteger("constructor", is_constructor);
131 0 : if (!state.empty()) value->SetString("state", state);
132 0 : if (map) {
133 : // V8 cannot represent integer above 2^53 - 1 in JavaScript from JSON,
134 : // thus `map` should be converted to a string rather than an integer.
135 0 : std::stringstream ss;
136 0 : ss << map;
137 0 : value->SetString("map", ss.str());
138 : }
139 0 : if (map) value->SetInteger("dict", is_dictionary_map);
140 0 : if (map) value->SetInteger("own", number_of_own_descriptors);
141 0 : if (!instance_type.empty()) value->SetString("instanceType", instance_type);
142 0 : value->EndDictionary();
143 0 : }
144 :
145 : } // namespace internal
146 178779 : } // namespace v8
|