OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 #include "src/profiler/profile-generator.h" | 5 #include "src/profiler/profile-generator.h" |
6 | 6 |
7 #include "src/ast/scopeinfo.h" | 7 #include "src/ast/scopeinfo.h" |
8 #include "src/debug/debug.h" | 8 #include "src/debug/debug.h" |
9 #include "src/deoptimizer.h" | 9 #include "src/deoptimizer.h" |
10 #include "src/global-handles.h" | 10 #include "src/global-handles.h" |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 unsigned ProfileTree::GetFunctionId(const ProfileNode* node) { | 267 unsigned ProfileTree::GetFunctionId(const ProfileNode* node) { |
268 CodeEntry* code_entry = node->entry(); | 268 CodeEntry* code_entry = node->entry(); |
269 HashMap::Entry* entry = | 269 HashMap::Entry* entry = |
270 function_ids_.LookupOrInsert(code_entry, code_entry->GetHash()); | 270 function_ids_.LookupOrInsert(code_entry, code_entry->GetHash()); |
271 if (!entry->value) { | 271 if (!entry->value) { |
272 entry->value = reinterpret_cast<void*>(next_function_id_++); | 272 entry->value = reinterpret_cast<void*>(next_function_id_++); |
273 } | 273 } |
274 return static_cast<unsigned>(reinterpret_cast<uintptr_t>(entry->value)); | 274 return static_cast<unsigned>(reinterpret_cast<uintptr_t>(entry->value)); |
275 } | 275 } |
276 | 276 |
277 | |
278 ProfileNode* ProfileTree::AddPathFromEnd(const Vector<CodeEntry*>& path, | 277 ProfileNode* ProfileTree::AddPathFromEnd(const Vector<CodeEntry*>& path, |
279 int src_line) { | 278 int src_line, bool update_stats) { |
280 ProfileNode* node = root_; | 279 ProfileNode* node = root_; |
281 CodeEntry* last_entry = NULL; | 280 CodeEntry* last_entry = NULL; |
282 for (CodeEntry** entry = path.start() + path.length() - 1; | 281 for (CodeEntry** entry = path.start() + path.length() - 1; |
283 entry != path.start() - 1; | 282 entry != path.start() - 1; |
284 --entry) { | 283 --entry) { |
285 if (*entry != NULL) { | 284 if (*entry != NULL) { |
286 node = node->FindOrAddChild(*entry); | 285 node = node->FindOrAddChild(*entry); |
287 last_entry = *entry; | 286 last_entry = *entry; |
288 } | 287 } |
289 } | 288 } |
290 if (last_entry && last_entry->has_deopt_info()) { | 289 if (last_entry && last_entry->has_deopt_info()) { |
291 node->CollectDeoptInfo(last_entry); | 290 node->CollectDeoptInfo(last_entry); |
292 } | 291 } |
293 node->IncrementSelfTicks(); | 292 if (update_stats) { |
294 if (src_line != v8::CpuProfileNode::kNoLineNumberInfo) { | 293 node->IncrementSelfTicks(); |
295 node->IncrementLineTicks(src_line); | 294 if (src_line != v8::CpuProfileNode::kNoLineNumberInfo) { |
| 295 node->IncrementLineTicks(src_line); |
| 296 } |
296 } | 297 } |
297 return node; | 298 return node; |
298 } | 299 } |
299 | 300 |
300 | 301 |
301 struct NodesPair { | 302 struct NodesPair { |
302 NodesPair(ProfileNode* src, ProfileNode* dst) | 303 NodesPair(ProfileNode* src, ProfileNode* dst) |
303 : src(src), dst(dst) { } | 304 : src(src), dst(dst) { } |
304 ProfileNode* src; | 305 ProfileNode* src; |
305 ProfileNode* dst; | 306 ProfileNode* dst; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
347 } | 348 } |
348 } | 349 } |
349 | 350 |
350 | 351 |
351 CpuProfile::CpuProfile(Isolate* isolate, const char* title, bool record_samples) | 352 CpuProfile::CpuProfile(Isolate* isolate, const char* title, bool record_samples) |
352 : title_(title), | 353 : title_(title), |
353 record_samples_(record_samples), | 354 record_samples_(record_samples), |
354 start_time_(base::TimeTicks::HighResolutionNow()), | 355 start_time_(base::TimeTicks::HighResolutionNow()), |
355 top_down_(isolate) {} | 356 top_down_(isolate) {} |
356 | 357 |
357 | |
358 void CpuProfile::AddPath(base::TimeTicks timestamp, | 358 void CpuProfile::AddPath(base::TimeTicks timestamp, |
359 const Vector<CodeEntry*>& path, int src_line) { | 359 const Vector<CodeEntry*>& path, int src_line, |
360 ProfileNode* top_frame_node = top_down_.AddPathFromEnd(path, src_line); | 360 bool update_stats) { |
| 361 ProfileNode* top_frame_node = |
| 362 top_down_.AddPathFromEnd(path, src_line, update_stats); |
361 if (record_samples_) { | 363 if (record_samples_) { |
362 timestamps_.Add(timestamp); | 364 timestamps_.Add(timestamp); |
363 samples_.Add(top_frame_node); | 365 samples_.Add(top_frame_node); |
364 } | 366 } |
365 } | 367 } |
366 | 368 |
367 | 369 |
368 void CpuProfile::CalculateTotalTicksAndSamplingRate() { | 370 void CpuProfile::CalculateTotalTicksAndSamplingRate() { |
369 end_time_ = base::TimeTicks::HighResolutionNow(); | 371 end_time_ = base::TimeTicks::HighResolutionNow(); |
370 } | 372 } |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
515 // Called from VM thread for a completed profile. | 517 // Called from VM thread for a completed profile. |
516 for (int i = 0; i < finished_profiles_.length(); i++) { | 518 for (int i = 0; i < finished_profiles_.length(); i++) { |
517 if (profile == finished_profiles_[i]) { | 519 if (profile == finished_profiles_[i]) { |
518 finished_profiles_.Remove(i); | 520 finished_profiles_.Remove(i); |
519 return; | 521 return; |
520 } | 522 } |
521 } | 523 } |
522 UNREACHABLE(); | 524 UNREACHABLE(); |
523 } | 525 } |
524 | 526 |
525 | |
526 void CpuProfilesCollection::AddPathToCurrentProfiles( | 527 void CpuProfilesCollection::AddPathToCurrentProfiles( |
527 base::TimeTicks timestamp, const Vector<CodeEntry*>& path, int src_line) { | 528 base::TimeTicks timestamp, const Vector<CodeEntry*>& path, int src_line, |
| 529 bool update_stats) { |
528 // As starting / stopping profiles is rare relatively to this | 530 // As starting / stopping profiles is rare relatively to this |
529 // method, we don't bother minimizing the duration of lock holding, | 531 // method, we don't bother minimizing the duration of lock holding, |
530 // e.g. copying contents of the list to a local vector. | 532 // e.g. copying contents of the list to a local vector. |
531 current_profiles_semaphore_.Wait(); | 533 current_profiles_semaphore_.Wait(); |
532 for (int i = 0; i < current_profiles_.length(); ++i) { | 534 for (int i = 0; i < current_profiles_.length(); ++i) { |
533 current_profiles_[i]->AddPath(timestamp, path, src_line); | 535 current_profiles_[i]->AddPath(timestamp, path, src_line, update_stats); |
534 } | 536 } |
535 current_profiles_semaphore_.Signal(); | 537 current_profiles_semaphore_.Signal(); |
536 } | 538 } |
537 | 539 |
538 | 540 |
539 CodeEntry* CpuProfilesCollection::NewCodeEntry( | 541 CodeEntry* CpuProfilesCollection::NewCodeEntry( |
540 Logger::LogEventsAndTags tag, const char* name, const char* name_prefix, | 542 Logger::LogEventsAndTags tag, const char* name, const char* name_prefix, |
541 const char* resource_name, int line_number, int column_number, | 543 const char* resource_name, int line_number, int column_number, |
542 JITLineInfoTable* line_info, Address instruction_start) { | 544 JITLineInfoTable* line_info, Address instruction_start) { |
543 CodeEntry* code_entry = | 545 CodeEntry* code_entry = |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
663 no_symbolized_entries = false; | 665 no_symbolized_entries = false; |
664 break; | 666 break; |
665 } | 667 } |
666 } | 668 } |
667 // If no frames were symbolized, put the VM state entry in. | 669 // If no frames were symbolized, put the VM state entry in. |
668 if (no_symbolized_entries) { | 670 if (no_symbolized_entries) { |
669 *entry++ = EntryForVMState(sample.state); | 671 *entry++ = EntryForVMState(sample.state); |
670 } | 672 } |
671 } | 673 } |
672 | 674 |
673 profiles_->AddPathToCurrentProfiles(sample.timestamp, entries, src_line); | 675 profiles_->AddPathToCurrentProfiles(sample.timestamp, entries, src_line, |
| 676 sample.update_stats); |
674 } | 677 } |
675 | 678 |
676 | 679 |
677 CodeEntry* ProfileGenerator::EntryForVMState(StateTag tag) { | 680 CodeEntry* ProfileGenerator::EntryForVMState(StateTag tag) { |
678 switch (tag) { | 681 switch (tag) { |
679 case GC: | 682 case GC: |
680 return gc_entry_; | 683 return gc_entry_; |
681 case JS: | 684 case JS: |
682 case COMPILER: | 685 case COMPILER: |
683 // DOM events handlers are reported as OTHER / EXTERNAL entries. | 686 // DOM events handlers are reported as OTHER / EXTERNAL entries. |
684 // To avoid confusing people, let's put all these entries into | 687 // To avoid confusing people, let's put all these entries into |
685 // one bucket. | 688 // one bucket. |
686 case OTHER: | 689 case OTHER: |
687 case EXTERNAL: | 690 case EXTERNAL: |
688 return program_entry_; | 691 return program_entry_; |
689 case IDLE: | 692 case IDLE: |
690 return idle_entry_; | 693 return idle_entry_; |
691 default: return NULL; | 694 default: return NULL; |
692 } | 695 } |
693 } | 696 } |
694 | 697 |
695 } // namespace internal | 698 } // namespace internal |
696 } // namespace v8 | 699 } // namespace v8 |
OLD | NEW |