| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "platform/address_sanitizer.h" | 5 #include "platform/address_sanitizer.h" |
| 6 #include "platform/memory_sanitizer.h" | 6 #include "platform/memory_sanitizer.h" |
| 7 #include "platform/utils.h" | 7 #include "platform/utils.h" |
| 8 | 8 |
| 9 #include "vm/allocation.h" | 9 #include "vm/allocation.h" |
| 10 #include "vm/atomic.h" | 10 #include "vm/atomic.h" |
| (...skipping 28 matching lines...) Expand all Loading... |
| 39 DEFINE_FLAG(bool, profile_vm, true, | 39 DEFINE_FLAG(bool, profile_vm, true, |
| 40 "Always collect native stack traces."); | 40 "Always collect native stack traces."); |
| 41 #else | 41 #else |
| 42 DEFINE_FLAG(bool, profile_vm, false, | 42 DEFINE_FLAG(bool, profile_vm, false, |
| 43 "Always collect native stack traces."); | 43 "Always collect native stack traces."); |
| 44 #endif | 44 #endif |
| 45 | 45 |
| 46 bool Profiler::initialized_ = false; | 46 bool Profiler::initialized_ = false; |
| 47 SampleBuffer* Profiler::sample_buffer_ = NULL; | 47 SampleBuffer* Profiler::sample_buffer_ = NULL; |
| 48 | 48 |
| 49 static intptr_t NumberOfFramesToCollect() { |
| 50 if (FLAG_profile_depth <= 0) { |
| 51 return 0; |
| 52 } |
| 53 // Subtract to reserve space for the possible missing frame. |
| 54 return FLAG_profile_depth - 1; |
| 55 } |
| 56 |
| 49 void Profiler::InitOnce() { | 57 void Profiler::InitOnce() { |
| 50 // Place some sane restrictions on user controlled flags. | 58 // Place some sane restrictions on user controlled flags. |
| 51 SetSamplePeriod(FLAG_profile_period); | 59 SetSamplePeriod(FLAG_profile_period); |
| 52 SetSampleDepth(FLAG_profile_depth); | 60 SetSampleDepth(FLAG_profile_depth); |
| 53 Sample::InitOnce(); | 61 Sample::InitOnce(); |
| 54 if (!FLAG_profile) { | 62 if (!FLAG_profile) { |
| 55 return; | 63 return; |
| 56 } | 64 } |
| 57 ASSERT(!initialized_); | 65 ASSERT(!initialized_); |
| 58 sample_buffer_ = new SampleBuffer(); | 66 sample_buffer_ = new SampleBuffer(); |
| 59 NativeSymbolResolver::InitOnce(); | 67 NativeSymbolResolver::InitOnce(); |
| 60 ThreadInterrupter::SetInterruptPeriod(FLAG_profile_period); | 68 ThreadInterrupter::SetInterruptPeriod(FLAG_profile_period); |
| 61 ThreadInterrupter::Startup(); | 69 ThreadInterrupter::Startup(); |
| 62 initialized_ = true; | 70 initialized_ = true; |
| 63 } | 71 } |
| 64 | 72 |
| 65 | 73 |
| 66 void Profiler::Shutdown() { | 74 void Profiler::Shutdown() { |
| 67 if (!FLAG_profile) { | 75 if (!FLAG_profile) { |
| 68 return; | 76 return; |
| 69 } | 77 } |
| 70 ASSERT(initialized_); | 78 ASSERT(initialized_); |
| 71 ThreadInterrupter::Shutdown(); | 79 ThreadInterrupter::Shutdown(); |
| 72 NativeSymbolResolver::ShutdownOnce(); | 80 NativeSymbolResolver::ShutdownOnce(); |
| 73 } | 81 } |
| 74 | 82 |
| 75 | 83 |
| 76 void Profiler::SetSampleDepth(intptr_t depth) { | 84 void Profiler::SetSampleDepth(intptr_t depth) { |
| 77 const int kMinimumDepth = 1; | 85 const int kMinimumDepth = 2; |
| 78 const int kMaximumDepth = 255; | 86 const int kMaximumDepth = 255; |
| 79 if (depth < kMinimumDepth) { | 87 if (depth < kMinimumDepth) { |
| 80 FLAG_profile_depth = kMinimumDepth; | 88 FLAG_profile_depth = kMinimumDepth; |
| 81 } else if (depth > kMaximumDepth) { | 89 } else if (depth > kMaximumDepth) { |
| 82 FLAG_profile_depth = kMaximumDepth; | 90 FLAG_profile_depth = kMaximumDepth; |
| 83 } else { | 91 } else { |
| 84 FLAG_profile_depth = depth; | 92 FLAG_profile_depth = depth; |
| 85 } | 93 } |
| 86 } | 94 } |
| 87 | 95 |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 206 ThreadInterrupter::WakeUp(); | 214 ThreadInterrupter::WakeUp(); |
| 207 } | 215 } |
| 208 } | 216 } |
| 209 | 217 |
| 210 | 218 |
| 211 intptr_t Sample::pcs_length_ = 0; | 219 intptr_t Sample::pcs_length_ = 0; |
| 212 intptr_t Sample::instance_size_ = 0; | 220 intptr_t Sample::instance_size_ = 0; |
| 213 | 221 |
| 214 | 222 |
| 215 void Sample::InitOnce() { | 223 void Sample::InitOnce() { |
| 216 ASSERT(FLAG_profile_depth >= 1); | 224 ASSERT(FLAG_profile_depth >= 2); |
| 217 pcs_length_ = FLAG_profile_depth; | 225 pcs_length_ = FLAG_profile_depth; |
| 218 instance_size_ = | 226 instance_size_ = |
| 219 sizeof(Sample) + (sizeof(uword) * pcs_length_); // NOLINT. | 227 sizeof(Sample) + (sizeof(uword) * pcs_length_); // NOLINT. |
| 220 } | 228 } |
| 221 | 229 |
| 222 | 230 |
| 223 uword* Sample::GetPCArray() const { | 231 uword* Sample::GetPCArray() const { |
| 224 return reinterpret_cast<uword*>( | 232 return reinterpret_cast<uword*>( |
| 225 reinterpret_cast<uintptr_t>(this) + sizeof(*this)); | 233 reinterpret_cast<uintptr_t>(this) + sizeof(*this)); |
| 226 } | 234 } |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 585 // Mark that this sample was collected from an exit frame. | 593 // Mark that this sample was collected from an exit frame. |
| 586 sample_->set_exit_frame_sample(true); | 594 sample_->set_exit_frame_sample(true); |
| 587 } | 595 } |
| 588 | 596 |
| 589 void walk() { | 597 void walk() { |
| 590 intptr_t frame_index = 0; | 598 intptr_t frame_index = 0; |
| 591 StackFrame* frame = frame_iterator_.NextFrame(); | 599 StackFrame* frame = frame_iterator_.NextFrame(); |
| 592 while (frame != NULL) { | 600 while (frame != NULL) { |
| 593 sample_->SetAt(frame_index, frame->pc()); | 601 sample_->SetAt(frame_index, frame->pc()); |
| 594 frame_index++; | 602 frame_index++; |
| 595 if (frame_index >= FLAG_profile_depth) { | 603 if (frame_index >= NumberOfFramesToCollect()) { |
| 604 sample_->set_truncated_trace(true); |
| 596 break; | 605 break; |
| 597 } | 606 } |
| 598 frame = frame_iterator_.NextFrame(); | 607 frame = frame_iterator_.NextFrame(); |
| 599 } | 608 } |
| 600 } | 609 } |
| 601 | 610 |
| 602 private: | 611 private: |
| 603 Sample* sample_; | 612 Sample* sample_; |
| 604 DartFrameIterator frame_iterator_; | 613 DartFrameIterator frame_iterator_; |
| 605 }; | 614 }; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 635 if (StubCode::InInvocationStubForIsolate(isolate_, return_pc)) { | 644 if (StubCode::InInvocationStubForIsolate(isolate_, return_pc)) { |
| 636 // Edge case- we have called out from the Invocation Stub but have not | 645 // Edge case- we have called out from the Invocation Stub but have not |
| 637 // created the stack frame of the callee. Attempt to locate the exit | 646 // created the stack frame of the callee. Attempt to locate the exit |
| 638 // frame before walking the stack. | 647 // frame before walking the stack. |
| 639 if (!NextExit() || !ValidFramePointer()) { | 648 if (!NextExit() || !ValidFramePointer()) { |
| 640 // Nothing to sample. | 649 // Nothing to sample. |
| 641 sample_->set_ignore_sample(true); | 650 sample_->set_ignore_sample(true); |
| 642 return; | 651 return; |
| 643 } | 652 } |
| 644 } | 653 } |
| 645 for (int i = 0; i < FLAG_profile_depth; i++) { | 654 for (int i = 0; i < NumberOfFramesToCollect(); i++) { |
| 646 sample_->SetAt(i, reinterpret_cast<uword>(pc_)); | 655 sample_->SetAt(i, reinterpret_cast<uword>(pc_)); |
| 647 if (!Next()) { | 656 if (!Next()) { |
| 648 return; | 657 return; |
| 649 } | 658 } |
| 650 } | 659 } |
| 660 sample_->set_truncated_trace(true); |
| 651 } | 661 } |
| 652 | 662 |
| 653 private: | 663 private: |
| 654 bool Next() { | 664 bool Next() { |
| 655 if (!ValidFramePointer()) { | 665 if (!ValidFramePointer()) { |
| 656 return false; | 666 return false; |
| 657 } | 667 } |
| 658 if (StubCode::InInvocationStubForIsolate(isolate_, | 668 if (StubCode::InInvocationStubForIsolate(isolate_, |
| 659 reinterpret_cast<uword>(pc_))) { | 669 reinterpret_cast<uword>(pc_))) { |
| 660 // In invocation stub. | 670 // In invocation stub. |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 793 if (gap >= kMaxStep) { | 803 if (gap >= kMaxStep) { |
| 794 // Gap between frame pointer and stack pointer is | 804 // Gap between frame pointer and stack pointer is |
| 795 // too large. | 805 // too large. |
| 796 return; | 806 return; |
| 797 } | 807 } |
| 798 | 808 |
| 799 if (!ValidFramePointer(fp)) { | 809 if (!ValidFramePointer(fp)) { |
| 800 return; | 810 return; |
| 801 } | 811 } |
| 802 | 812 |
| 803 for (int i = 0; i < FLAG_profile_depth; i++) { | 813 for (int i = 0; i < NumberOfFramesToCollect(); i++) { |
| 804 sample_->SetAt(i, reinterpret_cast<uword>(pc)); | 814 sample_->SetAt(i, reinterpret_cast<uword>(pc)); |
| 805 | 815 |
| 806 pc = CallerPC(fp); | 816 pc = CallerPC(fp); |
| 807 previous_fp = fp; | 817 previous_fp = fp; |
| 808 fp = CallerFP(fp); | 818 fp = CallerFP(fp); |
| 809 | 819 |
| 810 if (fp == NULL) { | 820 if (fp == NULL) { |
| 811 return; | 821 return; |
| 812 } | 822 } |
| 813 | 823 |
| 814 if (fp <= previous_fp) { | 824 if (fp <= previous_fp) { |
| 815 // Frame pointer did not move to a higher address. | 825 // Frame pointer did not move to a higher address. |
| 816 return; | 826 return; |
| 817 } | 827 } |
| 818 | 828 |
| 819 gap = fp - previous_fp; | 829 gap = fp - previous_fp; |
| 820 if (gap >= kMaxStep) { | 830 if (gap >= kMaxStep) { |
| 821 // Frame pointer step is too large. | 831 // Frame pointer step is too large. |
| 822 return; | 832 return; |
| 823 } | 833 } |
| 824 | 834 |
| 825 if (!ValidFramePointer(fp)) { | 835 if (!ValidFramePointer(fp)) { |
| 826 // Frame pointer is outside of isolate stack boundary. | 836 // Frame pointer is outside of isolate stack boundary. |
| 827 return; | 837 return; |
| 828 } | 838 } |
| 829 | 839 |
| 830 // Move the lower bound up. | 840 // Move the lower bound up. |
| 831 lower_bound_ = reinterpret_cast<uword>(fp); | 841 lower_bound_ = reinterpret_cast<uword>(fp); |
| 832 } | 842 } |
| 843 |
| 844 sample_->set_truncated_trace(true); |
| 833 } | 845 } |
| 834 | 846 |
| 835 private: | 847 private: |
| 836 uword* CallerPC(uword* fp) const { | 848 uword* CallerPC(uword* fp) const { |
| 837 ASSERT(fp != NULL); | 849 ASSERT(fp != NULL); |
| 838 uword* caller_pc_ptr = fp + kSavedCallerPcSlotFromFp; | 850 uword* caller_pc_ptr = fp + kSavedCallerPcSlotFromFp; |
| 839 // This may actually be uninitialized, by design (see class comment above). | 851 // This may actually be uninitialized, by design (see class comment above). |
| 840 MSAN_UNPOISON(caller_pc_ptr, kWordSize); | 852 MSAN_UNPOISON(caller_pc_ptr, kWordSize); |
| 841 ASAN_UNPOISON(caller_pc_ptr, kWordSize); | 853 ASAN_UNPOISON(caller_pc_ptr, kWordSize); |
| 842 return reinterpret_cast<uword*>(*caller_pc_ptr); | 854 return reinterpret_cast<uword*>(*caller_pc_ptr); |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1060 state.fp, | 1072 state.fp, |
| 1061 sp); | 1073 sp); |
| 1062 stackWalker.walk(); | 1074 stackWalker.walk(); |
| 1063 } else { | 1075 } else { |
| 1064 sample->set_vm_tag(VMTag::kEmbedderTagId); | 1076 sample->set_vm_tag(VMTag::kEmbedderTagId); |
| 1065 sample->SetAt(0, state.pc); | 1077 sample->SetAt(0, state.pc); |
| 1066 } | 1078 } |
| 1067 } | 1079 } |
| 1068 | 1080 |
| 1069 } // namespace dart | 1081 } // namespace dart |
| OLD | NEW |