Chromium Code Reviews| 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 bool contained = heap_->Contains(pc); | |
| 951 bool code_contained = heap_->CodeContains(pc); | |
| 952 if (contained != code_contained) { | |
|
siva
2014/02/27 00:00:26
Doesn't short circuit when it is not contained in
Cutch
2014/02/27 15:52:37
Done.
| |
| 953 for (int j = 0; j < i; j++) { | |
| 954 OS::Print("%d %" Px "\n", j, sample_->At(j)); | |
| 955 } | |
| 956 OS::Print("%d %" Px " <--\n", i, pc); | |
| 957 OS::Print("---ASSERT-FAILED---\n"); | |
| 958 OS::Print("%" Px " %" Px "\n", original_pc_, original_fp_); | |
| 959 } | |
| 960 ASSERT(contained == code_contained); | |
| 961 } | |
| 962 } | |
| 963 #endif | |
| 964 | |
| 942 uword* CallerPC(uword* fp) const { | 965 uword* CallerPC(uword* fp) const { |
| 943 ASSERT(fp != NULL); | 966 ASSERT(fp != NULL); |
| 944 return reinterpret_cast<uword*>(*(fp + kSavedCallerPcSlotFromFp)); | 967 return reinterpret_cast<uword*>(*(fp + kSavedCallerPcSlotFromFp)); |
| 945 } | 968 } |
| 946 | 969 |
| 947 uword* CallerFP(uword* fp) const { | 970 uword* CallerFP(uword* fp) const { |
| 948 ASSERT(fp != NULL); | 971 ASSERT(fp != NULL); |
| 949 return reinterpret_cast<uword*>(*(fp + kSavedCallerFpSlotFromFp)); | 972 return reinterpret_cast<uword*>(*(fp + kSavedCallerFpSlotFromFp)); |
| 950 } | 973 } |
| 951 | 974 |
| 952 bool ValidFramePointer(uword* fp) const { | 975 bool ValidFramePointer(uword* fp) const { |
| 953 if (fp == NULL) { | 976 if (fp == NULL) { |
| 954 return false; | 977 return false; |
| 955 } | 978 } |
| 956 uword cursor = reinterpret_cast<uword>(fp); | 979 uword cursor = reinterpret_cast<uword>(fp); |
| 957 cursor += sizeof(fp); | 980 cursor += sizeof(fp); |
| 958 bool r = cursor >= lower_bound_ && cursor < stack_upper_; | 981 bool r = cursor >= lower_bound_ && cursor < stack_upper_; |
| 959 return r; | 982 return r; |
| 960 } | 983 } |
| 961 | 984 |
| 985 Heap* heap_; | |
| 962 Sample* sample_; | 986 Sample* sample_; |
| 963 const uword stack_upper_; | 987 const uword stack_upper_; |
| 964 const uword original_pc_; | 988 const uword original_pc_; |
| 965 const uword original_fp_; | 989 const uword original_fp_; |
| 966 const uword original_sp_; | 990 const uword original_sp_; |
| 967 uword lower_bound_; | 991 uword lower_bound_; |
| 968 }; | 992 }; |
| 969 | 993 |
| 970 void Profiler::RecordSampleInterruptCallback( | 994 void Profiler::RecordSampleInterruptCallback( |
| 971 const InterruptedThreadState& state, | 995 const InterruptedThreadState& state, |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 984 } | 1008 } |
| 985 Sample* sample = sample_buffer->ReserveSample(); | 1009 Sample* sample = sample_buffer->ReserveSample(); |
| 986 sample->Init(isolate, OS::GetCurrentTimeMicros(), state.tid); | 1010 sample->Init(isolate, OS::GetCurrentTimeMicros(), state.tid); |
| 987 uword stack_lower = 0; | 1011 uword stack_lower = 0; |
| 988 uword stack_upper = 0; | 1012 uword stack_upper = 0; |
| 989 isolate->GetStackBounds(&stack_lower, &stack_upper); | 1013 isolate->GetStackBounds(&stack_lower, &stack_upper); |
| 990 if ((stack_lower == 0) || (stack_upper == 0)) { | 1014 if ((stack_lower == 0) || (stack_upper == 0)) { |
| 991 stack_lower = 0; | 1015 stack_lower = 0; |
| 992 stack_upper = 0; | 1016 stack_upper = 0; |
| 993 } | 1017 } |
| 994 ProfilerSampleStackWalker stackWalker(sample, stack_lower, stack_upper, | 1018 ProfilerSampleStackWalker stackWalker(isolate->heap(), sample, stack_lower, |
| 995 state.pc, state.fp, state.sp); | 1019 stack_upper, state.pc, state.fp, |
| 1020 state.sp); | |
| 996 stackWalker.walk(); | 1021 stackWalker.walk(); |
| 997 } | 1022 } |
| 998 | 1023 |
| 999 | 1024 |
| 1000 } // namespace dart | 1025 } // namespace dart |
| OLD | NEW |