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) { | |
156 if (isolate == NULL) { | |
157 return; | |
158 } | |
159 if (!FLAG_profile) { | |
160 return; | |
161 } | |
162 ASSERT(initialized_); | |
163 IsolateProfilerData* profiler_data = isolate->profiler_data(); | |
164 if (profiler_data == NULL) { | |
165 return; | |
166 } | |
167 Thread* thread = Thread::Current(); | |
168 thread->SetThreadInterrupter(RecordSampleInterruptCallback, thread); | |
169 ThreadInterrupter::WakeUp(); | |
170 } | |
171 | |
172 | |
173 void Profiler::EndExecution(Isolate* isolate) { | |
174 if (isolate == NULL) { | |
175 return; | |
176 } | |
177 if (!FLAG_profile) { | |
178 return; | |
179 } | |
180 ASSERT(initialized_); | |
181 Thread* thread = Thread::Current(); | |
182 thread->SetThreadInterrupter(NULL, NULL); | |
183 } | |
184 | |
185 | |
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; | 109 intptr_t Sample::pcs_length_ = 0; |
222 intptr_t Sample::instance_size_ = 0; | 110 intptr_t Sample::instance_size_ = 0; |
223 | 111 |
224 | 112 |
225 void Sample::InitOnce() { | 113 void Sample::InitOnce() { |
226 pcs_length_ = kSampleSize; | 114 pcs_length_ = kSampleSize; |
227 instance_size_ = | 115 instance_size_ = |
228 sizeof(Sample) + (sizeof(uword) * pcs_length_); // NOLINT. | 116 sizeof(Sample) + (sizeof(uword) * pcs_length_); // NOLINT. |
229 } | 117 } |
230 | 118 |
(...skipping 579 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
810 | 698 |
811 if (in_dart_code) { | 699 if (in_dart_code) { |
812 // We can only trust the stack pointer if we are executing Dart code. | 700 // We can only trust the stack pointer if we are executing Dart code. |
813 // See http://dartbug.com/20421 for details. | 701 // See http://dartbug.com/20421 for details. |
814 CopyStackBuffer(sample, sp); | 702 CopyStackBuffer(sample, sp); |
815 } | 703 } |
816 | 704 |
817 if (FLAG_profile_vm) { | 705 if (FLAG_profile_vm) { |
818 // Always walk the native stack collecting both native and Dart frames. | 706 // Always walk the native stack collecting both native and Dart frames. |
819 native_stack_walker->walk(); | 707 native_stack_walker->walk(); |
820 } else if (exited_dart_code) { | 708 } else if (StubCode::HasBeenInitialized() && exited_dart_code) { |
821 // We have a valid exit frame info, use the Dart stack walker. | 709 // We have a valid exit frame info, use the Dart stack walker. |
822 dart_exit_stack_walker->walk(); | 710 dart_exit_stack_walker->walk(); |
823 } else if (in_dart_code) { | 711 } else if (StubCode::HasBeenInitialized() && in_dart_code) { |
824 // We are executing Dart code. We have frame pointers. | 712 // We are executing Dart code. We have frame pointers. |
825 dart_stack_walker->walk(); | 713 dart_stack_walker->walk(); |
826 } else { | 714 } else { |
827 sample->set_vm_tag(VMTag::kEmbedderTagId); | 715 sample->set_vm_tag(VMTag::kEmbedderTagId); |
828 sample->SetAt(0, pc); | 716 sample->SetAt(0, pc); |
829 } | 717 } |
830 | 718 |
831 #if defined(TARGET_OS_WINDOWS) | 719 #if defined(TARGET_OS_WINDOWS) |
832 // Use structured exception handling to trap guard page access. | 720 // Use structured exception handling to trap guard page access. |
833 } __except(GuardPageExceptionFilter(GetExceptionInformation())) { | 721 } __except(GuardPageExceptionFilter(GetExceptionInformation())) { |
(...skipping 10 matching lines...) Expand all Loading... | |
844 new_protect, | 732 new_protect, |
845 &old_protect); | 733 &old_protect); |
846 USE(success); | 734 USE(success); |
847 ASSERT(success); | 735 ASSERT(success); |
848 ASSERT(old_protect == PAGE_READWRITE); | 736 ASSERT(old_protect == PAGE_READWRITE); |
849 } | 737 } |
850 #endif | 738 #endif |
851 } | 739 } |
852 | 740 |
853 | 741 |
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 | 742 // Get |isolate|'s stack boundary and verify that |sp| and |fp| are within |
870 // it. Return |false| if anything looks suspicious. | 743 // it. Return |false| if anything looks suspicious. |
871 static bool GetAndValidateIsolateStackBounds(Thread* thread, | 744 static bool GetAndValidateIsolateStackBounds(Thread* thread, |
745 uintptr_t fp, | |
872 uintptr_t sp, | 746 uintptr_t sp, |
873 uintptr_t fp, | |
874 uword* stack_lower, | 747 uword* stack_lower, |
875 uword* stack_upper) { | 748 uword* stack_upper) { |
876 ASSERT(thread != NULL); | 749 ASSERT(thread != NULL); |
877 Isolate* isolate = thread->isolate(); | 750 Isolate* isolate = thread->isolate(); |
878 ASSERT(isolate != NULL); | 751 ASSERT(isolate != NULL); |
879 ASSERT(stack_lower != NULL); | 752 ASSERT(stack_lower != NULL); |
880 ASSERT(stack_upper != NULL); | 753 ASSERT(stack_upper != NULL); |
881 #if defined(USING_SIMULATOR) | 754 #if defined(USING_SIMULATOR) |
882 const bool in_dart_code = ExecutingDart(thread); | 755 const bool in_dart_code = thread->IsExecutingDartCode(); |
883 if (in_dart_code) { | 756 if (in_dart_code) { |
884 Simulator* simulator = isolate->simulator(); | 757 Simulator* simulator = isolate->simulator(); |
885 *stack_lower = simulator->StackBase(); | 758 *stack_lower = simulator->StackBase(); |
886 *stack_upper = simulator->StackTop(); | 759 *stack_upper = simulator->StackTop(); |
887 } else if (!isolate->GetProfilerStackBounds(stack_lower, stack_upper)) { | 760 } else if (!isolate->GetProfilerStackBounds(stack_lower, stack_upper)) { |
888 // Could not get stack boundary. | 761 // Could not get stack boundary. |
889 return false; | 762 return false; |
890 } | 763 } |
891 if ((*stack_lower == 0) || (*stack_upper == 0)) { | 764 if ((*stack_lower == 0) || (*stack_upper == 0)) { |
892 return false; | 765 return false; |
(...skipping 22 matching lines...) Expand all Loading... | |
915 | 788 |
916 if ((fp < *stack_lower) || (fp >= *stack_upper)) { | 789 if ((fp < *stack_lower) || (fp >= *stack_upper)) { |
917 // Frame pointer is outside isolate stack boundary. | 790 // Frame pointer is outside isolate stack boundary. |
918 return false; | 791 return false; |
919 } | 792 } |
920 | 793 |
921 return true; | 794 return true; |
922 } | 795 } |
923 | 796 |
924 | 797 |
925 // Some simple sanity checking of |pc|, |sp|, and |fp|. | 798 // Some simple sanity checking of |pc|, |fp|, and |sp|. |
926 static bool InitialRegisterCheck(uintptr_t pc, uintptr_t sp, uintptr_t fp) { | 799 static bool InitialRegisterCheck(uintptr_t pc, uintptr_t fp, uintptr_t sp) { |
927 if ((sp == 0) || (fp == 0) || (pc == 0)) { | 800 if ((sp == 0) || (fp == 0) || (pc == 0)) { |
928 // None of these registers should be zero. | 801 // None of these registers should be zero. |
929 return false; | 802 return false; |
930 } | 803 } |
931 | 804 |
932 if (sp > fp) { | 805 if (sp > fp) { |
933 // Assuming the stack grows down, we should never have a stack pointer above | 806 // Assuming the stack grows down, we should never have a stack pointer above |
934 // the frame pointer. | 807 // the frame pointer. |
935 return false; | 808 return false; |
936 } | 809 } |
937 | 810 |
938 return true; | 811 return true; |
939 } | 812 } |
940 | 813 |
941 | 814 |
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, | 815 static Sample* SetupSample(Thread* thread, |
955 SampleBuffer* sample_buffer, | 816 SampleBuffer* sample_buffer, |
956 ThreadId tid) { | 817 ThreadId tid) { |
957 ASSERT(thread != NULL); | 818 ASSERT(thread != NULL); |
958 Isolate* isolate = thread->isolate(); | 819 Isolate* isolate = thread->isolate(); |
959 ASSERT(sample_buffer != NULL); | 820 ASSERT(sample_buffer != NULL); |
960 Sample* sample = sample_buffer->ReserveSample(); | 821 Sample* sample = sample_buffer->ReserveSample(); |
961 sample->Init(isolate, OS::GetCurrentTimeMicros(), tid); | 822 sample->Init(isolate, OS::GetCurrentTimeMicros(), tid); |
962 uword vm_tag = thread->vm_tag(); | 823 uword vm_tag = thread->vm_tag(); |
963 #if defined(USING_SIMULATOR) | 824 #if defined(USING_SIMULATOR) |
964 // When running in the simulator, the runtime entry function address | 825 // When running in the simulator, the runtime entry function address |
965 // (stored as the vm tag) is the address of a redirect function. | 826 // (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. | 827 // Attempt to find the real runtime entry function address and use that. |
967 uword redirect_vm_tag = Simulator::FunctionForRedirect(vm_tag); | 828 uword redirect_vm_tag = Simulator::FunctionForRedirect(vm_tag); |
968 if (redirect_vm_tag != 0) { | 829 if (redirect_vm_tag != 0) { |
969 vm_tag = redirect_vm_tag; | 830 vm_tag = redirect_vm_tag; |
970 } | 831 } |
971 #endif | 832 #endif |
972 sample->set_vm_tag(vm_tag); | 833 sample->set_vm_tag(vm_tag); |
973 sample->set_user_tag(isolate->user_tag()); | 834 sample->set_user_tag(isolate->user_tag()); |
974 return sample; | 835 return sample; |
975 } | 836 } |
976 | 837 |
977 | 838 |
978 static bool CheckIsolate(Isolate* isolate) { | 839 static bool CheckIsolate(Isolate* isolate) { |
979 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) { | 840 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) { |
980 // No isolate. | 841 // No isolate. |
981 return false; | 842 return false; |
982 } | 843 } |
983 ASSERT(isolate != Dart::vm_isolate()); | 844 return isolate != Dart::vm_isolate(); |
984 return true; | |
985 } | 845 } |
986 | 846 |
987 | 847 |
988 #if defined(TARGET_OS_WINDOWS) | 848 #if defined(TARGET_OS_WINDOWS) |
989 __declspec(noinline) | 849 __declspec(noinline) |
990 static uintptr_t GetProgramCounter() { | 850 static uintptr_t GetProgramCounter() { |
991 return reinterpret_cast<uintptr_t>(_ReturnAddress()); | 851 return reinterpret_cast<uintptr_t>(_ReturnAddress()); |
992 } | 852 } |
993 #else | 853 #else |
994 static uintptr_t __attribute__((noinline)) GetProgramCounter() { | 854 static uintptr_t __attribute__((noinline)) GetProgramCounter() { |
995 return reinterpret_cast<uintptr_t>( | 855 return reinterpret_cast<uintptr_t>( |
996 __builtin_extract_return_addr(__builtin_return_address(0))); | 856 __builtin_extract_return_addr(__builtin_return_address(0))); |
997 } | 857 } |
998 #endif | 858 #endif |
999 | 859 |
1000 void Profiler::RecordAllocation(Thread* thread, intptr_t cid) { | 860 void Profiler::SampleAllocation(Thread* thread, intptr_t cid) { |
1001 ASSERT(thread != NULL); | 861 ASSERT(thread != NULL); |
1002 Isolate* isolate = thread->isolate(); | 862 Isolate* isolate = thread->isolate(); |
1003 if (!CheckIsolate(isolate)) { | 863 if (!CheckIsolate(isolate)) { |
1004 return; | 864 return; |
1005 } | 865 } |
1006 | 866 |
1007 const bool exited_dart_code = ExitedDart(thread); | 867 const bool exited_dart_code = thread->HasExitedDartCode(); |
1008 | 868 |
1009 SampleBuffer* sample_buffer = GetSampleBuffer(isolate); | 869 SampleBuffer* sample_buffer = Profiler::sample_buffer(); |
1010 if (sample_buffer == NULL) { | 870 if (sample_buffer == NULL) { |
1011 // Profiler not initialized. | 871 // Profiler not initialized. |
1012 return; | 872 return; |
1013 } | 873 } |
1014 | 874 |
1015 if (FLAG_profile_vm) { | 875 if (FLAG_profile_vm) { |
1016 uintptr_t sp = Isolate::GetCurrentStackPointer(); | 876 uintptr_t sp = Isolate::GetCurrentStackPointer(); |
1017 uintptr_t fp = 0; | 877 uintptr_t fp = 0; |
1018 uintptr_t pc = GetProgramCounter(); | 878 uintptr_t pc = GetProgramCounter(); |
1019 | 879 |
1020 COPY_FP_REGISTER(fp); | 880 COPY_FP_REGISTER(fp); |
1021 | 881 |
1022 uword stack_lower = 0; | 882 uword stack_lower = 0; |
1023 uword stack_upper = 0; | 883 uword stack_upper = 0; |
1024 | 884 |
1025 if (!InitialRegisterCheck(pc, sp, fp)) { | 885 if (!InitialRegisterCheck(pc, fp, sp)) { |
1026 return; | 886 return; |
1027 } | 887 } |
1028 | 888 |
1029 if (!GetAndValidateIsolateStackBounds(thread, | 889 if (!GetAndValidateIsolateStackBounds(thread, |
890 fp, | |
1030 sp, | 891 sp, |
1031 fp, | |
1032 &stack_lower, | 892 &stack_lower, |
1033 &stack_upper)) { | 893 &stack_upper)) { |
1034 // Could not get stack boundary. | 894 // Could not get stack boundary. |
1035 return; | 895 return; |
1036 } | 896 } |
1037 | 897 |
1038 Sample* sample = SetupSample(thread, | 898 Sample* sample = SetupSample(thread, |
1039 sample_buffer, | 899 sample_buffer, |
1040 OSThread::GetCurrentThreadId()); | 900 OSThread::GetCurrentThreadId()); |
1041 sample->SetAllocationCid(cid); | 901 sample->SetAllocationCid(cid); |
(...skipping 22 matching lines...) Expand all Loading... | |
1064 Sample* sample = SetupSample(thread, | 924 Sample* sample = SetupSample(thread, |
1065 sample_buffer, | 925 sample_buffer, |
1066 OSThread::GetCurrentThreadId()); | 926 OSThread::GetCurrentThreadId()); |
1067 sample->SetAllocationCid(cid); | 927 sample->SetAllocationCid(cid); |
1068 sample->set_vm_tag(VMTag::kEmbedderTagId); | 928 sample->set_vm_tag(VMTag::kEmbedderTagId); |
1069 sample->SetAt(0, pc); | 929 sample->SetAt(0, pc); |
1070 } | 930 } |
1071 } | 931 } |
1072 | 932 |
1073 | 933 |
1074 void Profiler::RecordSampleInterruptCallback( | 934 void Profiler::SampleThread(Thread* thread, |
1075 const InterruptedThreadState& state, | 935 uintptr_t pc, |
1076 void* data) { | 936 uintptr_t fp, |
1077 Thread* thread = reinterpret_cast<Thread*>(data); | 937 uintptr_t sp) { |
938 ASSERT(thread != NULL); | |
1078 Isolate* isolate = thread->isolate(); | 939 Isolate* isolate = thread->isolate(); |
1079 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) { | 940 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; | 941 return; |
1089 } | 942 } |
1090 | 943 |
1091 const bool exited_dart_code = ExitedDart(thread); | 944 if (!thread->IsMutatorThread()) { |
1092 const bool in_dart_code = ExecutingDart(thread); | 945 // Not a mutator thread. |
1093 | 946 // 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; | 947 return; |
1118 } | 948 } |
1119 | 949 |
1120 if (StubCode::InJumpToExceptionHandlerStub(pc)) { | 950 if (!ShouldSampleMutator(thread, isolate)) { |
1121 // The JumpToExceptionHandler stub manually adjusts the stack pointer, | 951 // Mutator shouldn't be sampled. |
1122 // frame pointer, and some isolate state before jumping to a catch entry. | |
1123 // It is not safe to walk the stack when executing this stub. | |
1124 return; | 952 return; |
1125 } | 953 } |
1126 | 954 |
1127 uword stack_lower = 0; | 955 uword stack_lower = 0; |
1128 uword stack_upper = 0; | 956 uword stack_upper = 0; |
1129 if (!GetAndValidateIsolateStackBounds(thread, | 957 if (!GetAndValidateIsolateStackBounds(thread, |
958 fp, | |
1130 sp, | 959 sp, |
1131 fp, | |
1132 &stack_lower, | 960 &stack_lower, |
1133 &stack_upper)) { | 961 &stack_upper)) { |
1134 // Could not get stack boundary. | 962 // Could not get stack boundary. |
1135 return; | 963 return; |
1136 } | 964 } |
1137 | 965 |
1138 // At this point we have a valid stack boundary for this isolate and | 966 // 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. | 967 // know that our initial stack and frame pointers are within the boundary. |
968 SampleBuffer* sample_buffer = Profiler::sample_buffer(); | |
969 if (sample_buffer == NULL) { | |
970 // Profiler not initialized. | |
971 return; | |
972 } | |
1140 | 973 |
1141 // Setup sample. | 974 // Setup sample. |
1142 Sample* sample = SetupSample(thread, | 975 Sample* sample = SetupSample(thread, |
1143 sample_buffer, | 976 sample_buffer, |
1144 OSThread::GetCurrentThreadId()); | 977 OSThread::GetCurrentThreadId()); |
1145 // Increment counter for vm tag. | 978 // Increment counter for vm tag. |
1146 VMTagCounters* counters = isolate->vm_tag_counters(); | 979 VMTagCounters* counters = isolate->vm_tag_counters(); |
1147 ASSERT(counters != NULL); | 980 ASSERT(counters != NULL); |
1148 counters->Increment(sample->vm_tag()); | 981 counters->Increment(sample->vm_tag()); |
1149 | 982 |
(...skipping 13 matching lines...) Expand all Loading... | |
1163 | 996 |
1164 ProfilerDartStackWalker dart_stack_walker(isolate, | 997 ProfilerDartStackWalker dart_stack_walker(isolate, |
1165 sample, | 998 sample, |
1166 sample_buffer, | 999 sample_buffer, |
1167 stack_lower, | 1000 stack_lower, |
1168 stack_upper, | 1001 stack_upper, |
1169 pc, | 1002 pc, |
1170 fp, | 1003 fp, |
1171 sp); | 1004 sp); |
1172 | 1005 |
1006 const bool exited_dart_code = thread->HasExitedDartCode(); | |
1007 const bool in_dart_code = thread->IsExecutingDartCode(); | |
1008 | |
1173 // All memory access is done inside CollectSample. | 1009 // All memory access is done inside CollectSample. |
1174 CollectSample(isolate, | 1010 CollectSample(isolate, |
1175 exited_dart_code, | 1011 exited_dart_code, |
1176 in_dart_code, | 1012 in_dart_code, |
1177 sample, | 1013 sample, |
1178 &native_stack_walker, | 1014 &native_stack_walker, |
1179 &dart_exit_stack_walker, | 1015 &dart_exit_stack_walker, |
1180 &dart_stack_walker, | 1016 &dart_stack_walker, |
1181 pc, | 1017 pc, |
1182 fp, | 1018 fp, |
1183 sp); | 1019 sp); |
1184 } | 1020 } |
1185 | 1021 |
1186 | 1022 |
1023 bool Profiler::ShouldSampleMutator(Thread* thread, Isolate* isolate) { | |
1024 ASSERT(thread != NULL); | |
1025 ASSERT(isolate != NULL); | |
1026 | |
1027 // During isolate initialization we may get a tick before the debugger has | |
1028 // been setup. | |
1029 if (isolate->HasDebugger()) { | |
1030 Debugger* debugger = isolate->debugger(); | |
1031 if (debugger->IsPaused()) { | |
Ivan Posva
2015/10/28 19:31:53
Is this still needed given the fact that the debug
Cutch
2015/10/28 19:50:33
This whole function is now gone.
| |
1032 // Mutator is paused at breakpoint. | |
1033 return false; | |
1034 } | |
1035 } | |
1036 | |
1037 // Similarly, we might get a tick before the message handler is setup. | |
1038 MessageHandler* msg_handler = isolate->message_handler(); | |
1039 if ((msg_handler != NULL) && | |
1040 (msg_handler->paused_on_start() || | |
Ivan Posva
2015/10/28 19:31:53
If the isolate is paused on start/exit then it is
Cutch
2015/10/28 19:50:33
Done.
| |
1041 msg_handler->paused_on_exit())) { | |
1042 // Isolate is paused at start / exit. | |
1043 return false; | |
1044 } | |
1045 | |
1046 return true; | |
1047 } | |
1048 | |
1049 | |
1050 void Profiler::SampleThreadInterruptCallback( | |
1051 Thread* thread, | |
1052 const InterruptedThreadState& state) { | |
1053 const bool in_dart_code = thread->IsExecutingDartCode(); | |
1054 | |
1055 uintptr_t sp = 0; | |
1056 uintptr_t fp = state.fp; | |
1057 uintptr_t pc = state.pc; | |
1058 #if defined(USING_SIMULATOR) | |
1059 Simulator* simulator = NULL; | |
1060 #endif | |
1061 | |
1062 if (StubCode::HasBeenInitialized() && | |
1063 StubCode::InJumpToExceptionHandlerStub(pc)) { | |
1064 // The JumpToExceptionHandler stub manually adjusts the stack pointer, | |
1065 // frame pointer, and some isolate state before jumping to a catch entry. | |
1066 // It is not safe to walk the stack when executing this stub. | |
1067 return; | |
1068 } | |
1069 | |
1070 if (in_dart_code) { | |
1071 // If we're in Dart code, use the Dart stack pointer. | |
1072 #if defined(USING_SIMULATOR) | |
1073 simulator = isolate->simulator(); | |
1074 sp = simulator->get_register(SPREG); | |
1075 fp = simulator->get_register(FPREG); | |
1076 pc = simulator->get_pc(); | |
1077 #else | |
1078 sp = state.dsp; | |
1079 #endif | |
1080 } else { | |
1081 // If we're in runtime code, use the C stack pointer. | |
1082 sp = state.csp; | |
1083 } | |
1084 | |
1085 if (!InitialRegisterCheck(pc, fp, sp)) { | |
1086 return; | |
1087 } | |
1088 | |
1089 SampleThread(thread, pc, fp, sp); | |
1090 } | |
1091 | |
1092 | |
1187 ProcessedSampleBuffer* SampleBuffer::BuildProcessedSampleBuffer( | 1093 ProcessedSampleBuffer* SampleBuffer::BuildProcessedSampleBuffer( |
1188 SampleFilter* filter) { | 1094 SampleFilter* filter) { |
1189 ASSERT(filter != NULL); | 1095 ASSERT(filter != NULL); |
1190 Thread* thread = Thread::Current(); | 1096 Thread* thread = Thread::Current(); |
1191 Zone* zone = thread->zone(); | 1097 Zone* zone = thread->zone(); |
1192 | 1098 |
1193 ProcessedSampleBuffer* buffer = new(zone) ProcessedSampleBuffer(); | 1099 ProcessedSampleBuffer* buffer = new(zone) ProcessedSampleBuffer(); |
1194 | 1100 |
1195 const intptr_t length = capacity(); | 1101 const intptr_t length = capacity(); |
1196 for (intptr_t i = 0; i < length; i++) { | 1102 for (intptr_t i = 0; i < length; i++) { |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1394 uword pc) { | 1300 uword pc) { |
1395 return vm_isolate->heap()->CodeContains(pc) | 1301 return vm_isolate->heap()->CodeContains(pc) |
1396 || isolate->heap()->CodeContains(pc); | 1302 || isolate->heap()->CodeContains(pc); |
1397 } | 1303 } |
1398 | 1304 |
1399 | 1305 |
1400 ProcessedSampleBuffer::ProcessedSampleBuffer() { | 1306 ProcessedSampleBuffer::ProcessedSampleBuffer() { |
1401 } | 1307 } |
1402 | 1308 |
1403 } // namespace dart | 1309 } // namespace dart |
OLD | NEW |