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

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

Issue 1514006: C++ profiles processor: put under #ifdef and fix issues. (Closed)
Patch Set: Created 10 years, 9 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
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 11 matching lines...) Expand all
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #include "profile-generator-inl.h" 30 #include "profile-generator-inl.h"
31 31
32
33 namespace v8 { 32 namespace v8 {
34 namespace internal { 33 namespace internal {
35 34
35 #ifdef ENABLE_CPP_PROFILES_PROCESSOR
36 36
37 ProfileNode* ProfileNode::FindChild(CodeEntry* entry) { 37 ProfileNode* ProfileNode::FindChild(CodeEntry* entry) {
38 HashMap::Entry* map_entry = 38 HashMap::Entry* map_entry =
39 children_.Lookup(entry, CodeEntryHash(entry), false); 39 children_.Lookup(entry, CodeEntryHash(entry), false);
40 return map_entry != NULL ? 40 return map_entry != NULL ?
41 reinterpret_cast<ProfileNode*>(map_entry->value) : NULL; 41 reinterpret_cast<ProfileNode*>(map_entry->value) : NULL;
42 } 42 }
43 43
44 44
45 ProfileNode* ProfileNode::FindOrAddChild(CodeEntry* entry) { 45 ProfileNode* ProfileNode::FindOrAddChild(CodeEntry* entry) {
46 HashMap::Entry* map_entry = 46 HashMap::Entry* map_entry =
47 children_.Lookup(entry, CodeEntryHash(entry), true); 47 children_.Lookup(entry, CodeEntryHash(entry), true);
48 if (map_entry->value == NULL) { 48 if (map_entry->value == NULL) {
49 // New node added. 49 // New node added.
50 map_entry->value = new ProfileNode(entry); 50 ProfileNode* new_node = new ProfileNode(entry);
51 map_entry->value = new_node;
52 children_list_.Add(new_node);
51 } 53 }
52 return reinterpret_cast<ProfileNode*>(map_entry->value); 54 return reinterpret_cast<ProfileNode*>(map_entry->value);
53 } 55 }
54 56
55 57
56 void ProfileNode::GetChildren(List<ProfileNode*>* children) {
57 for (HashMap::Entry* p = children_.Start();
58 p != NULL;
59 p = children_.Next(p)) {
60 children->Add(reinterpret_cast<ProfileNode*>(p->value));
61 }
62 }
63
64
65 void ProfileNode::Print(int indent) { 58 void ProfileNode::Print(int indent) {
66 OS::Print("%4u %4u %*c %s\n", 59 OS::Print("%5u %5u %*c %s\n",
67 total_ticks_, self_ticks_, 60 total_ticks_, self_ticks_,
68 indent, ' ', 61 indent, ' ',
69 entry_ != NULL ? entry_->name() : ""); 62 entry_ != NULL ? entry_->name() : "");
70 for (HashMap::Entry* p = children_.Start(); 63 for (HashMap::Entry* p = children_.Start();
71 p != NULL; 64 p != NULL;
72 p = children_.Next(p)) { 65 p = children_.Next(p)) {
73 reinterpret_cast<ProfileNode*>(p->value)->Print(indent + 2); 66 reinterpret_cast<ProfileNode*>(p->value)->Print(indent + 2);
74 } 67 }
75 } 68 }
76 69
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 if (*entry != NULL) { 109 if (*entry != NULL) {
117 node = node->FindOrAddChild(*entry); 110 node = node->FindOrAddChild(*entry);
118 } 111 }
119 } 112 }
120 node->IncrementSelfTicks(); 113 node->IncrementSelfTicks();
121 } 114 }
122 115
123 116
124 namespace { 117 namespace {
125 118
126 struct Position { 119 class Position {
127 Position(ProfileNode* a_node, HashMap::Entry* a_p) 120 public:
128 : node(a_node), p(a_p) { } 121 explicit Position(ProfileNode* node)
122 : node(node), child_idx_(0) { }
129 INLINE(ProfileNode* current_child()) { 123 INLINE(ProfileNode* current_child()) {
130 return reinterpret_cast<ProfileNode*>(p->value); 124 return node->children()->at(child_idx_);
131 } 125 }
126 INLINE(bool has_current_child()) {
127 return child_idx_ < node->children()->length();
128 }
129 INLINE(void next_child()) { ++child_idx_; }
130
132 ProfileNode* node; 131 ProfileNode* node;
133 HashMap::Entry* p; 132 private:
133 int child_idx_;
134 }; 134 };
135 135
136 } // namespace 136 } // namespace
137 137
138 138
139 // Non-recursive implementation of breadth-first post-order tree traversal.
139 template <typename Callback> 140 template <typename Callback>
140 void ProfileTree::TraverseBreadthFirstPostOrder(Callback* callback) { 141 void ProfileTree::TraverseBreadthFirstPostOrder(Callback* callback) {
141 List<Position> stack(10); 142 List<Position> stack(10);
142 stack.Add(Position(root_, root_->children_.Start())); 143 stack.Add(Position(root_));
143 do { 144 do {
144 Position& current = stack.last(); 145 Position& current = stack.last();
145 if (current.p != NULL) { 146 if (current.has_current_child()) {
146 stack.Add(Position(current.current_child(), 147 stack.Add(Position(current.current_child()));
147 current.current_child()->children_.Start()));
148 } else { 148 } else {
149 callback->AfterAllChildrenTraversed(current.node); 149 callback->AfterAllChildrenTraversed(current.node);
150 if (stack.length() > 1) { 150 if (stack.length() > 1) {
151 Position& parent = stack[stack.length() - 2]; 151 Position& parent = stack[stack.length() - 2];
152 callback->AfterChildTraversed(parent.node, current.node); 152 callback->AfterChildTraversed(parent.node, current.node);
153 parent.p = parent.node->children_.Next(parent.p); 153 parent.next_child();
154 // Remove child from the stack. 154 // Remove child from the stack.
155 stack.RemoveLast(); 155 stack.RemoveLast();
156 } 156 }
157 } 157 }
158 } while (stack.length() > 1 || stack.last().p != NULL); 158 } while (stack.length() > 1 || stack.last().has_current_child());
159 } 159 }
160 160
161 161
162 namespace { 162 namespace {
163 163
164 class CalculateTotalTicksCallback { 164 class CalculateTotalTicksCallback {
165 public: 165 public:
166 void AfterAllChildrenTraversed(ProfileNode* node) { 166 void AfterAllChildrenTraversed(ProfileNode* node) {
167 node->IncreaseTotalTicks(node->self_ticks()); 167 node->IncreaseTotalTicks(node->self_ticks());
168 } 168 }
169 169
170 void AfterChildTraversed(ProfileNode* parent, ProfileNode* child) { 170 void AfterChildTraversed(ProfileNode* parent, ProfileNode* child) {
171 parent->IncreaseTotalTicks(child->total_ticks()); 171 parent->IncreaseTotalTicks(child->total_ticks());
172 } 172 }
173 }; 173 };
174 174
175 } // namespace 175 } // namespace
176 176
177 177
178 // Non-recursive implementation of breadth-first tree traversal.
179 void ProfileTree::CalculateTotalTicks() { 178 void ProfileTree::CalculateTotalTicks() {
180 CalculateTotalTicksCallback cb; 179 CalculateTotalTicksCallback cb;
181 TraverseBreadthFirstPostOrder(&cb); 180 TraverseBreadthFirstPostOrder(&cb);
182 } 181 }
183 182
184 183
185 void ProfileTree::ShortPrint() { 184 void ProfileTree::ShortPrint() {
186 OS::Print("root: %u %u\n", root_->total_ticks(), root_->self_ticks()); 185 OS::Print("root: %u %u\n", root_->total_ticks(), root_->self_ticks());
187 } 186 }
188 187
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
235 if (tree_.FindGreatestLessThan(addr, &locator)) { 234 if (tree_.FindGreatestLessThan(addr, &locator)) {
236 // locator.key() <= addr. Need to check that addr is within entry. 235 // locator.key() <= addr. Need to check that addr is within entry.
237 const CodeEntryInfo& entry = locator.value(); 236 const CodeEntryInfo& entry = locator.value();
238 if (addr < (locator.key() + entry.size)) 237 if (addr < (locator.key() + entry.size))
239 return entry.entry; 238 return entry.entry;
240 } 239 }
241 return NULL; 240 return NULL;
242 } 241 }
243 242
244 243
244 void CodeMap::CodeTreePrinter::Call(
245 const Address& key, const CodeMap::CodeEntryInfo& value) {
246 OS::Print("%p %5d %s\n", key, value.size, value.entry->name());
247 }
248
249
250 void CodeMap::Print() {
251 CodeTreePrinter printer;
252 tree_.ForEach(&printer);
253 }
254
255
245 CpuProfilesCollection::CpuProfilesCollection() 256 CpuProfilesCollection::CpuProfilesCollection()
246 : function_and_resource_names_(StringsMatch) { 257 : function_and_resource_names_(StringsMatch),
258 profiles_uids_(CpuProfilesMatch),
259 current_profiles_semaphore_(OS::CreateSemaphore(1)) {
247 } 260 }
248 261
249 262
250 static void DeleteArgsCountName(char** name_ptr) { 263 static void DeleteArgsCountName(char** name_ptr) {
251 DeleteArray(*name_ptr); 264 DeleteArray(*name_ptr);
252 } 265 }
253 266
254 267
255 static void DeleteCodeEntry(CodeEntry** entry_ptr) { 268 static void DeleteCodeEntry(CodeEntry** entry_ptr) {
256 delete *entry_ptr; 269 delete *entry_ptr;
257 } 270 }
258 271
259 static void DeleteCpuProfile(CpuProfile** profile_ptr) { 272 static void DeleteCpuProfile(CpuProfile** profile_ptr) {
260 delete *profile_ptr; 273 delete *profile_ptr;
261 } 274 }
262 275
263 276
264 CpuProfilesCollection::~CpuProfilesCollection() { 277 CpuProfilesCollection::~CpuProfilesCollection() {
278 delete current_profiles_semaphore_;
279 current_profiles_.Iterate(DeleteCpuProfile);
265 profiles_.Iterate(DeleteCpuProfile); 280 profiles_.Iterate(DeleteCpuProfile);
266 code_entries_.Iterate(DeleteCodeEntry); 281 code_entries_.Iterate(DeleteCodeEntry);
267 args_count_names_.Iterate(DeleteArgsCountName); 282 args_count_names_.Iterate(DeleteArgsCountName);
268 for (HashMap::Entry* p = function_and_resource_names_.Start(); 283 for (HashMap::Entry* p = function_and_resource_names_.Start();
269 p != NULL; 284 p != NULL;
270 p = function_and_resource_names_.Next(p)) { 285 p = function_and_resource_names_.Next(p)) {
271 DeleteArray(reinterpret_cast<const char*>(p->value)); 286 DeleteArray(reinterpret_cast<const char*>(p->value));
272 } 287 }
273 } 288 }
274 289
275 290
276 void CpuProfilesCollection::AddProfile(unsigned uid) { 291 bool CpuProfilesCollection::StartProfiling(const char* title, unsigned uid) {
277 profiles_.Add(new CpuProfile()); 292 ASSERT(uid > 0);
293 current_profiles_semaphore_->Wait();
294 for (int i = 0; i < current_profiles_.length(); ++i) {
295 if (strcmp(current_profiles_[i]->title(), title) == 0) {
296 // Ignore attempts to start profile with the same title.
297 current_profiles_semaphore_->Signal();
298 return false;
299 }
300 }
301 current_profiles_.Add(new CpuProfile(title, uid));
302 current_profiles_semaphore_->Signal();
303 return true;
278 } 304 }
279 305
280 306
307 bool CpuProfilesCollection::StartProfiling(String* title, unsigned uid) {
308 return StartProfiling(GetName(title), uid);
309 }
310
311
312 CpuProfile* CpuProfilesCollection::StopProfiling(const char* title) {
313 const int title_len = strlen(title);
314 CpuProfile* profile = NULL;
315 current_profiles_semaphore_->Wait();
316 for (int i = current_profiles_.length() - 1; i >= 0; --i) {
317 if (title_len == 0 || strcmp(current_profiles_[i]->title(), title) == 0) {
318 profile = current_profiles_.Remove(i);
319 break;
320 }
321 }
322 current_profiles_semaphore_->Signal();
323
324 if (profile != NULL) {
325 profile->CalculateTotalTicks();
326 profiles_.Add(profile);
327 HashMap::Entry* entry =
328 profiles_uids_.Lookup(reinterpret_cast<void*>(profile->uid()),
329 static_cast<uint32_t>(profile->uid()),
330 true);
331 ASSERT(entry->value == NULL);
332 entry->value = profile;
333 }
334 return profile;
335 }
336
337
338 CpuProfile* CpuProfilesCollection::StopProfiling(String* title) {
339 return StopProfiling(GetName(title));
340 }
341
342
343 CpuProfile* CpuProfilesCollection::GetProfile(unsigned uid) {
344 HashMap::Entry* entry = profiles_uids_.Lookup(reinterpret_cast<void*>(uid),
345 static_cast<uint32_t>(uid),
346 false);
347 return entry != NULL ? reinterpret_cast<CpuProfile*>(entry->value) : NULL;
348 }
349
350
281 CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag, 351 CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
282 String* name, 352 String* name,
283 String* resource_name, 353 String* resource_name,
284 int line_number) { 354 int line_number) {
285 CodeEntry* entry = new CodeEntry(tag, 355 CodeEntry* entry = new CodeEntry(tag,
286 GetName(name), 356 GetName(name),
287 GetName(resource_name), 357 GetName(resource_name),
288 line_number); 358 line_number);
289 code_entries_.Add(entry); 359 code_entries_.Add(entry);
290 return entry; 360 return entry;
291 } 361 }
292 362
293 363
294 CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag, 364 CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
295 const char* name) { 365 const char* name) {
296 CodeEntry* entry = new CodeEntry(tag, name, "", 0); 366 CodeEntry* entry = new CodeEntry(tag,
367 name,
368 "",
369 kNoLineNumberInfo);
297 code_entries_.Add(entry); 370 code_entries_.Add(entry);
298 return entry; 371 return entry;
299 } 372 }
300 373
301 374
302 CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag, 375 CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
303 int args_count) { 376 int args_count) {
304 CodeEntry* entry = new CodeEntry(tag, GetName(args_count), "", 0); 377 CodeEntry* entry = new CodeEntry(tag,
378 GetName(args_count),
379 "",
380 kNoLineNumberInfo);
305 code_entries_.Add(entry); 381 code_entries_.Add(entry);
306 return entry; 382 return entry;
307 } 383 }
308 384
309 385
310 const char* CpuProfilesCollection::GetName(String* name) { 386 const char* CpuProfilesCollection::GetName(String* name) {
311 if (name->IsString()) { 387 if (name->IsString()) {
312 char* c_name = 388 char* c_name =
313 name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL).Detach(); 389 name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL).Detach();
314 HashMap::Entry* cache_entry = 390 HashMap::Entry* cache_entry =
(...skipping 23 matching lines...) Expand all
338 const int kMaximumNameLength = 32; 414 const int kMaximumNameLength = 32;
339 char* name = NewArray<char>(kMaximumNameLength); 415 char* name = NewArray<char>(kMaximumNameLength);
340 OS::SNPrintF(Vector<char>(name, kMaximumNameLength), 416 OS::SNPrintF(Vector<char>(name, kMaximumNameLength),
341 "args_count: %d", args_count); 417 "args_count: %d", args_count);
342 args_count_names_[args_count] = name; 418 args_count_names_[args_count] = name;
343 } 419 }
344 return args_count_names_[args_count]; 420 return args_count_names_[args_count];
345 } 421 }
346 422
347 423
424 void CpuProfilesCollection::AddPathToCurrentProfiles(
425 const Vector<CodeEntry*>& path) {
426 // As starting / stopping profiles is rare relatively to this
427 // method, we don't bother minimizing the duration of lock holding,
428 // e.g. copying contents of the list to a local vector.
429 current_profiles_semaphore_->Wait();
430 for (int i = 0; i < current_profiles_.length(); ++i) {
431 current_profiles_[i]->AddPath(path);
432 }
433 current_profiles_semaphore_->Signal();
434 }
435
436
348 ProfileGenerator::ProfileGenerator(CpuProfilesCollection* profiles) 437 ProfileGenerator::ProfileGenerator(CpuProfilesCollection* profiles)
349 : profiles_(profiles) { 438 : profiles_(profiles) {
350 } 439 }
351 440
352 441
353 void ProfileGenerator::RecordTickSample(const TickSample& sample) { 442 void ProfileGenerator::RecordTickSample(const TickSample& sample) {
354 // Allocate space for stack frames + pc + function. 443 // Allocate space for stack frames + pc + function.
355 ScopedVector<CodeEntry*> entries(sample.frames_count + 2); 444 ScopedVector<CodeEntry*> entries(sample.frames_count + 2);
356 CodeEntry** entry = entries.start(); 445 CodeEntry** entry = entries.start();
357 *entry++ = code_map_.FindEntry(sample.pc); 446 *entry++ = code_map_.FindEntry(sample.pc);
(...skipping 12 matching lines...) Expand all
370 *entry++ = NULL; 459 *entry++ = NULL;
371 } 460 }
372 461
373 for (const Address *stack_pos = sample.stack, 462 for (const Address *stack_pos = sample.stack,
374 *stack_end = stack_pos + sample.frames_count; 463 *stack_end = stack_pos + sample.frames_count;
375 stack_pos != stack_end; 464 stack_pos != stack_end;
376 ++stack_pos) { 465 ++stack_pos) {
377 *entry++ = code_map_.FindEntry(*stack_pos); 466 *entry++ = code_map_.FindEntry(*stack_pos);
378 } 467 }
379 468
380 profile()->AddPath(entries); 469 profiles_->AddPathToCurrentProfiles(entries);
381 } 470 }
382 471
472 #endif // ENABLE_CPP_PROFILES_PROCESSOR
383 473
384 } } // namespace v8::internal 474 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698