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/base/adapters.h" | 7 #include "src/base/adapters.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 619 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
630 // e.g. copying contents of the list to a local vector. | 630 // e.g. copying contents of the list to a local vector. |
631 current_profiles_semaphore_.Wait(); | 631 current_profiles_semaphore_.Wait(); |
632 for (int i = 0; i < current_profiles_.length(); ++i) { | 632 for (int i = 0; i < current_profiles_.length(); ++i) { |
633 current_profiles_[i]->AddPath(timestamp, path, src_line, update_stats); | 633 current_profiles_[i]->AddPath(timestamp, path, src_line, update_stats); |
634 } | 634 } |
635 current_profiles_semaphore_.Signal(); | 635 current_profiles_semaphore_.Signal(); |
636 } | 636 } |
637 | 637 |
638 ProfileGenerator::ProfileGenerator(Isolate* isolate, | 638 ProfileGenerator::ProfileGenerator(Isolate* isolate, |
639 CpuProfilesCollection* profiles) | 639 CpuProfilesCollection* profiles) |
640 : isolate_(isolate), profiles_(profiles) {} | 640 : isolate_(isolate), profiles_(profiles) { |
| 641 RuntimeCallStats* rcs = isolate_->counters()->runtime_call_stats(); |
| 642 for (int i = 0; i < RuntimeCallStats::counters_count; ++i) { |
| 643 RuntimeCallCounter* counter = &(rcs->*(RuntimeCallStats::counters[i])); |
| 644 DCHECK(counter->name()); |
| 645 auto entry = new CodeEntry(CodeEventListener::FUNCTION_TAG, counter->name(), |
| 646 CodeEntry::kEmptyNamePrefix, "native V8Runtime"); |
| 647 code_map_.AddCode(reinterpret_cast<Address>(counter), entry, 1); |
| 648 } |
| 649 } |
641 | 650 |
642 void ProfileGenerator::RecordTickSample(const TickSample& sample) { | 651 void ProfileGenerator::RecordTickSample(const TickSample& sample) { |
643 std::vector<CodeEntry*> entries; | 652 std::vector<CodeEntry*> entries; |
644 // Conservatively reserve space for stack frames + pc + function + vm-state. | 653 // Conservatively reserve space for stack frames + pc + function + vm-state. |
645 // There could in fact be more of them because of inlined entries. | 654 // There could in fact be more of them because of inlined entries. |
646 entries.reserve(sample.frames_count + 3); | 655 entries.reserve(sample.frames_count + 3); |
647 | 656 |
648 // The ProfileNode knows nothing about all versions of generated code for | 657 // The ProfileNode knows nothing about all versions of generated code for |
649 // the same JS function. The line number information associated with | 658 // the same JS function. The line number information associated with |
650 // the latest version of generated code is used to find a source line number | 659 // the latest version of generated code is used to find a source line number |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
735 if (no_symbolized_entries) { | 744 if (no_symbolized_entries) { |
736 entries.push_back(EntryForVMState(sample.state)); | 745 entries.push_back(EntryForVMState(sample.state)); |
737 } | 746 } |
738 } | 747 } |
739 | 748 |
740 profiles_->AddPathToCurrentProfiles(sample.timestamp, entries, src_line, | 749 profiles_->AddPathToCurrentProfiles(sample.timestamp, entries, src_line, |
741 sample.update_stats); | 750 sample.update_stats); |
742 } | 751 } |
743 | 752 |
744 CodeEntry* ProfileGenerator::FindEntry(void* address) { | 753 CodeEntry* ProfileGenerator::FindEntry(void* address) { |
745 CodeEntry* entry = code_map_.FindEntry(reinterpret_cast<Address>(address)); | 754 return code_map_.FindEntry(reinterpret_cast<Address>(address)); |
746 if (!entry) { | |
747 RuntimeCallStats* rcs = isolate_->counters()->runtime_call_stats(); | |
748 void* start = reinterpret_cast<void*>(rcs); | |
749 void* end = reinterpret_cast<void*>(rcs + 1); | |
750 if (start <= address && address < end) { | |
751 RuntimeCallCounter* counter = | |
752 reinterpret_cast<RuntimeCallCounter*>(address); | |
753 CHECK(counter->name()); | |
754 entry = new CodeEntry(CodeEventListener::FUNCTION_TAG, counter->name(), | |
755 CodeEntry::kEmptyNamePrefix, "native V8Runtime"); | |
756 code_map_.AddCode(reinterpret_cast<Address>(address), entry, 1); | |
757 } | |
758 } | |
759 return entry; | |
760 } | 755 } |
761 | 756 |
762 CodeEntry* ProfileGenerator::EntryForVMState(StateTag tag) { | 757 CodeEntry* ProfileGenerator::EntryForVMState(StateTag tag) { |
763 switch (tag) { | 758 switch (tag) { |
764 case GC: | 759 case GC: |
765 return CodeEntry::gc_entry(); | 760 return CodeEntry::gc_entry(); |
766 case JS: | 761 case JS: |
767 case COMPILER: | 762 case COMPILER: |
768 // DOM events handlers are reported as OTHER / EXTERNAL entries. | 763 // DOM events handlers are reported as OTHER / EXTERNAL entries. |
769 // To avoid confusing people, let's put all these entries into | 764 // To avoid confusing people, let's put all these entries into |
770 // one bucket. | 765 // one bucket. |
771 case OTHER: | 766 case OTHER: |
772 case EXTERNAL: | 767 case EXTERNAL: |
773 return CodeEntry::program_entry(); | 768 return CodeEntry::program_entry(); |
774 case IDLE: | 769 case IDLE: |
775 return CodeEntry::idle_entry(); | 770 return CodeEntry::idle_entry(); |
776 default: return NULL; | 771 default: return NULL; |
777 } | 772 } |
778 } | 773 } |
779 | 774 |
780 } // namespace internal | 775 } // namespace internal |
781 } // namespace v8 | 776 } // namespace v8 |
OLD | NEW |