| 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/utils.h" | 5 #include "platform/utils.h" |
| 6 | 6 |
| 7 #include "vm/allocation.h" | 7 #include "vm/allocation.h" |
| 8 #include "vm/atomic.h" | 8 #include "vm/atomic.h" |
| 9 #include "vm/code_patcher.h" | 9 #include "vm/code_patcher.h" |
| 10 #include "vm/isolate.h" | 10 #include "vm/isolate.h" |
| (...skipping 856 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 867 // Notes on stack frame walking: | 867 // Notes on stack frame walking: |
| 868 // | 868 // |
| 869 // The sampling profiler will collect up to Sample::kNumStackFrames stack frames | 869 // The sampling profiler will collect up to Sample::kNumStackFrames stack frames |
| 870 // The stack frame walking code uses the frame pointer to traverse the stack. | 870 // The stack frame walking code uses the frame pointer to traverse the stack. |
| 871 // If the VM is compiled without frame pointers (which is the default on | 871 // If the VM is compiled without frame pointers (which is the default on |
| 872 // recent GCC versions with optimizing enabled) the stack walking code may | 872 // recent GCC versions with optimizing enabled) the stack walking code may |
| 873 // fail (sometimes leading to a crash). | 873 // fail (sometimes leading to a crash). |
| 874 // | 874 // |
| 875 class ProfilerSampleStackWalker : public ValueObject { | 875 class ProfilerSampleStackWalker : public ValueObject { |
| 876 public: | 876 public: |
| 877 ProfilerSampleStackWalker(Sample* sample, | 877 ProfilerSampleStackWalker(Heap* heap, |
| 878 Sample* sample, |
| 878 uword stack_lower, | 879 uword stack_lower, |
| 879 uword stack_upper, | 880 uword stack_upper, |
| 880 uword pc, | 881 uword pc, |
| 881 uword fp, | 882 uword fp, |
| 882 uword sp) | 883 uword sp) |
| 883 : sample_(sample), | 884 : heap_(heap), |
| 885 sample_(sample), |
| 884 stack_upper_(stack_upper), | 886 stack_upper_(stack_upper), |
| 885 original_pc_(pc), | 887 original_pc_(pc), |
| 886 original_fp_(fp), | 888 original_fp_(fp), |
| 887 original_sp_(sp), | 889 original_sp_(sp), |
| 888 lower_bound_(stack_lower) { | 890 lower_bound_(stack_lower) { |
| 889 ASSERT(sample_ != NULL); | 891 ASSERT(sample_ != NULL); |
| 890 } | 892 } |
| 891 | 893 |
| 892 int walk() { | 894 int walk() { |
| 893 const intptr_t kMaxStep = 0x1000; // 4K. | 895 const intptr_t kMaxStep = 0x1000; // 4K. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 911 // too large. | 913 // too large. |
| 912 return 1; | 914 return 1; |
| 913 } | 915 } |
| 914 if (original_sp_ < lower_bound_) { | 916 if (original_sp_ < lower_bound_) { |
| 915 // The stack pointer gives us a better lower bound than | 917 // The stack pointer gives us a better lower bound than |
| 916 // the isolates stack limit. | 918 // the isolates stack limit. |
| 917 lower_bound_ = original_sp_; | 919 lower_bound_ = original_sp_; |
| 918 } | 920 } |
| 919 int i = 0; | 921 int i = 0; |
| 920 for (; i < FLAG_profile_depth; i++) { | 922 for (; i < FLAG_profile_depth; i++) { |
| 923 #if defined(DEBUG_STACK_WALK) |
| 924 VerifyCodeAddress(i, reinterpret_cast<uword>(pc)); |
| 925 #endif |
| 921 sample_->SetAt(i, reinterpret_cast<uword>(pc)); | 926 sample_->SetAt(i, reinterpret_cast<uword>(pc)); |
| 922 if (!ValidFramePointer(fp)) { | 927 if (!ValidFramePointer(fp)) { |
| 923 return i + 1; | 928 return i + 1; |
| 924 } | 929 } |
| 925 pc = CallerPC(fp); | 930 pc = CallerPC(fp); |
| 926 previous_fp = fp; | 931 previous_fp = fp; |
| 927 fp = CallerFP(fp); | 932 fp = CallerFP(fp); |
| 928 intptr_t step = fp - previous_fp; | 933 intptr_t step = fp - previous_fp; |
| 929 if ((step >= kMaxStep) || (fp <= previous_fp) || !ValidFramePointer(fp)) { | 934 if ((step >= kMaxStep) || (fp <= previous_fp) || !ValidFramePointer(fp)) { |
| 930 // Frame pointer step is too large. | 935 // Frame pointer step is too large. |
| 931 // Frame pointer did not move to a higher address. | 936 // Frame pointer did not move to a higher address. |
| 932 // Frame pointer is outside of isolate stack bounds. | 937 // Frame pointer is outside of isolate stack bounds. |
| 933 return i + 1; | 938 return i + 1; |
| 934 } | 939 } |
| 935 // Move the lower bound up. | 940 // Move the lower bound up. |
| 936 lower_bound_ = reinterpret_cast<uword>(fp); | 941 lower_bound_ = reinterpret_cast<uword>(fp); |
| 937 } | 942 } |
| 938 return i; | 943 return i; |
| 939 } | 944 } |
| 940 | 945 |
| 941 private: | 946 private: |
| 947 #if defined(DEBUG_STACK_WALK) |
| 948 void VerifyCodeAddress(int i, uword pc) { |
| 949 if (heap_ != NULL) { |
| 950 if (heap_->Contains(pc) && !heap_->CodeContains(pc)) { |
| 951 for (int j = 0; j < i; j++) { |
| 952 OS::Print("%d %" Px "\n", j, sample_->At(j)); |
| 953 } |
| 954 OS::Print("%d %" Px " <--\n", i, pc); |
| 955 OS::Print("---ASSERT-FAILED---\n"); |
| 956 OS::Print("%" Px " %" Px "\n", original_pc_, original_fp_); |
| 957 UNREACHABLE(); |
| 958 } |
| 959 } |
| 960 } |
| 961 #endif |
| 962 |
| 942 uword* CallerPC(uword* fp) const { | 963 uword* CallerPC(uword* fp) const { |
| 943 ASSERT(fp != NULL); | 964 ASSERT(fp != NULL); |
| 944 return reinterpret_cast<uword*>(*(fp + kSavedCallerPcSlotFromFp)); | 965 return reinterpret_cast<uword*>(*(fp + kSavedCallerPcSlotFromFp)); |
| 945 } | 966 } |
| 946 | 967 |
| 947 uword* CallerFP(uword* fp) const { | 968 uword* CallerFP(uword* fp) const { |
| 948 ASSERT(fp != NULL); | 969 ASSERT(fp != NULL); |
| 949 return reinterpret_cast<uword*>(*(fp + kSavedCallerFpSlotFromFp)); | 970 return reinterpret_cast<uword*>(*(fp + kSavedCallerFpSlotFromFp)); |
| 950 } | 971 } |
| 951 | 972 |
| 952 bool ValidFramePointer(uword* fp) const { | 973 bool ValidFramePointer(uword* fp) const { |
| 953 if (fp == NULL) { | 974 if (fp == NULL) { |
| 954 return false; | 975 return false; |
| 955 } | 976 } |
| 956 uword cursor = reinterpret_cast<uword>(fp); | 977 uword cursor = reinterpret_cast<uword>(fp); |
| 957 cursor += sizeof(fp); | 978 cursor += sizeof(fp); |
| 958 bool r = cursor >= lower_bound_ && cursor < stack_upper_; | 979 bool r = cursor >= lower_bound_ && cursor < stack_upper_; |
| 959 return r; | 980 return r; |
| 960 } | 981 } |
| 961 | 982 |
| 983 Heap* heap_; |
| 962 Sample* sample_; | 984 Sample* sample_; |
| 963 const uword stack_upper_; | 985 const uword stack_upper_; |
| 964 const uword original_pc_; | 986 const uword original_pc_; |
| 965 const uword original_fp_; | 987 const uword original_fp_; |
| 966 const uword original_sp_; | 988 const uword original_sp_; |
| 967 uword lower_bound_; | 989 uword lower_bound_; |
| 968 }; | 990 }; |
| 969 | 991 |
| 970 void Profiler::RecordSampleInterruptCallback( | 992 void Profiler::RecordSampleInterruptCallback( |
| 971 const InterruptedThreadState& state, | 993 const InterruptedThreadState& state, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 984 } | 1006 } |
| 985 Sample* sample = sample_buffer->ReserveSample(); | 1007 Sample* sample = sample_buffer->ReserveSample(); |
| 986 sample->Init(isolate, OS::GetCurrentTimeMicros(), state.tid); | 1008 sample->Init(isolate, OS::GetCurrentTimeMicros(), state.tid); |
| 987 uword stack_lower = 0; | 1009 uword stack_lower = 0; |
| 988 uword stack_upper = 0; | 1010 uword stack_upper = 0; |
| 989 isolate->GetStackBounds(&stack_lower, &stack_upper); | 1011 isolate->GetStackBounds(&stack_lower, &stack_upper); |
| 990 if ((stack_lower == 0) || (stack_upper == 0)) { | 1012 if ((stack_lower == 0) || (stack_upper == 0)) { |
| 991 stack_lower = 0; | 1013 stack_lower = 0; |
| 992 stack_upper = 0; | 1014 stack_upper = 0; |
| 993 } | 1015 } |
| 994 ProfilerSampleStackWalker stackWalker(sample, stack_lower, stack_upper, | 1016 ProfilerSampleStackWalker stackWalker(isolate->heap(), sample, stack_lower, |
| 995 state.pc, state.fp, state.sp); | 1017 stack_upper, state.pc, state.fp, |
| 1018 state.sp); |
| 996 stackWalker.walk(); | 1019 stackWalker.walk(); |
| 997 } | 1020 } |
| 998 | 1021 |
| 999 | 1022 |
| 1000 } // namespace dart | 1023 } // namespace dart |
| OLD | NEW |