| 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 |