OLD | NEW |
---|---|
(Empty) | |
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 ICStats::ICStats() : ic_infos_(MAX_IC_INFO), pos_(0) { | |
20 base::NoBarrier_Store(&being_used_, 0); | |
21 } | |
22 | |
23 void ICStats::Begin() { | |
24 if (V8_LIKELY(!FLAG_ic_stats)) return; | |
25 base::NoBarrier_Store(&being_used_, 1); | |
26 } | |
27 | |
28 void ICStats::End() { | |
29 if (base::NoBarrier_Load(&being_used_) != 1) return; | |
30 ++pos_; | |
31 if (pos_ == MAX_IC_INFO) { | |
32 Dump(); | |
33 } | |
34 base::NoBarrier_Store(&being_used_, 0); | |
35 } | |
36 | |
37 void ICStats::Reset() { | |
38 for (auto ic_info : ic_infos_) { | |
39 ic_info.Reset(); | |
40 } | |
41 pos_ = 0; | |
42 } | |
43 | |
44 void ICStats::Dump() { | |
45 auto value = v8::tracing::TracedValue::Create(); | |
46 value->BeginArray("data"); | |
47 for (int i = 0; i < pos_; ++i) { | |
48 ic_infos_[i].AppendToTracedValue(value.get()); | |
49 } | |
50 value->EndArray(); | |
51 | |
52 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("v8.ic_stats"), "V8.ICStats", | |
53 TRACE_EVENT_SCOPE_THREAD, "ic-stats", std::move(value)); | |
54 Reset(); | |
55 } | |
56 | |
57 const char* ICStats::GetOrCacheScriptName(Object* obj) { | |
58 if (script_name_map_.find(obj) != script_name_map_.end()) { | |
59 return script_name_map_[obj].get(); | |
60 } | |
61 Script* script = Script::cast(obj); | |
62 Object* script_name_raw = script->name(); | |
63 if (script_name_raw->IsString()) { | |
64 String* script_name = String::cast(script->name()); | |
Camillo Bruni
2016/12/02 12:12:55
String::cast(script_name_raw);
lpy
2016/12/05 17:49:10
Done.
| |
65 char* c_script_name = | |
66 script_name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL) | |
67 .release(); | |
68 script_name_map_.insert( | |
69 std::make_pair(obj, std::unique_ptr<char[]>(c_script_name))); | |
70 return c_script_name; | |
71 } else { | |
72 script_name_map_.insert( | |
73 std::make_pair(obj, std::unique_ptr<char[]>(nullptr))); | |
74 return nullptr; | |
75 } | |
76 return nullptr; | |
77 } | |
78 | |
79 std::string& ICStats::GetOrCacheFunctionName(JSFunction* function) { | |
80 if (function_name_map_.find(function) != function_name_map_.end()) { | |
81 return function_name_map_[function]; | |
82 } | |
83 SharedFunctionInfo* shared = function->shared(); | |
84 std::string function_name = function->IsOptimized() ? "*" : "~"; | |
Camillo Bruni
2016/12/02 12:12:55
that might be another boolean that could be put no
lpy
2016/12/05 17:49:10
Done.
| |
85 function_name += shared->DebugName()->ToCString().get(); | |
86 function_name_map_.insert(std::make_pair(function, function_name)); | |
87 return function_name_map_[function]; | |
Camillo Bruni
2016/12/02 12:12:55
return function_name;
lpy
2016/12/05 17:49:10
Done.
| |
88 } | |
89 | |
90 ICInfo::ICInfo() | |
91 : offset(0), | |
92 script_name(nullptr), | |
93 line_num(-1), | |
94 constructor(0), | |
95 map(nullptr), | |
96 dict(0), | |
97 own(0) {} | |
98 | |
99 void ICInfo::Reset() { | |
100 type.clear(); | |
101 function_name.clear(); | |
102 offset = 0; | |
103 script_name = nullptr; | |
104 line_num = -1; | |
105 constructor = 0; | |
106 state.clear(); | |
107 map = nullptr; | |
108 dict = 0; | |
109 own = 0; | |
110 instance_type.clear(); | |
111 } | |
112 | |
113 void ICInfo::AppendToTracedValue(v8::tracing::TracedValue* value) const { | |
114 value->BeginDictionary(); | |
115 value->SetString("type", type); | |
116 if (!function_name.empty()) { | |
117 value->SetString("functionName", function_name); | |
118 } | |
119 if (offset) value->SetInteger("offset", offset); | |
120 if (script_name) value->SetString("scriptName", script_name); | |
121 if (line_num != -1) value->SetInteger("lineNum", line_num); | |
122 if (constructor) value->SetInteger("constructor", constructor); | |
123 if (!state.empty()) value->SetString("state", state); | |
124 // TODO(lpy) Find a better solution rather than stringstream. | |
125 if (map) { | |
126 std::stringstream ss; | |
127 ss << map; | |
128 value->SetString("map", ss.str()); | |
Camillo Bruni
2016/12/02 12:12:55
Can't you just use SetInteger and reinterpet_cast
lpy
2016/12/05 17:49:10
Done.
| |
129 } | |
130 if (map) value->SetInteger("dict", dict); | |
131 if (map) value->SetInteger("own", own); | |
132 if (!instance_type.empty()) value->SetString("instanceType", instance_type); | |
133 value->EndDictionary(); | |
134 } | |
135 | |
136 } // namespace internal | |
137 } // namespace v8 | |
OLD | NEW |