| 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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 "Always collect native stack traces."); | 46 "Always collect native stack traces."); |
| 47 #else | 47 #else |
| 48 DEFINE_FLAG(bool, profile_vm, false, | 48 DEFINE_FLAG(bool, profile_vm, false, |
| 49 "Always collect native stack traces."); | 49 "Always collect native stack traces."); |
| 50 #endif | 50 #endif |
| 51 | 51 |
| 52 #ifndef PRODUCT | 52 #ifndef PRODUCT |
| 53 | 53 |
| 54 bool Profiler::initialized_ = false; | 54 bool Profiler::initialized_ = false; |
| 55 SampleBuffer* Profiler::sample_buffer_ = NULL; | 55 SampleBuffer* Profiler::sample_buffer_ = NULL; |
| 56 | 56 ProfilerCounters Profiler::counters_; |
| 57 | 57 |
| 58 void Profiler::InitOnce() { | 58 void Profiler::InitOnce() { |
| 59 // Place some sane restrictions on user controlled flags. | 59 // Place some sane restrictions on user controlled flags. |
| 60 SetSamplePeriod(FLAG_profile_period); | 60 SetSamplePeriod(FLAG_profile_period); |
| 61 SetSampleDepth(FLAG_max_profile_depth); | 61 SetSampleDepth(FLAG_max_profile_depth); |
| 62 Sample::InitOnce(); | 62 Sample::InitOnce(); |
| 63 if (!FLAG_profiler) { | 63 if (!FLAG_profiler) { |
| 64 return; | 64 return; |
| 65 } | 65 } |
| 66 ASSERT(!initialized_); | 66 ASSERT(!initialized_); |
| 67 sample_buffer_ = new SampleBuffer(); | 67 sample_buffer_ = new SampleBuffer(); |
| 68 NativeSymbolResolver::InitOnce(); | 68 NativeSymbolResolver::InitOnce(); |
| 69 ThreadInterrupter::SetInterruptPeriod(FLAG_profile_period); | 69 ThreadInterrupter::SetInterruptPeriod(FLAG_profile_period); |
| 70 ThreadInterrupter::Startup(); | 70 ThreadInterrupter::Startup(); |
| 71 // Zero counters. |
| 72 memset(&counters_, 0, sizeof(counters_)); |
| 71 initialized_ = true; | 73 initialized_ = true; |
| 72 } | 74 } |
| 73 | 75 |
| 74 | 76 |
| 75 void Profiler::Shutdown() { | 77 void Profiler::Shutdown() { |
| 76 if (!FLAG_profiler) { | 78 if (!FLAG_profiler) { |
| 77 return; | 79 return; |
| 78 } | 80 } |
| 79 ASSERT(initialized_); | 81 ASSERT(initialized_); |
| 80 ThreadInterrupter::Shutdown(); | 82 ThreadInterrupter::Shutdown(); |
| (...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 762 // All memory access done to collect the sample is performed in CollectSample. | 764 // All memory access done to collect the sample is performed in CollectSample. |
| 763 static void CollectSample(Isolate* isolate, | 765 static void CollectSample(Isolate* isolate, |
| 764 bool exited_dart_code, | 766 bool exited_dart_code, |
| 765 bool in_dart_code, | 767 bool in_dart_code, |
| 766 Sample* sample, | 768 Sample* sample, |
| 767 ProfilerNativeStackWalker* native_stack_walker, | 769 ProfilerNativeStackWalker* native_stack_walker, |
| 768 ProfilerDartExitStackWalker* dart_exit_stack_walker, | 770 ProfilerDartExitStackWalker* dart_exit_stack_walker, |
| 769 ProfilerDartStackWalker* dart_stack_walker, | 771 ProfilerDartStackWalker* dart_stack_walker, |
| 770 uword pc, | 772 uword pc, |
| 771 uword fp, | 773 uword fp, |
| 772 uword sp) { | 774 uword sp, |
| 775 ProfilerCounters* counters) { |
| 776 ASSERT(counters != NULL); |
| 773 #if defined(TARGET_OS_WINDOWS) | 777 #if defined(TARGET_OS_WINDOWS) |
| 774 // Use structured exception handling to trap guard page access on Windows. | 778 // Use structured exception handling to trap guard page access on Windows. |
| 775 __try { | 779 __try { |
| 776 #endif | 780 #endif |
| 777 | 781 |
| 778 if (in_dart_code) { | 782 if (in_dart_code) { |
| 779 // We can only trust the stack pointer if we are executing Dart code. | 783 // We can only trust the stack pointer if we are executing Dart code. |
| 780 // See http://dartbug.com/20421 for details. | 784 // See http://dartbug.com/20421 for details. |
| 781 CopyStackBuffer(sample, sp); | 785 CopyStackBuffer(sample, sp); |
| 782 } | 786 } |
| 783 | 787 |
| 784 if (FLAG_profile_vm) { | 788 if (FLAG_profile_vm) { |
| 785 // Always walk the native stack collecting both native and Dart frames. | 789 // Always walk the native stack collecting both native and Dart frames. |
| 790 counters->stack_walker_native++; |
| 786 native_stack_walker->walk(); | 791 native_stack_walker->walk(); |
| 787 } else if (StubCode::HasBeenInitialized() && exited_dart_code) { | 792 } else if (StubCode::HasBeenInitialized() && exited_dart_code) { |
| 793 counters->stack_walker_dart_exit++; |
| 788 // We have a valid exit frame info, use the Dart stack walker. | 794 // We have a valid exit frame info, use the Dart stack walker. |
| 789 dart_exit_stack_walker->walk(); | 795 dart_exit_stack_walker->walk(); |
| 790 } else if (StubCode::HasBeenInitialized() && in_dart_code) { | 796 } else if (StubCode::HasBeenInitialized() && in_dart_code) { |
| 797 counters->stack_walker_dart++; |
| 791 // We are executing Dart code. We have frame pointers. | 798 // We are executing Dart code. We have frame pointers. |
| 792 dart_stack_walker->walk(); | 799 dart_stack_walker->walk(); |
| 793 } else { | 800 } else { |
| 801 counters->stack_walker_none++; |
| 794 sample->SetAt(0, pc); | 802 sample->SetAt(0, pc); |
| 795 } | 803 } |
| 796 | 804 |
| 797 #if defined(TARGET_OS_WINDOWS) | 805 #if defined(TARGET_OS_WINDOWS) |
| 798 // Use structured exception handling to trap guard page access. | 806 // Use structured exception handling to trap guard page access. |
| 799 } __except(GuardPageExceptionFilter(GetExceptionInformation())) { | 807 } __except(GuardPageExceptionFilter(GetExceptionInformation())) { |
| 800 // Sample collection triggered a guard page fault: | 808 // Sample collection triggered a guard page fault: |
| 801 // 1) discard entire sample. | 809 // 1) discard entire sample. |
| 802 sample->set_ignore_sample(true); | 810 sample->set_ignore_sample(true); |
| 803 | 811 |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1112 return; | 1120 return; |
| 1113 #endif | 1121 #endif |
| 1114 | 1122 |
| 1115 ASSERT(thread != NULL); | 1123 ASSERT(thread != NULL); |
| 1116 OSThread* os_thread = thread->os_thread(); | 1124 OSThread* os_thread = thread->os_thread(); |
| 1117 ASSERT(os_thread != NULL); | 1125 ASSERT(os_thread != NULL); |
| 1118 Isolate* isolate = thread->isolate(); | 1126 Isolate* isolate = thread->isolate(); |
| 1119 | 1127 |
| 1120 // Thread is not doing VM work. | 1128 // Thread is not doing VM work. |
| 1121 if (thread->task_kind() == Thread::kUnknownTask) { | 1129 if (thread->task_kind() == Thread::kUnknownTask) { |
| 1130 counters_.bail_out_unknown_task++; |
| 1122 return; | 1131 return; |
| 1123 } | 1132 } |
| 1124 | 1133 |
| 1125 if (StubCode::HasBeenInitialized() && | 1134 if (StubCode::HasBeenInitialized() && |
| 1126 StubCode::InJumpToExceptionHandlerStub(state.pc)) { | 1135 StubCode::InJumpToExceptionHandlerStub(state.pc)) { |
| 1127 // The JumpToExceptionHandler stub manually adjusts the stack pointer, | 1136 // The JumpToExceptionHandler stub manually adjusts the stack pointer, |
| 1128 // frame pointer, and some isolate state before jumping to a catch entry. | 1137 // frame pointer, and some isolate state before jumping to a catch entry. |
| 1129 // It is not safe to walk the stack when executing this stub. | 1138 // It is not safe to walk the stack when executing this stub. |
| 1139 counters_.bail_out_jump_to_exception_handler++; |
| 1130 return; | 1140 return; |
| 1131 } | 1141 } |
| 1132 | 1142 |
| 1133 const bool in_dart_code = thread->IsExecutingDartCode(); | 1143 const bool in_dart_code = thread->IsExecutingDartCode(); |
| 1134 | 1144 |
| 1135 uintptr_t sp = 0; | 1145 uintptr_t sp = 0; |
| 1136 uintptr_t fp = state.fp; | 1146 uintptr_t fp = state.fp; |
| 1137 uintptr_t pc = state.pc; | 1147 uintptr_t pc = state.pc; |
| 1138 #if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC) | 1148 #if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC) |
| 1139 Simulator* simulator = NULL; | 1149 Simulator* simulator = NULL; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1150 pc = simulator->get_pc(); | 1160 pc = simulator->get_pc(); |
| 1151 #else | 1161 #else |
| 1152 sp = state.dsp; | 1162 sp = state.dsp; |
| 1153 #endif | 1163 #endif |
| 1154 } else { | 1164 } else { |
| 1155 // If we're in runtime code, use the C stack pointer. | 1165 // If we're in runtime code, use the C stack pointer. |
| 1156 sp = state.csp; | 1166 sp = state.csp; |
| 1157 } | 1167 } |
| 1158 | 1168 |
| 1159 if (!CheckIsolate(isolate)) { | 1169 if (!CheckIsolate(isolate)) { |
| 1170 counters_.bail_out_check_isolate++; |
| 1160 return; | 1171 return; |
| 1161 } | 1172 } |
| 1162 | 1173 |
| 1163 if (thread->IsMutatorThread() && isolate->IsDeoptimizing()) { | 1174 if (thread->IsMutatorThread() && isolate->IsDeoptimizing()) { |
| 1175 counters_.single_frame_sample_deoptimizing++; |
| 1164 SampleThreadSingleFrame(thread, pc); | 1176 SampleThreadSingleFrame(thread, pc); |
| 1165 return; | 1177 return; |
| 1166 } | 1178 } |
| 1167 | 1179 |
| 1168 if (!InitialRegisterCheck(pc, fp, sp)) { | 1180 if (!InitialRegisterCheck(pc, fp, sp)) { |
| 1181 counters_.single_frame_sample_register_check++; |
| 1169 SampleThreadSingleFrame(thread, pc); | 1182 SampleThreadSingleFrame(thread, pc); |
| 1170 return; | 1183 return; |
| 1171 } | 1184 } |
| 1172 | 1185 |
| 1173 uword stack_lower = 0; | 1186 uword stack_lower = 0; |
| 1174 uword stack_upper = 0; | 1187 uword stack_upper = 0; |
| 1175 if (!GetAndValidateIsolateStackBounds(thread, | 1188 if (!GetAndValidateIsolateStackBounds(thread, |
| 1176 fp, | 1189 fp, |
| 1177 sp, | 1190 sp, |
| 1178 &stack_lower, | 1191 &stack_lower, |
| 1179 &stack_upper)) { | 1192 &stack_upper)) { |
| 1193 counters_.single_frame_sample_get_and_validate_stack_bounds++; |
| 1180 // Could not get stack boundary. | 1194 // Could not get stack boundary. |
| 1181 SampleThreadSingleFrame(thread, pc); | 1195 SampleThreadSingleFrame(thread, pc); |
| 1182 return; | 1196 return; |
| 1183 } | 1197 } |
| 1184 | 1198 |
| 1185 // At this point we have a valid stack boundary for this isolate and | 1199 // At this point we have a valid stack boundary for this isolate and |
| 1186 // know that our initial stack and frame pointers are within the boundary. | 1200 // know that our initial stack and frame pointers are within the boundary. |
| 1187 SampleBuffer* sample_buffer = Profiler::sample_buffer(); | 1201 SampleBuffer* sample_buffer = Profiler::sample_buffer(); |
| 1188 if (sample_buffer == NULL) { | 1202 if (sample_buffer == NULL) { |
| 1189 // Profiler not initialized. | 1203 // Profiler not initialized. |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1227 // All memory access is done inside CollectSample. | 1241 // All memory access is done inside CollectSample. |
| 1228 CollectSample(isolate, | 1242 CollectSample(isolate, |
| 1229 exited_dart_code, | 1243 exited_dart_code, |
| 1230 in_dart_code, | 1244 in_dart_code, |
| 1231 sample, | 1245 sample, |
| 1232 &native_stack_walker, | 1246 &native_stack_walker, |
| 1233 &dart_exit_stack_walker, | 1247 &dart_exit_stack_walker, |
| 1234 &dart_stack_walker, | 1248 &dart_stack_walker, |
| 1235 pc, | 1249 pc, |
| 1236 fp, | 1250 fp, |
| 1237 sp); | 1251 sp, |
| 1252 &counters_); |
| 1238 } | 1253 } |
| 1239 | 1254 |
| 1240 | 1255 |
| 1241 | 1256 |
| 1242 CodeDescriptor::CodeDescriptor(const Code& code) : code_(code) { | 1257 CodeDescriptor::CodeDescriptor(const Code& code) : code_(code) { |
| 1243 ASSERT(!code_.IsNull()); | 1258 ASSERT(!code_.IsNull()); |
| 1244 } | 1259 } |
| 1245 | 1260 |
| 1246 | 1261 |
| 1247 uword CodeDescriptor::Entry() const { | 1262 uword CodeDescriptor::Entry() const { |
| (...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1564 | 1579 |
| 1565 | 1580 |
| 1566 ProcessedSampleBuffer::ProcessedSampleBuffer() | 1581 ProcessedSampleBuffer::ProcessedSampleBuffer() |
| 1567 : code_lookup_table_(new CodeLookupTable(Thread::Current())) { | 1582 : code_lookup_table_(new CodeLookupTable(Thread::Current())) { |
| 1568 ASSERT(code_lookup_table_ != NULL); | 1583 ASSERT(code_lookup_table_ != NULL); |
| 1569 } | 1584 } |
| 1570 | 1585 |
| 1571 #endif // !PRODUCT | 1586 #endif // !PRODUCT |
| 1572 | 1587 |
| 1573 } // namespace dart | 1588 } // namespace dart |
| OLD | NEW |