Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: src/profile-generator.h

Issue 424973004: Extend CPU profiler with mapping ticks to source lines (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed comments Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef V8_PROFILE_GENERATOR_H_ 5 #ifndef V8_PROFILE_GENERATOR_H_
6 #define V8_PROFILE_GENERATOR_H_ 6 #define V8_PROFILE_GENERATOR_H_
7 7
8 #include <map>
8 #include "include/v8-profiler.h" 9 #include "include/v8-profiler.h"
9 #include "src/allocation.h" 10 #include "src/allocation.h"
10 #include "src/hashmap.h" 11 #include "src/hashmap.h"
11 12
12 namespace v8 { 13 namespace v8 {
13 namespace internal { 14 namespace internal {
14 15
15 struct OffsetRange; 16 struct OffsetRange;
16 17
17 // Provides a storage of strings allocated in C++ heap, to hold them 18 // Provides a storage of strings allocated in C++ heap, to hold them
(...skipping 20 matching lines...) Expand all
38 const char* AddOrDisposeString(char* str, int len); 39 const char* AddOrDisposeString(char* str, int len);
39 HashMap::Entry* GetEntry(const char* str, int len); 40 HashMap::Entry* GetEntry(const char* str, int len);
40 41
41 uint32_t hash_seed_; 42 uint32_t hash_seed_;
42 HashMap names_; 43 HashMap names_;
43 44
44 DISALLOW_COPY_AND_ASSIGN(StringsStorage); 45 DISALLOW_COPY_AND_ASSIGN(StringsStorage);
45 }; 46 };
46 47
47 48
49 // Provides a mapping from the offsets within generated code to
50 // the source line.
51 class JITLineInfoTable : public Malloced {
52 public:
53 JITLineInfoTable() {}
54 ~JITLineInfoTable() {}
55
56 void SetPosition(int pc_offset, int line) {
57 ASSERT(pc_offset >= 0);
58 ASSERT(line > 0); // The 1-based number of the source line.
59 pc_offset_map_.insert(std::make_pair(pc_offset, line));
60 }
61
62 int GetSourceLineNumber(int pc_offset) const {
63 PcOffsetMap::const_iterator it = pc_offset_map_.lower_bound(pc_offset);
64 if (it == pc_offset_map_.end()) {
65 return v8::CpuProfileNode::kNoLineNumberInfo;
66 }
67 return it->second;
68 }
69
70 bool Empty() const { return pc_offset_map_.empty(); }
71
72 private:
73 // pc_offset -> source line
74 typedef std::map<int, int> PcOffsetMap;
75 PcOffsetMap pc_offset_map_;
76 DISALLOW_COPY_AND_ASSIGN(JITLineInfoTable);
77 };
78
48 class CodeEntry { 79 class CodeEntry {
49 public: 80 public:
50 // CodeEntry doesn't own name strings, just references them. 81 // CodeEntry doesn't own name strings, just references them.
51 inline CodeEntry(Logger::LogEventsAndTags tag, 82 inline CodeEntry(Logger::LogEventsAndTags tag,
52 const char* name, 83 const char* name,
53 const char* name_prefix = CodeEntry::kEmptyNamePrefix, 84 const char* name_prefix = CodeEntry::kEmptyNamePrefix,
54 const char* resource_name = CodeEntry::kEmptyResourceName, 85 const char* resource_name = CodeEntry::kEmptyResourceName,
55 int line_number = v8::CpuProfileNode::kNoLineNumberInfo, 86 int line_number = v8::CpuProfileNode::kNoLineNumberInfo,
56 int column_number = v8::CpuProfileNode::kNoColumnNumberInfo); 87 int column_number = v8::CpuProfileNode::kNoColumnNumberInfo,
88 JITLineInfoTable* line_info = NULL);
57 ~CodeEntry(); 89 ~CodeEntry();
58 90
59 bool is_js_function() const { return is_js_function_tag(tag_); } 91 bool is_js_function() const { return is_js_function_tag(tag_); }
60 const char* name_prefix() const { return name_prefix_; } 92 const char* name_prefix() const { return name_prefix_; }
61 bool has_name_prefix() const { return name_prefix_[0] != '\0'; } 93 bool has_name_prefix() const { return name_prefix_[0] != '\0'; }
62 const char* name() const { return name_; } 94 const char* name() const { return name_; }
63 const char* resource_name() const { return resource_name_; } 95 const char* resource_name() const { return resource_name_; }
64 int line_number() const { return line_number_; } 96 int line_number() const { return line_number_; }
65 int column_number() const { return column_number_; } 97 int column_number() const { return column_number_; }
98 const JITLineInfoTable* line_info() const { return line_info_; }
66 void set_shared_id(int shared_id) { shared_id_ = shared_id; } 99 void set_shared_id(int shared_id) { shared_id_ = shared_id; }
67 int script_id() const { return script_id_; } 100 int script_id() const { return script_id_; }
68 void set_script_id(int script_id) { script_id_ = script_id; } 101 void set_script_id(int script_id) { script_id_ = script_id; }
69 void set_bailout_reason(const char* bailout_reason) { 102 void set_bailout_reason(const char* bailout_reason) {
70 bailout_reason_ = bailout_reason; 103 bailout_reason_ = bailout_reason;
71 } 104 }
72 const char* bailout_reason() const { return bailout_reason_; } 105 const char* bailout_reason() const { return bailout_reason_; }
73 106
74 static inline bool is_js_function_tag(Logger::LogEventsAndTags tag); 107 static inline bool is_js_function_tag(Logger::LogEventsAndTags tag);
75 108
76 List<OffsetRange>* no_frame_ranges() const { return no_frame_ranges_; } 109 List<OffsetRange>* no_frame_ranges() const { return no_frame_ranges_; }
77 void set_no_frame_ranges(List<OffsetRange>* ranges) { 110 void set_no_frame_ranges(List<OffsetRange>* ranges) {
78 no_frame_ranges_ = ranges; 111 no_frame_ranges_ = ranges;
79 } 112 }
80 113
81 void SetBuiltinId(Builtins::Name id); 114 void SetBuiltinId(Builtins::Name id);
82 Builtins::Name builtin_id() const { return builtin_id_; } 115 Builtins::Name builtin_id() const { return builtin_id_; }
83 116
84 uint32_t GetCallUid() const; 117 uint32_t GetCallUid() const;
85 bool IsSameAs(CodeEntry* entry) const; 118 bool IsSameAs(CodeEntry* entry) const;
86 119
120 int GetSourceLine(int pc_offset) const;
121
87 static const char* const kEmptyNamePrefix; 122 static const char* const kEmptyNamePrefix;
88 static const char* const kEmptyResourceName; 123 static const char* const kEmptyResourceName;
89 static const char* const kEmptyBailoutReason; 124 static const char* const kEmptyBailoutReason;
90 125
91 private: 126 private:
92 Logger::LogEventsAndTags tag_ : 8; 127 Logger::LogEventsAndTags tag_ : 8;
93 Builtins::Name builtin_id_ : 8; 128 Builtins::Name builtin_id_ : 8;
94 const char* name_prefix_; 129 const char* name_prefix_;
95 const char* name_; 130 const char* name_;
96 const char* resource_name_; 131 const char* resource_name_;
97 int line_number_; 132 int line_number_;
98 int column_number_; 133 int column_number_;
99 int shared_id_; 134 int shared_id_;
100 int script_id_; 135 int script_id_;
101 List<OffsetRange>* no_frame_ranges_; 136 List<OffsetRange>* no_frame_ranges_;
102 const char* bailout_reason_; 137 const char* bailout_reason_;
138 JITLineInfoTable* line_info_;
103 139
104 DISALLOW_COPY_AND_ASSIGN(CodeEntry); 140 DISALLOW_COPY_AND_ASSIGN(CodeEntry);
105 }; 141 };
106 142
107 143
108 class ProfileTree; 144 class ProfileTree;
109 145
110 class ProfileNode { 146 class ProfileNode {
111 public: 147 public:
112 inline ProfileNode(ProfileTree* tree, CodeEntry* entry); 148 inline ProfileNode(ProfileTree* tree, CodeEntry* entry);
113 149
114 ProfileNode* FindChild(CodeEntry* entry); 150 ProfileNode* FindChild(CodeEntry* entry);
115 ProfileNode* FindOrAddChild(CodeEntry* entry); 151 ProfileNode* FindOrAddChild(CodeEntry* entry);
116 void IncrementSelfTicks() { ++self_ticks_; } 152 void IncrementSelfTicks() { ++self_ticks_; }
117 void IncreaseSelfTicks(unsigned amount) { self_ticks_ += amount; } 153 void IncreaseSelfTicks(unsigned amount) { self_ticks_ += amount; }
154 void IncrementLineTicks(int src_line);
118 155
119 CodeEntry* entry() const { return entry_; } 156 CodeEntry* entry() const { return entry_; }
120 unsigned self_ticks() const { return self_ticks_; } 157 unsigned self_ticks() const { return self_ticks_; }
121 const List<ProfileNode*>* children() const { return &children_list_; } 158 const List<ProfileNode*>* children() const { return &children_list_; }
122 unsigned id() const { return id_; } 159 unsigned id() const { return id_; }
160 unsigned int GetHitLineCount() const { return line_ticks_.occupancy(); }
161 bool GetLineTicks(v8::CpuProfileNode::LineTick* entries,
162 unsigned int length) const;
123 163
124 void Print(int indent); 164 void Print(int indent);
125 165
126 private: 166 private:
127 static bool CodeEntriesMatch(void* entry1, void* entry2) { 167 static bool CodeEntriesMatch(void* entry1, void* entry2) {
128 return reinterpret_cast<CodeEntry*>(entry1)->IsSameAs( 168 return reinterpret_cast<CodeEntry*>(entry1)->IsSameAs(
129 reinterpret_cast<CodeEntry*>(entry2)); 169 reinterpret_cast<CodeEntry*>(entry2));
130 } 170 }
131 171
132 static uint32_t CodeEntryHash(CodeEntry* entry) { 172 static uint32_t CodeEntryHash(CodeEntry* entry) {
133 return entry->GetCallUid(); 173 return entry->GetCallUid();
134 } 174 }
135 175
136 ProfileTree* tree_; 176 ProfileTree* tree_;
137 CodeEntry* entry_; 177 CodeEntry* entry_;
138 unsigned self_ticks_; 178 unsigned self_ticks_;
139 // Mapping from CodeEntry* to ProfileNode* 179 // Mapping from CodeEntry* to ProfileNode*
140 HashMap children_; 180 HashMap children_;
141 List<ProfileNode*> children_list_; 181 List<ProfileNode*> children_list_;
142 unsigned id_; 182 unsigned id_;
183 HashMap line_ticks_;
143 184
144 DISALLOW_COPY_AND_ASSIGN(ProfileNode); 185 DISALLOW_COPY_AND_ASSIGN(ProfileNode);
145 }; 186 };
146 187
147 188
148 class ProfileTree { 189 class ProfileTree {
149 public: 190 public:
150 ProfileTree(); 191 ProfileTree();
151 ~ProfileTree(); 192 ~ProfileTree();
152 193
153 ProfileNode* AddPathFromEnd(const Vector<CodeEntry*>& path); 194 ProfileNode* AddPathFromEnd(
154 void AddPathFromStart(const Vector<CodeEntry*>& path); 195 const Vector<CodeEntry*>& path,
196 int src_line = v8::CpuProfileNode::kNoLineNumberInfo);
197 void AddPathFromStart(const Vector<CodeEntry*>& path,
198 int src_line = v8::CpuProfileNode::kNoLineNumberInfo);
155 ProfileNode* root() const { return root_; } 199 ProfileNode* root() const { return root_; }
156 unsigned next_node_id() { return next_node_id_++; } 200 unsigned next_node_id() { return next_node_id_++; }
157 201
158 void Print() { 202 void Print() {
159 root_->Print(0); 203 root_->Print(0);
160 } 204 }
161 205
162 private: 206 private:
163 template <typename Callback> 207 template <typename Callback>
164 void TraverseDepthFirst(Callback* callback); 208 void TraverseDepthFirst(Callback* callback);
165 209
166 CodeEntry root_entry_; 210 CodeEntry root_entry_;
167 unsigned next_node_id_; 211 unsigned next_node_id_;
168 ProfileNode* root_; 212 ProfileNode* root_;
169 213
170 DISALLOW_COPY_AND_ASSIGN(ProfileTree); 214 DISALLOW_COPY_AND_ASSIGN(ProfileTree);
171 }; 215 };
172 216
173 217
174 class CpuProfile { 218 class CpuProfile {
175 public: 219 public:
176 CpuProfile(const char* title, bool record_samples); 220 CpuProfile(const char* title, bool record_samples);
177 221
178 // Add pc -> ... -> main() call path to the profile. 222 // Add pc -> ... -> main() call path to the profile.
179 void AddPath(base::TimeTicks timestamp, const Vector<CodeEntry*>& path); 223 void AddPath(base::TimeTicks timestamp,
224 const Vector<CodeEntry*>& path,
225 int src_line);
180 void CalculateTotalTicksAndSamplingRate(); 226 void CalculateTotalTicksAndSamplingRate();
181 227
182 const char* title() const { return title_; } 228 const char* title() const { return title_; }
183 const ProfileTree* top_down() const { return &top_down_; } 229 const ProfileTree* top_down() const { return &top_down_; }
184 230
185 int samples_count() const { return samples_.length(); } 231 int samples_count() const { return samples_.length(); }
186 ProfileNode* sample(int index) const { return samples_.at(index); } 232 ProfileNode* sample(int index) const { return samples_.at(index); }
187 base::TimeTicks sample_timestamp(int index) const { 233 base::TimeTicks sample_timestamp(int index) const {
188 return timestamps_.at(index); 234 return timestamps_.at(index);
189 } 235 }
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 } 322 }
277 bool IsLastProfile(const char* title); 323 bool IsLastProfile(const char* title);
278 void RemoveProfile(CpuProfile* profile); 324 void RemoveProfile(CpuProfile* profile);
279 325
280 CodeEntry* NewCodeEntry( 326 CodeEntry* NewCodeEntry(
281 Logger::LogEventsAndTags tag, 327 Logger::LogEventsAndTags tag,
282 const char* name, 328 const char* name,
283 const char* name_prefix = CodeEntry::kEmptyNamePrefix, 329 const char* name_prefix = CodeEntry::kEmptyNamePrefix,
284 const char* resource_name = CodeEntry::kEmptyResourceName, 330 const char* resource_name = CodeEntry::kEmptyResourceName,
285 int line_number = v8::CpuProfileNode::kNoLineNumberInfo, 331 int line_number = v8::CpuProfileNode::kNoLineNumberInfo,
286 int column_number = v8::CpuProfileNode::kNoColumnNumberInfo); 332 int column_number = v8::CpuProfileNode::kNoColumnNumberInfo,
333 JITLineInfoTable* line_info = NULL);
287 334
288 // Called from profile generator thread. 335 // Called from profile generator thread.
289 void AddPathToCurrentProfiles( 336 void AddPathToCurrentProfiles(base::TimeTicks timestamp,
290 base::TimeTicks timestamp, const Vector<CodeEntry*>& path); 337 const Vector<CodeEntry*>& path,
338 int src_line);
291 339
292 // Limits the number of profiles that can be simultaneously collected. 340 // Limits the number of profiles that can be simultaneously collected.
293 static const int kMaxSimultaneousProfiles = 100; 341 static const int kMaxSimultaneousProfiles = 100;
294 342
295 private: 343 private:
296 StringsStorage function_and_resource_names_; 344 StringsStorage function_and_resource_names_;
297 List<CodeEntry*> code_entries_; 345 List<CodeEntry*> code_entries_;
298 List<CpuProfile*> finished_profiles_; 346 List<CpuProfile*> finished_profiles_;
299 347
300 // Accessed by VM thread and profile generator thread. 348 // Accessed by VM thread and profile generator thread.
(...skipping 30 matching lines...) Expand all
331 CodeEntry* gc_entry_; 379 CodeEntry* gc_entry_;
332 CodeEntry* unresolved_entry_; 380 CodeEntry* unresolved_entry_;
333 381
334 DISALLOW_COPY_AND_ASSIGN(ProfileGenerator); 382 DISALLOW_COPY_AND_ASSIGN(ProfileGenerator);
335 }; 383 };
336 384
337 385
338 } } // namespace v8::internal 386 } } // namespace v8::internal
339 387
340 #endif // V8_PROFILE_GENERATOR_H_ 388 #endif // V8_PROFILE_GENERATOR_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698