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 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
161 | 161 |
162 Sample* SampleBuffer::ReserveSample() { | 162 Sample* SampleBuffer::ReserveSample() { |
163 return At(ReserveSampleSlot()); | 163 return At(ReserveSampleSlot()); |
164 } | 164 } |
165 | 165 |
166 | 166 |
167 Sample* SampleBuffer::ReserveSampleAndLink(Sample* previous) { | 167 Sample* SampleBuffer::ReserveSampleAndLink(Sample* previous) { |
168 ASSERT(previous != NULL); | 168 ASSERT(previous != NULL); |
169 intptr_t next_index = ReserveSampleSlot(); | 169 intptr_t next_index = ReserveSampleSlot(); |
170 Sample* next = At(next_index); | 170 Sample* next = At(next_index); |
171 next->Init(previous->isolate(), previous->timestamp(), previous->tid()); | 171 next->Init(previous->port(), previous->timestamp(), previous->tid()); |
172 next->set_head_sample(false); | 172 next->set_head_sample(false); |
173 // Mark that previous continues at next. | 173 // Mark that previous continues at next. |
174 previous->SetContinuationIndex(next_index); | 174 previous->SetContinuationIndex(next_index); |
175 return next; | 175 return next; |
176 } | 176 } |
177 | 177 |
178 | 178 |
179 // Attempts to find the true return address when a Dart frame is being setup | 179 // Attempts to find the true return address when a Dart frame is being setup |
180 // or torn down. | 180 // or torn down. |
181 // NOTE: Architecture specific implementations below. | 181 // NOTE: Architecture specific implementations below. |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
314 } | 314 } |
315 | 315 |
316 | 316 |
317 bool SampleFilter::TaskFilterSample(Sample* sample) { | 317 bool SampleFilter::TaskFilterSample(Sample* sample) { |
318 const intptr_t task = static_cast<intptr_t>(sample->thread_task()); | 318 const intptr_t task = static_cast<intptr_t>(sample->thread_task()); |
319 return (task & thread_task_mask_) != 0; | 319 return (task & thread_task_mask_) != 0; |
320 } | 320 } |
321 | 321 |
322 | 322 |
323 ClearProfileVisitor::ClearProfileVisitor(Isolate* isolate) | 323 ClearProfileVisitor::ClearProfileVisitor(Isolate* isolate) |
324 : SampleVisitor(isolate) {} | 324 : SampleVisitor(isolate->main_port()) {} |
325 | 325 |
326 | 326 |
327 void ClearProfileVisitor::VisitSample(Sample* sample) { | 327 void ClearProfileVisitor::VisitSample(Sample* sample) { |
328 sample->Clear(); | 328 sample->Clear(); |
329 } | 329 } |
330 | 330 |
331 | 331 |
332 static void DumpStackFrame(intptr_t frame_index, uword pc) { | 332 static void DumpStackFrame(intptr_t frame_index, uword pc) { |
333 Isolate* isolate = Isolate::Current(); | 333 Isolate* isolate = Isolate::Current(); |
334 if ((isolate != NULL) && isolate->is_runnable()) { | 334 if ((isolate != NULL) && isolate->is_runnable()) { |
(...skipping 15 matching lines...) Expand all Loading... | |
350 OS::PrintErr(" [0x%" Pp "] Unknown symbol\n", pc); | 350 OS::PrintErr(" [0x%" Pp "] Unknown symbol\n", pc); |
351 } else { | 351 } else { |
352 OS::PrintErr(" [0x%" Pp "] %s\n", pc, native_symbol_name); | 352 OS::PrintErr(" [0x%" Pp "] %s\n", pc, native_symbol_name); |
353 NativeSymbolResolver::FreeSymbolName(native_symbol_name); | 353 NativeSymbolResolver::FreeSymbolName(native_symbol_name); |
354 } | 354 } |
355 } | 355 } |
356 | 356 |
357 | 357 |
358 class ProfilerStackWalker : public ValueObject { | 358 class ProfilerStackWalker : public ValueObject { |
359 public: | 359 public: |
360 ProfilerStackWalker(Isolate* isolate, | 360 ProfilerStackWalker(Dart_Port port_id, |
361 Sample* head_sample, | 361 Sample* head_sample, |
362 SampleBuffer* sample_buffer) | 362 SampleBuffer* sample_buffer, |
363 : isolate_(isolate), | 363 intptr_t skip_count = 0) |
364 : port_id_(port_id), | |
364 sample_(head_sample), | 365 sample_(head_sample), |
365 sample_buffer_(sample_buffer), | 366 sample_buffer_(sample_buffer), |
367 skip_count_(skip_count), | |
368 frames_skipped_(0), | |
366 frame_index_(0), | 369 frame_index_(0), |
367 total_frames_(0) { | 370 total_frames_(0) { |
368 ASSERT(isolate_ != NULL); | |
369 if (sample_ == NULL) { | 371 if (sample_ == NULL) { |
370 ASSERT(sample_buffer_ == NULL); | 372 ASSERT(sample_buffer_ == NULL); |
371 } else { | 373 } else { |
372 ASSERT(sample_buffer_ != NULL); | 374 ASSERT(sample_buffer_ != NULL); |
373 ASSERT(sample_->head_sample()); | 375 ASSERT(sample_->head_sample()); |
374 } | 376 } |
375 } | 377 } |
376 | 378 |
377 bool Append(uword pc) { | 379 bool Append(uword pc) { |
380 if (frames_skipped_ < skip_count_) { | |
381 frames_skipped_++; | |
382 return true; | |
383 } | |
384 | |
378 if (sample_ == NULL) { | 385 if (sample_ == NULL) { |
379 DumpStackFrame(frame_index_, pc); | 386 DumpStackFrame(frame_index_, pc); |
380 frame_index_++; | 387 frame_index_++; |
381 total_frames_++; | 388 total_frames_++; |
382 return true; | 389 return true; |
383 } | 390 } |
384 if (total_frames_ >= FLAG_max_profile_depth) { | 391 if (total_frames_ >= FLAG_max_profile_depth) { |
385 sample_->set_truncated_trace(true); | 392 sample_->set_truncated_trace(true); |
386 return false; | 393 return false; |
387 } | 394 } |
388 ASSERT(sample_ != NULL); | 395 ASSERT(sample_ != NULL); |
389 if (frame_index_ == kSampleSize) { | 396 if (frame_index_ == kSampleSize) { |
390 Sample* new_sample = sample_buffer_->ReserveSampleAndLink(sample_); | 397 Sample* new_sample = sample_buffer_->ReserveSampleAndLink(sample_); |
391 if (new_sample == NULL) { | 398 if (new_sample == NULL) { |
392 // Could not reserve new sample- mark this as truncated. | 399 // Could not reserve new sample- mark this as truncated. |
393 sample_->set_truncated_trace(true); | 400 sample_->set_truncated_trace(true); |
394 return false; | 401 return false; |
395 } | 402 } |
396 frame_index_ = 0; | 403 frame_index_ = 0; |
397 sample_ = new_sample; | 404 sample_ = new_sample; |
398 } | 405 } |
399 ASSERT(frame_index_ < kSampleSize); | 406 ASSERT(frame_index_ < kSampleSize); |
400 sample_->SetAt(frame_index_, pc); | 407 sample_->SetAt(frame_index_, pc); |
401 frame_index_++; | 408 frame_index_++; |
402 total_frames_++; | 409 total_frames_++; |
403 return true; | 410 return true; |
404 } | 411 } |
405 | 412 |
406 protected: | 413 protected: |
407 Isolate* isolate_; | 414 Dart_Port port_id_; |
408 Sample* sample_; | 415 Sample* sample_; |
409 SampleBuffer* sample_buffer_; | 416 SampleBuffer* sample_buffer_; |
417 intptr_t skip_count_; | |
418 intptr_t frames_skipped_; | |
410 intptr_t frame_index_; | 419 intptr_t frame_index_; |
411 intptr_t total_frames_; | 420 intptr_t total_frames_; |
412 }; | 421 }; |
413 | 422 |
414 | 423 |
415 // Executing Dart code, walk the stack. | 424 // Executing Dart code, walk the stack. |
416 class ProfilerDartStackWalker : public ProfilerStackWalker { | 425 class ProfilerDartStackWalker : public ProfilerStackWalker { |
417 public: | 426 public: |
418 ProfilerDartStackWalker(Thread* thread, | 427 ProfilerDartStackWalker(Thread* thread, |
419 Sample* sample, | 428 Sample* sample, |
420 SampleBuffer* sample_buffer, | 429 SampleBuffer* sample_buffer, |
421 uword stack_lower, | 430 uword stack_lower, |
422 uword stack_upper, | 431 uword stack_upper, |
423 uword pc, | 432 uword pc, |
424 uword fp, | 433 uword fp, |
425 uword sp, | 434 uword sp, |
426 bool exited_dart_code, | 435 bool exited_dart_code, |
427 bool allocation_sample) | 436 bool allocation_sample, |
428 : ProfilerStackWalker(thread->isolate(), sample, sample_buffer), | 437 intptr_t skip_count = 0) |
438 : ProfilerStackWalker((thread->isolate() != NULL) | |
439 ? thread->isolate()->main_port() | |
440 : ILLEGAL_PORT, | |
441 sample, | |
442 sample_buffer, | |
443 skip_count), | |
429 pc_(reinterpret_cast<uword*>(pc)), | 444 pc_(reinterpret_cast<uword*>(pc)), |
430 fp_(reinterpret_cast<uword*>(fp)), | 445 fp_(reinterpret_cast<uword*>(fp)), |
431 sp_(reinterpret_cast<uword*>(sp)), | 446 sp_(reinterpret_cast<uword*>(sp)), |
432 stack_upper_(stack_upper), | 447 stack_upper_(stack_upper), |
433 stack_lower_(stack_lower), | 448 stack_lower_(stack_lower), |
434 has_exit_frame_(exited_dart_code) { | 449 has_exit_frame_(exited_dart_code) { |
435 if (exited_dart_code) { | 450 if (exited_dart_code) { |
436 StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames, | 451 StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames, |
437 thread); | 452 thread); |
438 pc_ = NULL; | 453 pc_ = NULL; |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
590 bool has_exit_frame_; | 605 bool has_exit_frame_; |
591 }; | 606 }; |
592 | 607 |
593 | 608 |
594 // If the VM is compiled without frame pointers (which is the default on | 609 // If the VM is compiled without frame pointers (which is the default on |
595 // recent GCC versions with optimizing enabled) the stack walking code may | 610 // recent GCC versions with optimizing enabled) the stack walking code may |
596 // fail. | 611 // fail. |
597 // | 612 // |
598 class ProfilerNativeStackWalker : public ProfilerStackWalker { | 613 class ProfilerNativeStackWalker : public ProfilerStackWalker { |
599 public: | 614 public: |
600 ProfilerNativeStackWalker(Isolate* isolate, | 615 ProfilerNativeStackWalker(Dart_Port port_id, |
601 Sample* sample, | 616 Sample* sample, |
602 SampleBuffer* sample_buffer, | 617 SampleBuffer* sample_buffer, |
603 uword stack_lower, | 618 uword stack_lower, |
604 uword stack_upper, | 619 uword stack_upper, |
605 uword pc, | 620 uword pc, |
606 uword fp, | 621 uword fp, |
607 uword sp) | 622 uword sp, |
608 : ProfilerStackWalker(isolate, sample, sample_buffer), | 623 intptr_t skip_count = 0) |
624 : ProfilerStackWalker(port_id, sample, sample_buffer, skip_count), | |
609 stack_upper_(stack_upper), | 625 stack_upper_(stack_upper), |
610 original_pc_(pc), | 626 original_pc_(pc), |
611 original_fp_(fp), | 627 original_fp_(fp), |
612 original_sp_(sp), | 628 original_sp_(sp), |
613 lower_bound_(stack_lower) {} | 629 lower_bound_(stack_lower) {} |
614 | 630 |
615 void walk() { | 631 void walk() { |
616 const uword kMaxStep = VirtualMemory::PageSize(); | 632 const uword kMaxStep = VirtualMemory::PageSize(); |
633 | |
617 Append(original_pc_); | 634 Append(original_pc_); |
618 | 635 |
619 uword* pc = reinterpret_cast<uword*>(original_pc_); | 636 uword* pc = reinterpret_cast<uword*>(original_pc_); |
620 uword* fp = reinterpret_cast<uword*>(original_fp_); | 637 uword* fp = reinterpret_cast<uword*>(original_fp_); |
621 uword* previous_fp = fp; | 638 uword* previous_fp = fp; |
622 | 639 |
623 uword gap = original_fp_ - original_sp_; | 640 uword gap = original_fp_ - original_sp_; |
624 if (gap >= kMaxStep) { | 641 if (gap >= kMaxStep) { |
625 // Gap between frame pointer and stack pointer is | 642 // Gap between frame pointer and stack pointer is |
626 // too large. | 643 // too large. |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
800 // it. If |get_os_thread_bounds| is true then if |isolate| stackbounds are | 817 // it. If |get_os_thread_bounds| is true then if |isolate| stackbounds are |
801 // not available we fallback to using underlying OS thread bounds. This only | 818 // not available we fallback to using underlying OS thread bounds. This only |
802 // works for the current thread. | 819 // works for the current thread. |
803 // Return |false| if anything looks suspicious. | 820 // Return |false| if anything looks suspicious. |
804 static bool GetAndValidateThreadStackBounds(Thread* thread, | 821 static bool GetAndValidateThreadStackBounds(Thread* thread, |
805 uintptr_t fp, | 822 uintptr_t fp, |
806 uintptr_t sp, | 823 uintptr_t sp, |
807 uword* stack_lower, | 824 uword* stack_lower, |
808 uword* stack_upper, | 825 uword* stack_upper, |
809 bool get_os_thread_bounds = false) { | 826 bool get_os_thread_bounds = false) { |
810 ASSERT(thread != NULL); | 827 OSThread* os_thread = NULL; |
811 OSThread* os_thread = thread->os_thread(); | 828 if (thread != NULL) { |
829 os_thread = thread->os_thread(); | |
830 } else { | |
831 os_thread = OSThread::Current(); | |
832 } | |
812 ASSERT(os_thread != NULL); | 833 ASSERT(os_thread != NULL); |
813 ASSERT(stack_lower != NULL); | 834 ASSERT(stack_lower != NULL); |
814 ASSERT(stack_upper != NULL); | 835 ASSERT(stack_upper != NULL); |
815 ASSERT(!get_os_thread_bounds || (Thread::Current() == thread)); | 836 ASSERT(!get_os_thread_bounds || (Thread::Current() == thread)); |
816 | 837 |
817 #if defined(USING_SIMULATOR) | 838 #if defined(USING_SIMULATOR) |
818 const bool use_simulator_stack_bounds = thread->IsExecutingDartCode(); | 839 const bool use_simulator_stack_bounds = thread->IsExecutingDartCode(); |
819 if (use_simulator_stack_bounds) { | 840 if (use_simulator_stack_bounds) { |
820 Isolate* isolate = thread->isolate(); | 841 Isolate* isolate = thread->isolate(); |
821 ASSERT(isolate != NULL); | 842 ASSERT(isolate != NULL); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
880 } | 901 } |
881 | 902 |
882 | 903 |
883 static Sample* SetupSample(Thread* thread, | 904 static Sample* SetupSample(Thread* thread, |
884 SampleBuffer* sample_buffer, | 905 SampleBuffer* sample_buffer, |
885 ThreadId tid) { | 906 ThreadId tid) { |
886 ASSERT(thread != NULL); | 907 ASSERT(thread != NULL); |
887 Isolate* isolate = thread->isolate(); | 908 Isolate* isolate = thread->isolate(); |
888 ASSERT(sample_buffer != NULL); | 909 ASSERT(sample_buffer != NULL); |
889 Sample* sample = sample_buffer->ReserveSample(); | 910 Sample* sample = sample_buffer->ReserveSample(); |
890 sample->Init(isolate, OS::GetCurrentMonotonicMicros(), tid); | 911 sample->Init(isolate->main_port(), OS::GetCurrentMonotonicMicros(), tid); |
891 uword vm_tag = thread->vm_tag(); | 912 uword vm_tag = thread->vm_tag(); |
892 #if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC) | 913 #if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC) |
893 // When running in the simulator, the runtime entry function address | 914 // When running in the simulator, the runtime entry function address |
894 // (stored as the vm tag) is the address of a redirect function. | 915 // (stored as the vm tag) is the address of a redirect function. |
895 // Attempt to find the real runtime entry function address and use that. | 916 // Attempt to find the real runtime entry function address and use that. |
896 uword redirect_vm_tag = Simulator::FunctionForRedirect(vm_tag); | 917 uword redirect_vm_tag = Simulator::FunctionForRedirect(vm_tag); |
897 if (redirect_vm_tag != 0) { | 918 if (redirect_vm_tag != 0) { |
898 vm_tag = redirect_vm_tag; | 919 vm_tag = redirect_vm_tag; |
899 } | 920 } |
900 #endif | 921 #endif |
901 sample->set_vm_tag(vm_tag); | 922 sample->set_vm_tag(vm_tag); |
902 sample->set_user_tag(isolate->user_tag()); | 923 sample->set_user_tag(isolate->user_tag()); |
903 sample->set_thread_task(thread->task_kind()); | 924 sample->set_thread_task(thread->task_kind()); |
904 return sample; | 925 return sample; |
905 } | 926 } |
906 | 927 |
907 | 928 |
929 static Sample* SetupSampleNative(SampleBuffer* sample_buffer, ThreadId tid) { | |
930 Sample* sample = sample_buffer->ReserveSample(); | |
931 sample->Init(ILLEGAL_PORT, OS::GetCurrentMonotonicMicros(), tid); | |
932 sample->set_is_native_allocation_sample(true); | |
933 | |
934 Thread* thread = Thread::Current(); | |
935 | |
936 // TODO(bkonyi) Any samples created while a current thread doesn't exist are | |
937 // ignored by the NativeAllocationSampleFilter since the default task is | |
938 // kUnknownTask. Is this what we want to do? | |
939 if (thread != NULL) { | |
940 sample->set_thread_task(thread->task_kind()); | |
941 } | |
942 return sample; | |
943 } | |
944 | |
945 | |
908 static bool CheckIsolate(Isolate* isolate) { | 946 static bool CheckIsolate(Isolate* isolate) { |
909 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) { | 947 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) { |
910 // No isolate. | 948 // No isolate. |
911 return false; | 949 return false; |
912 } | 950 } |
913 return isolate != Dart::vm_isolate(); | 951 return isolate != Dart::vm_isolate(); |
914 } | 952 } |
915 | 953 |
916 | 954 |
917 #if defined(TARGET_OS_WINDOWS) | |
918 __declspec(noinline) static uintptr_t GetProgramCounter() { | |
919 return reinterpret_cast<uintptr_t>(_ReturnAddress()); | |
920 } | |
921 #else | |
922 static uintptr_t __attribute__((noinline)) GetProgramCounter() { | |
923 return reinterpret_cast<uintptr_t>( | |
924 __builtin_extract_return_addr(__builtin_return_address(0))); | |
925 } | |
926 #endif | |
927 | |
928 | |
929 void Profiler::DumpStackTrace(void* context) { | 955 void Profiler::DumpStackTrace(void* context) { |
930 #if defined(TARGET_OS_LINUX) || defined(TARGET_OS_MACOS) | 956 #if defined(TARGET_OS_LINUX) || defined(TARGET_OS_MACOS) |
931 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); | 957 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); |
932 mcontext_t mcontext = ucontext->uc_mcontext; | 958 mcontext_t mcontext = ucontext->uc_mcontext; |
933 uword pc = SignalHandler::GetProgramCounter(mcontext); | 959 uword pc = SignalHandler::GetProgramCounter(mcontext); |
934 uword fp = SignalHandler::GetFramePointer(mcontext); | 960 uword fp = SignalHandler::GetFramePointer(mcontext); |
935 uword sp = SignalHandler::GetCStackPointer(mcontext); | 961 uword sp = SignalHandler::GetCStackPointer(mcontext); |
936 DumpStackTrace(sp, fp, pc); | 962 DumpStackTrace(sp, fp, pc); |
937 #else | 963 #else |
938 // TODO(fschneider): Add support for more platforms. | 964 // TODO(fschneider): Add support for more platforms. |
939 // Do nothing on unsupported platforms. | 965 // Do nothing on unsupported platforms. |
940 #endif | 966 #endif |
941 } | 967 } |
942 | 968 |
943 | 969 |
944 void Profiler::DumpStackTrace() { | 970 void Profiler::DumpStackTrace() { |
945 uintptr_t sp = Thread::GetCurrentStackPointer(); | 971 uintptr_t sp = Thread::GetCurrentStackPointer(); |
946 uintptr_t fp = 0; | 972 uintptr_t fp = 0; |
947 uintptr_t pc = GetProgramCounter(); | 973 uintptr_t pc = OS::GetProgramCounter(); |
948 | 974 |
949 COPY_FP_REGISTER(fp); | 975 COPY_FP_REGISTER(fp); |
950 | 976 |
951 DumpStackTrace(sp, fp, pc); | 977 DumpStackTrace(sp, fp, pc); |
952 } | 978 } |
953 | 979 |
954 | 980 |
955 void Profiler::DumpStackTrace(uword sp, uword fp, uword pc) { | 981 void Profiler::DumpStackTrace(uword sp, uword fp, uword pc) { |
956 // Allow only one stack trace to prevent recursively printing stack traces if | 982 // Allow only one stack trace to prevent recursively printing stack traces if |
957 // we hit an assert while printing the stack. | 983 // we hit an assert while printing the stack. |
(...skipping 27 matching lines...) Expand all Loading... | |
985 | 1011 |
986 if (!GetAndValidateThreadStackBounds(thread, fp, sp, &stack_lower, | 1012 if (!GetAndValidateThreadStackBounds(thread, fp, sp, &stack_lower, |
987 &stack_upper, | 1013 &stack_upper, |
988 /*get_os_thread_bounds=*/true)) { | 1014 /*get_os_thread_bounds=*/true)) { |
989 OS::PrintErr( | 1015 OS::PrintErr( |
990 "Stack dump aborted because GetAndValidateThreadStackBounds.\n"); | 1016 "Stack dump aborted because GetAndValidateThreadStackBounds.\n"); |
991 return; | 1017 return; |
992 } | 1018 } |
993 | 1019 |
994 ProfilerNativeStackWalker native_stack_walker( | 1020 ProfilerNativeStackWalker native_stack_walker( |
995 isolate, NULL, NULL, stack_lower, stack_upper, pc, fp, sp); | 1021 (isolate != NULL) ? isolate->main_port() : ILLEGAL_PORT, NULL, NULL, |
1022 stack_lower, stack_upper, pc, fp, sp); | |
996 native_stack_walker.walk(); | 1023 native_stack_walker.walk(); |
997 OS::PrintErr("-- End of DumpStackTrace\n"); | 1024 OS::PrintErr("-- End of DumpStackTrace\n"); |
998 } | 1025 } |
999 | 1026 |
1000 | 1027 |
1001 void Profiler::SampleAllocation(Thread* thread, intptr_t cid) { | 1028 void Profiler::SampleAllocation(Thread* thread, intptr_t cid) { |
1002 ASSERT(thread != NULL); | 1029 ASSERT(thread != NULL); |
1003 OSThread* os_thread = thread->os_thread(); | 1030 OSThread* os_thread = thread->os_thread(); |
1004 ASSERT(os_thread != NULL); | 1031 ASSERT(os_thread != NULL); |
1005 Isolate* isolate = thread->isolate(); | 1032 Isolate* isolate = thread->isolate(); |
1006 if (!CheckIsolate(isolate)) { | 1033 if (!CheckIsolate(isolate)) { |
1007 return; | 1034 return; |
1008 } | 1035 } |
1009 | 1036 |
1010 const bool exited_dart_code = thread->HasExitedDartCode(); | 1037 const bool exited_dart_code = thread->HasExitedDartCode(); |
1011 | 1038 |
1012 SampleBuffer* sample_buffer = Profiler::sample_buffer(); | 1039 SampleBuffer* sample_buffer = Profiler::sample_buffer(); |
1013 if (sample_buffer == NULL) { | 1040 if (sample_buffer == NULL) { |
1014 // Profiler not initialized. | 1041 // Profiler not initialized. |
1015 return; | 1042 return; |
1016 } | 1043 } |
1017 | 1044 |
1018 uintptr_t sp = Thread::GetCurrentStackPointer(); | 1045 uintptr_t sp = Thread::GetCurrentStackPointer(); |
1019 uintptr_t fp = 0; | 1046 uintptr_t fp = 0; |
1020 uintptr_t pc = GetProgramCounter(); | 1047 uintptr_t pc = OS::GetProgramCounter(); |
1021 | 1048 |
1022 COPY_FP_REGISTER(fp); | 1049 COPY_FP_REGISTER(fp); |
1023 | 1050 |
1024 uword stack_lower = 0; | 1051 uword stack_lower = 0; |
1025 uword stack_upper = 0; | 1052 uword stack_upper = 0; |
1026 | 1053 |
1027 if (!InitialRegisterCheck(pc, fp, sp)) { | 1054 if (!InitialRegisterCheck(pc, fp, sp)) { |
1028 return; | 1055 return; |
1029 } | 1056 } |
1030 | 1057 |
1031 if (!GetAndValidateThreadStackBounds(thread, fp, sp, &stack_lower, | 1058 if (!GetAndValidateThreadStackBounds(thread, fp, sp, &stack_lower, |
1032 &stack_upper)) { | 1059 &stack_upper)) { |
1033 // Could not get stack boundary. | 1060 // Could not get stack boundary. |
1034 return; | 1061 return; |
1035 } | 1062 } |
1036 | 1063 |
1037 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id()); | 1064 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id()); |
1038 sample->SetAllocationCid(cid); | 1065 sample->SetAllocationCid(cid); |
1039 | 1066 |
1040 if (FLAG_profile_vm) { | 1067 if (FLAG_profile_vm) { |
1041 ProfilerNativeStackWalker native_stack_walker( | 1068 ProfilerNativeStackWalker native_stack_walker( |
1042 isolate, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp); | 1069 (isolate != NULL) ? isolate->main_port() : ILLEGAL_PORT, sample, |
1070 sample_buffer, stack_lower, stack_upper, pc, fp, sp); | |
1043 native_stack_walker.walk(); | 1071 native_stack_walker.walk(); |
1044 } else if (exited_dart_code) { | 1072 } else if (exited_dart_code) { |
1045 ProfilerDartStackWalker dart_exit_stack_walker( | 1073 ProfilerDartStackWalker dart_exit_stack_walker( |
1046 thread, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp, | 1074 thread, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp, |
1047 exited_dart_code, true); | 1075 exited_dart_code, true); |
1048 dart_exit_stack_walker.walk(); | 1076 dart_exit_stack_walker.walk(); |
1049 } else { | 1077 } else { |
1050 // Fall back. | 1078 // Fall back. |
1051 uintptr_t pc = GetProgramCounter(); | 1079 uintptr_t pc = OS::GetProgramCounter(); |
1052 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id()); | 1080 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id()); |
1053 sample->SetAllocationCid(cid); | 1081 sample->SetAllocationCid(cid); |
1054 sample->SetAt(0, pc); | 1082 sample->SetAt(0, pc); |
1055 } | 1083 } |
1056 } | 1084 } |
1057 | 1085 |
1058 | 1086 |
1087 Sample* Profiler::SampleNativeAllocation(intptr_t skip_count) { | |
1088 SampleBuffer* sample_buffer = Profiler::sample_buffer(); | |
1089 if (sample_buffer == NULL) { | |
1090 return NULL; | |
1091 } | |
1092 | |
1093 uintptr_t sp = Thread::GetCurrentStackPointer(); | |
1094 uintptr_t fp = 0; | |
1095 uintptr_t pc = OS::GetProgramCounter(); | |
1096 | |
1097 COPY_FP_REGISTER(fp); | |
1098 | |
1099 uword stack_lower = 0; | |
1100 uword stack_upper = 0; | |
1101 if (!InitialRegisterCheck(pc, fp, sp)) { | |
1102 return NULL; | |
1103 } | |
1104 | |
1105 OSThread* os_thread = OSThread::Current(); | |
1106 if (os_thread->stack_base() == 0) { | |
1107 stack_lower = sp; | |
Cutch
2017/02/21 18:53:35
OSThread::GetCurrentStackBounds
bkonyi
2017/02/22 19:12:51
Done.
| |
1108 stack_upper = ~static_cast<uintptr_t>(0x0); | |
1109 } else { | |
1110 if (!GetAndValidateThreadStackBounds(NULL, fp, sp, &stack_lower, | |
1111 &stack_upper)) { | |
1112 // Could not get stack boundary. | |
1113 return NULL; | |
1114 } | |
1115 } | |
1116 Sample* sample = SetupSampleNative(sample_buffer, os_thread->trace_id()); | |
1117 ProfilerNativeStackWalker native_stack_walker( | |
1118 ILLEGAL_PORT, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp, | |
1119 skip_count); | |
1120 native_stack_walker.walk(); | |
1121 return sample; | |
1122 } | |
1123 | |
1124 | |
1059 void Profiler::SampleThreadSingleFrame(Thread* thread, uintptr_t pc) { | 1125 void Profiler::SampleThreadSingleFrame(Thread* thread, uintptr_t pc) { |
1060 ASSERT(thread != NULL); | 1126 ASSERT(thread != NULL); |
1061 OSThread* os_thread = thread->os_thread(); | 1127 OSThread* os_thread = thread->os_thread(); |
1062 ASSERT(os_thread != NULL); | 1128 ASSERT(os_thread != NULL); |
1063 Isolate* isolate = thread->isolate(); | 1129 Isolate* isolate = thread->isolate(); |
1064 | 1130 |
1065 SampleBuffer* sample_buffer = Profiler::sample_buffer(); | 1131 SampleBuffer* sample_buffer = Profiler::sample_buffer(); |
1066 if (sample_buffer == NULL) { | 1132 if (sample_buffer == NULL) { |
1067 // Profiler not initialized. | 1133 // Profiler not initialized. |
1068 return; | 1134 return; |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1174 // Setup sample. | 1240 // Setup sample. |
1175 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id()); | 1241 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id()); |
1176 // Increment counter for vm tag. | 1242 // Increment counter for vm tag. |
1177 VMTagCounters* counters = isolate->vm_tag_counters(); | 1243 VMTagCounters* counters = isolate->vm_tag_counters(); |
1178 ASSERT(counters != NULL); | 1244 ASSERT(counters != NULL); |
1179 if (thread->IsMutatorThread()) { | 1245 if (thread->IsMutatorThread()) { |
1180 counters->Increment(sample->vm_tag()); | 1246 counters->Increment(sample->vm_tag()); |
1181 } | 1247 } |
1182 | 1248 |
1183 ProfilerNativeStackWalker native_stack_walker( | 1249 ProfilerNativeStackWalker native_stack_walker( |
1184 isolate, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp); | 1250 (isolate != NULL) ? isolate->main_port() : ILLEGAL_PORT, sample, |
1251 sample_buffer, stack_lower, stack_upper, pc, fp, sp); | |
1185 const bool exited_dart_code = thread->HasExitedDartCode(); | 1252 const bool exited_dart_code = thread->HasExitedDartCode(); |
1186 ProfilerDartStackWalker dart_stack_walker(thread, sample, sample_buffer, | 1253 ProfilerDartStackWalker dart_stack_walker(thread, sample, sample_buffer, |
1187 stack_lower, stack_upper, pc, fp, | 1254 stack_lower, stack_upper, pc, fp, |
1188 sp, exited_dart_code, false); | 1255 sp, exited_dart_code, false); |
1189 | 1256 |
1190 // All memory access is done inside CollectSample. | 1257 // All memory access is done inside CollectSample. |
1191 CollectSample(isolate, exited_dart_code, in_dart_code, sample, | 1258 CollectSample(isolate, exited_dart_code, in_dart_code, sample, |
1192 &native_stack_walker, &dart_stack_walker, pc, fp, sp, | 1259 &native_stack_walker, &dart_stack_walker, pc, fp, sp, |
1193 &counters_); | 1260 &counters_); |
1194 } | 1261 } |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1334 for (intptr_t i = 0; i < length; i++) { | 1401 for (intptr_t i = 0; i < length; i++) { |
1335 Sample* sample = At(i); | 1402 Sample* sample = At(i); |
1336 if (sample->ignore_sample()) { | 1403 if (sample->ignore_sample()) { |
1337 // Bad sample. | 1404 // Bad sample. |
1338 continue; | 1405 continue; |
1339 } | 1406 } |
1340 if (!sample->head_sample()) { | 1407 if (!sample->head_sample()) { |
1341 // An inner sample in a chain of samples. | 1408 // An inner sample in a chain of samples. |
1342 continue; | 1409 continue; |
1343 } | 1410 } |
1344 if (sample->isolate() != filter->isolate()) { | 1411 // If we're requesting all the native allocation samples, we don't care |
1412 // whether or not we're in the same isolate as the sample. | |
1413 if ((sample->port() != filter->port()) && | |
1414 !sample->is_native_allocation_sample()) { | |
1345 // Another isolate. | 1415 // Another isolate. |
1346 continue; | 1416 continue; |
1347 } | 1417 } |
1348 if (sample->timestamp() == 0) { | 1418 if (sample->timestamp() == 0) { |
1349 // Empty. | 1419 // Empty. |
1350 continue; | 1420 continue; |
1351 } | 1421 } |
1352 if (sample->At(0) == 0) { | 1422 if (sample->At(0) == 0) { |
1353 // No frames. | 1423 // No frames. |
1354 continue; | 1424 continue; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1413 return processed_sample; | 1483 return processed_sample; |
1414 } | 1484 } |
1415 | 1485 |
1416 | 1486 |
1417 Sample* SampleBuffer::Next(Sample* sample) { | 1487 Sample* SampleBuffer::Next(Sample* sample) { |
1418 if (!sample->is_continuation_sample()) return NULL; | 1488 if (!sample->is_continuation_sample()) return NULL; |
1419 Sample* next_sample = At(sample->continuation_index()); | 1489 Sample* next_sample = At(sample->continuation_index()); |
1420 // Sanity check. | 1490 // Sanity check. |
1421 ASSERT(sample != next_sample); | 1491 ASSERT(sample != next_sample); |
1422 // Detect invalid chaining. | 1492 // Detect invalid chaining. |
1423 if (sample->isolate() != next_sample->isolate()) { | 1493 if (sample->port() != next_sample->port()) { |
1424 return NULL; | 1494 return NULL; |
1425 } | 1495 } |
1426 if (sample->timestamp() != next_sample->timestamp()) { | 1496 if (sample->timestamp() != next_sample->timestamp()) { |
1427 return NULL; | 1497 return NULL; |
1428 } | 1498 } |
1429 if (sample->tid() != next_sample->tid()) { | 1499 if (sample->tid() != next_sample->tid()) { |
1430 return NULL; | 1500 return NULL; |
1431 } | 1501 } |
1432 return next_sample; | 1502 return next_sample; |
1433 } | 1503 } |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1515 | 1585 |
1516 | 1586 |
1517 ProcessedSampleBuffer::ProcessedSampleBuffer() | 1587 ProcessedSampleBuffer::ProcessedSampleBuffer() |
1518 : code_lookup_table_(new CodeLookupTable(Thread::Current())) { | 1588 : code_lookup_table_(new CodeLookupTable(Thread::Current())) { |
1519 ASSERT(code_lookup_table_ != NULL); | 1589 ASSERT(code_lookup_table_ != NULL); |
1520 } | 1590 } |
1521 | 1591 |
1522 #endif // !PRODUCT | 1592 #endif // !PRODUCT |
1523 | 1593 |
1524 } // namespace dart | 1594 } // namespace dart |
OLD | NEW |