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/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" |
| 11 #include "vm/code_patcher.h" | 11 #include "vm/code_patcher.h" |
| 12 #include "vm/debugger.h" | |
| 12 #include "vm/instructions.h" | 13 #include "vm/instructions.h" |
| 13 #include "vm/isolate.h" | 14 #include "vm/isolate.h" |
| 14 #include "vm/json_stream.h" | 15 #include "vm/json_stream.h" |
| 15 #include "vm/lockers.h" | 16 #include "vm/lockers.h" |
| 17 #include "vm/message_handler.h" | |
| 16 #include "vm/native_symbol.h" | 18 #include "vm/native_symbol.h" |
| 17 #include "vm/object.h" | 19 #include "vm/object.h" |
| 18 #include "vm/os.h" | 20 #include "vm/os.h" |
| 19 #include "vm/profiler.h" | 21 #include "vm/profiler.h" |
| 20 #include "vm/reusable_handles.h" | 22 #include "vm/reusable_handles.h" |
| 21 #include "vm/signal_handler.h" | 23 #include "vm/signal_handler.h" |
| 22 #include "vm/simulator.h" | 24 #include "vm/simulator.h" |
| 23 #include "vm/stack_frame.h" | 25 #include "vm/stack_frame.h" |
| 24 | 26 |
| 25 namespace dart { | 27 namespace dart { |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 97 void Profiler::SetSamplePeriod(intptr_t period) { | 99 void Profiler::SetSamplePeriod(intptr_t period) { |
| 98 const int kMinimumProfilePeriod = 50; | 100 const int kMinimumProfilePeriod = 50; |
| 99 if (period < kMinimumProfilePeriod) { | 101 if (period < kMinimumProfilePeriod) { |
| 100 FLAG_profile_period = kMinimumProfilePeriod; | 102 FLAG_profile_period = kMinimumProfilePeriod; |
| 101 } else { | 103 } else { |
| 102 FLAG_profile_period = period; | 104 FLAG_profile_period = period; |
| 103 } | 105 } |
| 104 } | 106 } |
| 105 | 107 |
| 106 | 108 |
| 107 void Profiler::InitProfilingForIsolate(Isolate* isolate, bool shared_buffer) { | |
| 108 if (!FLAG_profile) { | |
| 109 return; | |
| 110 } | |
| 111 ASSERT(isolate == Isolate::Current()); | |
| 112 ASSERT(isolate != NULL); | |
| 113 ASSERT(sample_buffer_ != NULL); | |
| 114 { | |
| 115 MutexLocker profiler_data_lock(isolate->profiler_data_mutex()); | |
| 116 SampleBuffer* sample_buffer = sample_buffer_; | |
| 117 if (!shared_buffer) { | |
| 118 sample_buffer = new SampleBuffer(); | |
| 119 } | |
| 120 IsolateProfilerData* profiler_data = | |
| 121 new IsolateProfilerData(sample_buffer, !shared_buffer); | |
| 122 ASSERT(profiler_data != NULL); | |
| 123 isolate->set_profiler_data(profiler_data); | |
| 124 if (FLAG_trace_profiled_isolates) { | |
| 125 OS::Print("Profiler Setup %p %s\n", isolate, isolate->name()); | |
| 126 } | |
| 127 } | |
| 128 BeginExecution(isolate); | |
| 129 } | |
| 130 | |
| 131 | |
| 132 void Profiler::ShutdownProfilingForIsolate(Isolate* isolate) { | |
| 133 ASSERT(isolate != NULL); | |
| 134 if (!FLAG_profile) { | |
| 135 return; | |
| 136 } | |
| 137 // We do not have a current isolate. | |
| 138 ASSERT(Isolate::Current() == NULL); | |
| 139 { | |
| 140 MutexLocker profiler_data_lock(isolate->profiler_data_mutex()); | |
| 141 IsolateProfilerData* profiler_data = isolate->profiler_data(); | |
| 142 if (profiler_data == NULL) { | |
| 143 // Already freed. | |
| 144 return; | |
| 145 } | |
| 146 isolate->set_profiler_data(NULL); | |
| 147 delete profiler_data; | |
| 148 if (FLAG_trace_profiled_isolates) { | |
| 149 OS::Print("Profiler Shutdown %p %s\n", isolate, isolate->name()); | |
| 150 } | |
| 151 } | |
| 152 } | |
| 153 | |
| 154 | |
| 155 void Profiler::BeginExecution(Isolate* isolate) { | 109 void Profiler::BeginExecution(Isolate* isolate) { |
| 156 if (isolate == NULL) { | 110 if (isolate == NULL) { |
| 157 return; | 111 return; |
| 158 } | 112 } |
| 159 if (!FLAG_profile) { | 113 if (!FLAG_profile) { |
| 160 return; | 114 return; |
| 161 } | 115 } |
| 162 ASSERT(initialized_); | 116 ASSERT(initialized_); |
| 163 IsolateProfilerData* profiler_data = isolate->profiler_data(); | 117 Thread* thread = Thread::Current(); |
| 164 if (profiler_data == NULL) { | 118 if (thread == NULL) { |
| 165 return; | 119 return; |
| 166 } | 120 } |
| 167 Thread* thread = Thread::Current(); | 121 thread->SetThreadInterruptCallback(SampleThreadInterruptCallback); |
| 168 thread->SetThreadInterrupter(RecordSampleInterruptCallback, thread); | |
| 169 ThreadInterrupter::WakeUp(); | |
| 170 } | 122 } |
| 171 | 123 |
| 172 | 124 |
| 173 void Profiler::EndExecution(Isolate* isolate) { | 125 void Profiler::EndExecution(Isolate* isolate) { |
| 174 if (isolate == NULL) { | 126 if (isolate == NULL) { |
| 175 return; | 127 return; |
| 176 } | 128 } |
| 177 if (!FLAG_profile) { | 129 if (!FLAG_profile) { |
| 178 return; | 130 return; |
| 179 } | 131 } |
| 180 ASSERT(initialized_); | 132 ASSERT(initialized_); |
| 181 Thread* thread = Thread::Current(); | 133 Thread* thread = Thread::Current(); |
| 182 thread->SetThreadInterrupter(NULL, NULL); | 134 thread->SetThreadInterruptCallback(NULL); |
|
Ivan Posva
2015/10/28 08:27:47
It looks like we have several redundant ways of di
| |
| 183 } | 135 } |
| 184 | 136 |
| 185 | 137 |
| 186 IsolateProfilerData::IsolateProfilerData(SampleBuffer* sample_buffer, | |
| 187 bool own_sample_buffer) { | |
| 188 ASSERT(sample_buffer != NULL); | |
| 189 sample_buffer_ = sample_buffer; | |
| 190 own_sample_buffer_ = own_sample_buffer; | |
| 191 block_count_ = 0; | |
| 192 } | |
| 193 | |
| 194 | |
| 195 IsolateProfilerData::~IsolateProfilerData() { | |
| 196 if (own_sample_buffer_) { | |
| 197 delete sample_buffer_; | |
| 198 sample_buffer_ = NULL; | |
| 199 own_sample_buffer_ = false; | |
| 200 } | |
| 201 } | |
| 202 | |
| 203 | |
| 204 void IsolateProfilerData::Block() { | |
| 205 block_count_++; | |
| 206 } | |
| 207 | |
| 208 | |
| 209 void IsolateProfilerData::Unblock() { | |
| 210 block_count_--; | |
| 211 if (block_count_ < 0) { | |
| 212 FATAL("Too many calls to Dart_IsolateUnblocked."); | |
| 213 } | |
| 214 if (!blocked()) { | |
| 215 // We just unblocked this isolate, wake up the thread interrupter. | |
| 216 ThreadInterrupter::WakeUp(); | |
| 217 } | |
| 218 } | |
| 219 | |
| 220 | |
| 221 intptr_t Sample::pcs_length_ = 0; | 138 intptr_t Sample::pcs_length_ = 0; |
| 222 intptr_t Sample::instance_size_ = 0; | 139 intptr_t Sample::instance_size_ = 0; |
| 223 | 140 |
| 224 | 141 |
| 225 void Sample::InitOnce() { | 142 void Sample::InitOnce() { |
| 226 pcs_length_ = kSampleSize; | 143 pcs_length_ = kSampleSize; |
| 227 instance_size_ = | 144 instance_size_ = |
| 228 sizeof(Sample) + (sizeof(uword) * pcs_length_); // NOLINT. | 145 sizeof(Sample) + (sizeof(uword) * pcs_length_); // NOLINT. |
| 229 } | 146 } |
| 230 | 147 |
| (...skipping 579 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 810 | 727 |
| 811 if (in_dart_code) { | 728 if (in_dart_code) { |
| 812 // We can only trust the stack pointer if we are executing Dart code. | 729 // We can only trust the stack pointer if we are executing Dart code. |
| 813 // See http://dartbug.com/20421 for details. | 730 // See http://dartbug.com/20421 for details. |
| 814 CopyStackBuffer(sample, sp); | 731 CopyStackBuffer(sample, sp); |
| 815 } | 732 } |
| 816 | 733 |
| 817 if (FLAG_profile_vm) { | 734 if (FLAG_profile_vm) { |
| 818 // Always walk the native stack collecting both native and Dart frames. | 735 // Always walk the native stack collecting both native and Dart frames. |
| 819 native_stack_walker->walk(); | 736 native_stack_walker->walk(); |
| 820 } else if (exited_dart_code) { | 737 } else if (StubCode::HasBeenInitialized() && exited_dart_code) { |
| 821 // We have a valid exit frame info, use the Dart stack walker. | 738 // We have a valid exit frame info, use the Dart stack walker. |
| 822 dart_exit_stack_walker->walk(); | 739 dart_exit_stack_walker->walk(); |
| 823 } else if (in_dart_code) { | 740 } else if (StubCode::HasBeenInitialized() && in_dart_code) { |
| 824 // We are executing Dart code. We have frame pointers. | 741 // We are executing Dart code. We have frame pointers. |
| 825 dart_stack_walker->walk(); | 742 dart_stack_walker->walk(); |
| 826 } else { | 743 } else { |
| 827 sample->set_vm_tag(VMTag::kEmbedderTagId); | 744 sample->set_vm_tag(VMTag::kEmbedderTagId); |
| 828 sample->SetAt(0, pc); | 745 sample->SetAt(0, pc); |
| 829 } | 746 } |
| 830 | 747 |
| 831 #if defined(TARGET_OS_WINDOWS) | 748 #if defined(TARGET_OS_WINDOWS) |
| 832 // Use structured exception handling to trap guard page access. | 749 // Use structured exception handling to trap guard page access. |
| 833 } __except(GuardPageExceptionFilter(GetExceptionInformation())) { | 750 } __except(GuardPageExceptionFilter(GetExceptionInformation())) { |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 844 new_protect, | 761 new_protect, |
| 845 &old_protect); | 762 &old_protect); |
| 846 USE(success); | 763 USE(success); |
| 847 ASSERT(success); | 764 ASSERT(success); |
| 848 ASSERT(old_protect == PAGE_READWRITE); | 765 ASSERT(old_protect == PAGE_READWRITE); |
| 849 } | 766 } |
| 850 #endif | 767 #endif |
| 851 } | 768 } |
| 852 | 769 |
| 853 | 770 |
| 854 // Is |thread| executing Dart code? | |
| 855 static bool ExecutingDart(Thread* thread) { | |
| 856 ASSERT(thread != NULL); | |
| 857 return (thread->top_exit_frame_info() == 0) && | |
| 858 (thread->vm_tag() == VMTag::kDartTagId); | |
| 859 } | |
| 860 | |
| 861 | |
| 862 // Has |thread| exited Dart code? | |
| 863 static bool ExitedDart(Thread* thread) { | |
| 864 return (thread->top_exit_frame_info() != 0) && | |
| 865 (thread->vm_tag() != VMTag::kDartTagId); | |
| 866 } | |
| 867 | |
| 868 | |
| 869 // Get |isolate|'s stack boundary and verify that |sp| and |fp| are within | 771 // Get |isolate|'s stack boundary and verify that |sp| and |fp| are within |
| 870 // it. Return |false| if anything looks suspicious. | 772 // it. Return |false| if anything looks suspicious. |
| 871 static bool GetAndValidateIsolateStackBounds(Thread* thread, | 773 static bool GetAndValidateIsolateStackBounds(Thread* thread, |
| 774 uintptr_t fp, | |
| 872 uintptr_t sp, | 775 uintptr_t sp, |
| 873 uintptr_t fp, | |
| 874 uword* stack_lower, | 776 uword* stack_lower, |
| 875 uword* stack_upper) { | 777 uword* stack_upper) { |
| 876 ASSERT(thread != NULL); | 778 ASSERT(thread != NULL); |
| 877 Isolate* isolate = thread->isolate(); | 779 Isolate* isolate = thread->isolate(); |
| 878 ASSERT(isolate != NULL); | 780 ASSERT(isolate != NULL); |
| 879 ASSERT(stack_lower != NULL); | 781 ASSERT(stack_lower != NULL); |
| 880 ASSERT(stack_upper != NULL); | 782 ASSERT(stack_upper != NULL); |
| 881 #if defined(USING_SIMULATOR) | 783 #if defined(USING_SIMULATOR) |
| 882 const bool in_dart_code = ExecutingDart(thread); | 784 const bool in_dart_code = thread->IsExecutingDartCode(); |
| 883 if (in_dart_code) { | 785 if (in_dart_code) { |
| 884 Simulator* simulator = isolate->simulator(); | 786 Simulator* simulator = isolate->simulator(); |
| 885 *stack_lower = simulator->StackBase(); | 787 *stack_lower = simulator->StackBase(); |
| 886 *stack_upper = simulator->StackTop(); | 788 *stack_upper = simulator->StackTop(); |
| 887 } else if (!isolate->GetProfilerStackBounds(stack_lower, stack_upper)) { | 789 } else if (!isolate->GetProfilerStackBounds(stack_lower, stack_upper)) { |
| 888 // Could not get stack boundary. | 790 // Could not get stack boundary. |
| 889 return false; | 791 return false; |
| 890 } | 792 } |
| 891 if ((*stack_lower == 0) || (*stack_upper == 0)) { | 793 if ((*stack_lower == 0) || (*stack_upper == 0)) { |
| 892 return false; | 794 return false; |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 915 | 817 |
| 916 if ((fp < *stack_lower) || (fp >= *stack_upper)) { | 818 if ((fp < *stack_lower) || (fp >= *stack_upper)) { |
| 917 // Frame pointer is outside isolate stack boundary. | 819 // Frame pointer is outside isolate stack boundary. |
| 918 return false; | 820 return false; |
| 919 } | 821 } |
| 920 | 822 |
| 921 return true; | 823 return true; |
| 922 } | 824 } |
| 923 | 825 |
| 924 | 826 |
| 925 // Some simple sanity checking of |pc|, |sp|, and |fp|. | 827 // Some simple sanity checking of |pc|, |fp|, and |sp|. |
| 926 static bool InitialRegisterCheck(uintptr_t pc, uintptr_t sp, uintptr_t fp) { | 828 static bool InitialRegisterCheck(uintptr_t pc, uintptr_t fp, uintptr_t sp) { |
| 927 if ((sp == 0) || (fp == 0) || (pc == 0)) { | 829 if ((sp == 0) || (fp == 0) || (pc == 0)) { |
| 928 // None of these registers should be zero. | 830 // None of these registers should be zero. |
| 929 return false; | 831 return false; |
| 930 } | 832 } |
| 931 | 833 |
| 932 if (sp > fp) { | 834 if (sp > fp) { |
| 933 // Assuming the stack grows down, we should never have a stack pointer above | 835 // Assuming the stack grows down, we should never have a stack pointer above |
| 934 // the frame pointer. | 836 // the frame pointer. |
| 935 return false; | 837 return false; |
| 936 } | 838 } |
| 937 | 839 |
| 938 return true; | 840 return true; |
| 939 } | 841 } |
| 940 | 842 |
| 941 | 843 |
| 942 // Return |isolate|'s sample buffer. | |
| 943 static SampleBuffer* GetSampleBuffer(Isolate* isolate) { | |
| 944 IsolateProfilerData* profiler_data = isolate->profiler_data(); | |
| 945 if (profiler_data == NULL) { | |
| 946 // Profiler not initialized. | |
| 947 return NULL; | |
| 948 } | |
| 949 SampleBuffer* sample_buffer = profiler_data->sample_buffer(); | |
| 950 return sample_buffer; | |
| 951 } | |
| 952 | |
| 953 | |
| 954 static Sample* SetupSample(Thread* thread, | 844 static Sample* SetupSample(Thread* thread, |
| 955 SampleBuffer* sample_buffer, | 845 SampleBuffer* sample_buffer, |
| 956 ThreadId tid) { | 846 ThreadId tid) { |
| 957 ASSERT(thread != NULL); | 847 ASSERT(thread != NULL); |
| 958 Isolate* isolate = thread->isolate(); | 848 Isolate* isolate = thread->isolate(); |
| 959 ASSERT(sample_buffer != NULL); | 849 ASSERT(sample_buffer != NULL); |
| 960 Sample* sample = sample_buffer->ReserveSample(); | 850 Sample* sample = sample_buffer->ReserveSample(); |
| 961 sample->Init(isolate, OS::GetCurrentTimeMicros(), tid); | 851 sample->Init(isolate, OS::GetCurrentTimeMicros(), tid); |
| 962 uword vm_tag = thread->vm_tag(); | 852 uword vm_tag = thread->vm_tag(); |
| 963 #if defined(USING_SIMULATOR) | 853 #if defined(USING_SIMULATOR) |
| 964 // When running in the simulator, the runtime entry function address | 854 // When running in the simulator, the runtime entry function address |
| 965 // (stored as the vm tag) is the address of a redirect function. | 855 // (stored as the vm tag) is the address of a redirect function. |
| 966 // Attempt to find the real runtime entry function address and use that. | 856 // Attempt to find the real runtime entry function address and use that. |
| 967 uword redirect_vm_tag = Simulator::FunctionForRedirect(vm_tag); | 857 uword redirect_vm_tag = Simulator::FunctionForRedirect(vm_tag); |
| 968 if (redirect_vm_tag != 0) { | 858 if (redirect_vm_tag != 0) { |
| 969 vm_tag = redirect_vm_tag; | 859 vm_tag = redirect_vm_tag; |
| 970 } | 860 } |
| 971 #endif | 861 #endif |
| 972 sample->set_vm_tag(vm_tag); | 862 sample->set_vm_tag(vm_tag); |
| 973 sample->set_user_tag(isolate->user_tag()); | 863 sample->set_user_tag(isolate->user_tag()); |
| 974 return sample; | 864 return sample; |
| 975 } | 865 } |
| 976 | 866 |
| 977 | 867 |
| 978 static bool CheckIsolate(Isolate* isolate) { | 868 static bool CheckIsolate(Isolate* isolate) { |
| 979 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) { | 869 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) { |
| 980 // No isolate. | 870 // No isolate. |
| 981 return false; | 871 return false; |
| 982 } | 872 } |
| 983 ASSERT(isolate != Dart::vm_isolate()); | 873 return isolate != Dart::vm_isolate(); |
| 984 return true; | |
| 985 } | 874 } |
| 986 | 875 |
| 987 | 876 |
| 988 #if defined(TARGET_OS_WINDOWS) | 877 #if defined(TARGET_OS_WINDOWS) |
| 989 __declspec(noinline) | 878 __declspec(noinline) |
| 990 static uintptr_t GetProgramCounter() { | 879 static uintptr_t GetProgramCounter() { |
| 991 return reinterpret_cast<uintptr_t>(_ReturnAddress()); | 880 return reinterpret_cast<uintptr_t>(_ReturnAddress()); |
| 992 } | 881 } |
| 993 #else | 882 #else |
| 994 static uintptr_t __attribute__((noinline)) GetProgramCounter() { | 883 static uintptr_t __attribute__((noinline)) GetProgramCounter() { |
| 995 return reinterpret_cast<uintptr_t>( | 884 return reinterpret_cast<uintptr_t>( |
| 996 __builtin_extract_return_addr(__builtin_return_address(0))); | 885 __builtin_extract_return_addr(__builtin_return_address(0))); |
| 997 } | 886 } |
| 998 #endif | 887 #endif |
| 999 | 888 |
| 1000 void Profiler::RecordAllocation(Thread* thread, intptr_t cid) { | 889 void Profiler::SampleAllocation(Thread* thread, intptr_t cid) { |
| 1001 ASSERT(thread != NULL); | 890 ASSERT(thread != NULL); |
| 1002 Isolate* isolate = thread->isolate(); | 891 Isolate* isolate = thread->isolate(); |
| 1003 if (!CheckIsolate(isolate)) { | 892 if (!CheckIsolate(isolate)) { |
| 1004 return; | 893 return; |
| 1005 } | 894 } |
| 1006 | 895 |
| 1007 const bool exited_dart_code = ExitedDart(thread); | 896 const bool exited_dart_code = thread->HasExitedDartCode(); |
|
Ivan Posva
2015/10/28 08:27:47
Shouldn't this be an assert? The thread has better
Cutch
2015/10/28 14:39:19
This is called from Object::Allocate which means w
| |
| 1008 | 897 |
| 1009 SampleBuffer* sample_buffer = GetSampleBuffer(isolate); | 898 SampleBuffer* sample_buffer = Profiler::sample_buffer(); |
| 1010 if (sample_buffer == NULL) { | 899 if (sample_buffer == NULL) { |
| 1011 // Profiler not initialized. | 900 // Profiler not initialized. |
| 1012 return; | 901 return; |
| 1013 } | 902 } |
| 1014 | 903 |
| 1015 if (FLAG_profile_vm) { | 904 if (FLAG_profile_vm) { |
| 1016 uintptr_t sp = Isolate::GetCurrentStackPointer(); | 905 uintptr_t sp = Isolate::GetCurrentStackPointer(); |
| 1017 uintptr_t fp = 0; | 906 uintptr_t fp = 0; |
| 1018 uintptr_t pc = GetProgramCounter(); | 907 uintptr_t pc = GetProgramCounter(); |
| 1019 | 908 |
| 1020 COPY_FP_REGISTER(fp); | 909 COPY_FP_REGISTER(fp); |
| 1021 | 910 |
| 1022 uword stack_lower = 0; | 911 uword stack_lower = 0; |
| 1023 uword stack_upper = 0; | 912 uword stack_upper = 0; |
| 1024 | 913 |
| 1025 if (!InitialRegisterCheck(pc, sp, fp)) { | 914 if (!InitialRegisterCheck(pc, fp, sp)) { |
| 1026 return; | 915 return; |
| 1027 } | 916 } |
| 1028 | 917 |
| 1029 if (!GetAndValidateIsolateStackBounds(thread, | 918 if (!GetAndValidateIsolateStackBounds(thread, |
| 919 fp, | |
| 1030 sp, | 920 sp, |
| 1031 fp, | |
| 1032 &stack_lower, | 921 &stack_lower, |
| 1033 &stack_upper)) { | 922 &stack_upper)) { |
| 1034 // Could not get stack boundary. | 923 // Could not get stack boundary. |
| 1035 return; | 924 return; |
| 1036 } | 925 } |
| 1037 | 926 |
| 1038 Sample* sample = SetupSample(thread, | 927 Sample* sample = SetupSample(thread, |
| 1039 sample_buffer, | 928 sample_buffer, |
| 1040 OSThread::GetCurrentThreadId()); | 929 OSThread::GetCurrentThreadId()); |
| 1041 sample->SetAllocationCid(cid); | 930 sample->SetAllocationCid(cid); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 1064 Sample* sample = SetupSample(thread, | 953 Sample* sample = SetupSample(thread, |
| 1065 sample_buffer, | 954 sample_buffer, |
| 1066 OSThread::GetCurrentThreadId()); | 955 OSThread::GetCurrentThreadId()); |
| 1067 sample->SetAllocationCid(cid); | 956 sample->SetAllocationCid(cid); |
| 1068 sample->set_vm_tag(VMTag::kEmbedderTagId); | 957 sample->set_vm_tag(VMTag::kEmbedderTagId); |
| 1069 sample->SetAt(0, pc); | 958 sample->SetAt(0, pc); |
| 1070 } | 959 } |
| 1071 } | 960 } |
| 1072 | 961 |
| 1073 | 962 |
| 1074 void Profiler::RecordSampleInterruptCallback( | 963 void Profiler::SampleThread(Thread* thread, |
| 1075 const InterruptedThreadState& state, | 964 uintptr_t pc, |
| 1076 void* data) { | 965 uintptr_t fp, |
| 1077 Thread* thread = reinterpret_cast<Thread*>(data); | 966 uintptr_t sp) { |
| 967 ASSERT(thread != NULL); | |
| 1078 Isolate* isolate = thread->isolate(); | 968 Isolate* isolate = thread->isolate(); |
| 1079 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) { | 969 if (!CheckIsolate(isolate)) { |
| 1080 // No isolate. | |
| 1081 return; | |
| 1082 } | |
| 1083 ASSERT(isolate != Dart::vm_isolate()); | |
| 1084 | |
| 1085 SampleBuffer* sample_buffer = GetSampleBuffer(isolate); | |
| 1086 if (sample_buffer == NULL) { | |
| 1087 // Profiler not initialized. | |
| 1088 return; | 970 return; |
| 1089 } | 971 } |
| 1090 | 972 |
| 1091 const bool exited_dart_code = ExitedDart(thread); | 973 if (!thread->IsMutatorThread()) { |
| 1092 const bool in_dart_code = ExecutingDart(thread); | 974 // Not a mutator thread. |
| 1093 | 975 // TODO(johnmccutchan): Profile all threads with an isolate. |
| 1094 uintptr_t sp = 0; | |
| 1095 uintptr_t fp = state.fp; | |
| 1096 uintptr_t pc = state.pc; | |
| 1097 #if defined(USING_SIMULATOR) | |
| 1098 Simulator* simulator = NULL; | |
| 1099 #endif | |
| 1100 | |
| 1101 if (in_dart_code) { | |
| 1102 // If we're in Dart code, use the Dart stack pointer. | |
| 1103 #if defined(USING_SIMULATOR) | |
| 1104 simulator = isolate->simulator(); | |
| 1105 sp = simulator->get_register(SPREG); | |
| 1106 fp = simulator->get_register(FPREG); | |
| 1107 pc = simulator->get_pc(); | |
| 1108 #else | |
| 1109 sp = state.dsp; | |
| 1110 #endif | |
| 1111 } else { | |
| 1112 // If we're in runtime code, use the C stack pointer. | |
| 1113 sp = state.csp; | |
| 1114 } | |
| 1115 | |
| 1116 if (!InitialRegisterCheck(pc, sp, fp)) { | |
| 1117 return; | 976 return; |
| 1118 } | 977 } |
| 1119 | 978 |
| 1120 if (StubCode::InJumpToExceptionHandlerStub(pc)) { | 979 if (isolate->HasDebugger()) { |
|
Ivan Posva
2015/10/28 08:27:47
Please add a comment that this is really only rele
Cutch
2015/10/28 14:39:18
Done.
| |
| 1121 // The JumpToExceptionHandler stub manually adjusts the stack pointer, | 980 Debugger* debugger = isolate->debugger(); |
| 1122 // frame pointer, and some isolate state before jumping to a catch entry. | 981 if (debugger->IsPaused()) { |
| 1123 // It is not safe to walk the stack when executing this stub. | 982 // Mutator is paused at breakpoint. |
| 983 return; | |
| 984 } | |
| 985 } | |
| 986 | |
| 987 MessageHandler* msg_handler = isolate->message_handler(); | |
|
Ivan Posva
2015/10/28 08:27:47
This and the debugger check are only relevant for
Cutch
2015/10/28 14:39:18
I've factored both of these checks into a helper f
| |
| 988 if ((msg_handler != NULL) && | |
| 989 (msg_handler->paused_on_start() || | |
| 990 msg_handler->paused_on_exit())) { | |
| 991 // Isolate is paused at start / exit. | |
| 1124 return; | 992 return; |
| 1125 } | 993 } |
| 1126 | 994 |
| 995 const bool exited_dart_code = thread->HasExitedDartCode(); | |
|
Ivan Posva
2015/10/28 08:27:47
Is there any particular reason why this should be
Cutch
2015/10/28 14:39:19
No. Moved down closer to their use.
| |
| 996 const bool in_dart_code = thread->IsExecutingDartCode(); | |
| 997 | |
| 1127 uword stack_lower = 0; | 998 uword stack_lower = 0; |
| 1128 uword stack_upper = 0; | 999 uword stack_upper = 0; |
| 1129 if (!GetAndValidateIsolateStackBounds(thread, | 1000 if (!GetAndValidateIsolateStackBounds(thread, |
| 1001 fp, | |
| 1130 sp, | 1002 sp, |
| 1131 fp, | |
| 1132 &stack_lower, | 1003 &stack_lower, |
| 1133 &stack_upper)) { | 1004 &stack_upper)) { |
| 1134 // Could not get stack boundary. | 1005 // Could not get stack boundary. |
| 1135 return; | 1006 return; |
| 1136 } | 1007 } |
| 1137 | 1008 |
| 1138 // At this point we have a valid stack boundary for this isolate and | 1009 // At this point we have a valid stack boundary for this isolate and |
| 1139 // know that our initial stack and frame pointers are within the boundary. | 1010 // know that our initial stack and frame pointers are within the boundary. |
| 1011 SampleBuffer* sample_buffer = Profiler::sample_buffer(); | |
| 1012 if (sample_buffer == NULL) { | |
| 1013 // Profiler not initialized. | |
| 1014 return; | |
| 1015 } | |
| 1140 | 1016 |
| 1141 // Setup sample. | 1017 // Setup sample. |
| 1142 Sample* sample = SetupSample(thread, | 1018 Sample* sample = SetupSample(thread, |
| 1143 sample_buffer, | 1019 sample_buffer, |
| 1144 OSThread::GetCurrentThreadId()); | 1020 OSThread::GetCurrentThreadId()); |
| 1145 // Increment counter for vm tag. | 1021 // Increment counter for vm tag. |
| 1146 VMTagCounters* counters = isolate->vm_tag_counters(); | 1022 VMTagCounters* counters = isolate->vm_tag_counters(); |
| 1147 ASSERT(counters != NULL); | 1023 ASSERT(counters != NULL); |
| 1148 counters->Increment(sample->vm_tag()); | 1024 counters->Increment(sample->vm_tag()); |
| 1149 | 1025 |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 1177 sample, | 1053 sample, |
| 1178 &native_stack_walker, | 1054 &native_stack_walker, |
| 1179 &dart_exit_stack_walker, | 1055 &dart_exit_stack_walker, |
| 1180 &dart_stack_walker, | 1056 &dart_stack_walker, |
| 1181 pc, | 1057 pc, |
| 1182 fp, | 1058 fp, |
| 1183 sp); | 1059 sp); |
| 1184 } | 1060 } |
| 1185 | 1061 |
| 1186 | 1062 |
| 1063 void Profiler::SampleThreadInterruptCallback( | |
| 1064 Thread* thread, | |
| 1065 const InterruptedThreadState& state) { | |
| 1066 const bool in_dart_code = thread->IsExecutingDartCode(); | |
| 1067 | |
| 1068 uintptr_t sp = 0; | |
| 1069 uintptr_t fp = state.fp; | |
| 1070 uintptr_t pc = state.pc; | |
| 1071 #if defined(USING_SIMULATOR) | |
| 1072 Simulator* simulator = NULL; | |
| 1073 #endif | |
| 1074 | |
| 1075 if (StubCode::HasBeenInitialized() && | |
| 1076 StubCode::InJumpToExceptionHandlerStub(pc)) { | |
| 1077 // The JumpToExceptionHandler stub manually adjusts the stack pointer, | |
| 1078 // frame pointer, and some isolate state before jumping to a catch entry. | |
| 1079 // It is not safe to walk the stack when executing this stub. | |
| 1080 return; | |
| 1081 } | |
| 1082 | |
| 1083 if (in_dart_code) { | |
| 1084 // If we're in Dart code, use the Dart stack pointer. | |
| 1085 #if defined(USING_SIMULATOR) | |
| 1086 simulator = isolate->simulator(); | |
| 1087 sp = simulator->get_register(SPREG); | |
| 1088 fp = simulator->get_register(FPREG); | |
| 1089 pc = simulator->get_pc(); | |
| 1090 #else | |
| 1091 sp = state.dsp; | |
| 1092 #endif | |
| 1093 } else { | |
| 1094 // If we're in runtime code, use the C stack pointer. | |
| 1095 sp = state.csp; | |
| 1096 } | |
| 1097 | |
| 1098 if (!InitialRegisterCheck(pc, fp, sp)) { | |
| 1099 return; | |
| 1100 } | |
| 1101 | |
| 1102 SampleThread(thread, pc, fp, sp); | |
| 1103 } | |
| 1104 | |
| 1105 | |
| 1187 ProcessedSampleBuffer* SampleBuffer::BuildProcessedSampleBuffer( | 1106 ProcessedSampleBuffer* SampleBuffer::BuildProcessedSampleBuffer( |
| 1188 SampleFilter* filter) { | 1107 SampleFilter* filter) { |
| 1189 ASSERT(filter != NULL); | 1108 ASSERT(filter != NULL); |
| 1190 Thread* thread = Thread::Current(); | 1109 Thread* thread = Thread::Current(); |
| 1191 Zone* zone = thread->zone(); | 1110 Zone* zone = thread->zone(); |
| 1192 | 1111 |
| 1193 ProcessedSampleBuffer* buffer = new(zone) ProcessedSampleBuffer(); | 1112 ProcessedSampleBuffer* buffer = new(zone) ProcessedSampleBuffer(); |
| 1194 | 1113 |
| 1195 const intptr_t length = capacity(); | 1114 const intptr_t length = capacity(); |
| 1196 for (intptr_t i = 0; i < length; i++) { | 1115 for (intptr_t i = 0; i < length; i++) { |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1394 uword pc) { | 1313 uword pc) { |
| 1395 return vm_isolate->heap()->CodeContains(pc) | 1314 return vm_isolate->heap()->CodeContains(pc) |
| 1396 || isolate->heap()->CodeContains(pc); | 1315 || isolate->heap()->CodeContains(pc); |
| 1397 } | 1316 } |
| 1398 | 1317 |
| 1399 | 1318 |
| 1400 ProcessedSampleBuffer::ProcessedSampleBuffer() { | 1319 ProcessedSampleBuffer::ProcessedSampleBuffer() { |
| 1401 } | 1320 } |
| 1402 | 1321 |
| 1403 } // namespace dart | 1322 } // namespace dart |
| OLD | NEW |