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->port(), previous->timestamp(), previous->tid()); | 171 next->Init(previous->isolate(), 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->main_port()) {} | 324 : SampleVisitor(isolate) {} |
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(Dart_Port port_id, | 360 ProfilerStackWalker(Isolate* isolate, |
361 Sample* head_sample, | 361 Sample* head_sample, |
362 SampleBuffer* sample_buffer, | 362 SampleBuffer* sample_buffer) |
363 intptr_t skip_count = 0) | 363 : isolate_(isolate), |
364 : port_id_(port_id), | |
365 sample_(head_sample), | 364 sample_(head_sample), |
366 sample_buffer_(sample_buffer), | 365 sample_buffer_(sample_buffer), |
367 skip_count_(skip_count), | |
368 frames_skipped_(0), | |
369 frame_index_(0), | 366 frame_index_(0), |
370 total_frames_(0) { | 367 total_frames_(0) { |
| 368 ASSERT(isolate_ != NULL); |
371 if (sample_ == NULL) { | 369 if (sample_ == NULL) { |
372 ASSERT(sample_buffer_ == NULL); | 370 ASSERT(sample_buffer_ == NULL); |
373 } else { | 371 } else { |
374 ASSERT(sample_buffer_ != NULL); | 372 ASSERT(sample_buffer_ != NULL); |
375 ASSERT(sample_->head_sample()); | 373 ASSERT(sample_->head_sample()); |
376 } | 374 } |
377 } | 375 } |
378 | 376 |
379 bool Append(uword pc) { | 377 bool Append(uword pc) { |
380 if (frames_skipped_ < skip_count_) { | |
381 frames_skipped_++; | |
382 return true; | |
383 } | |
384 | |
385 if (sample_ == NULL) { | 378 if (sample_ == NULL) { |
386 DumpStackFrame(frame_index_, pc); | 379 DumpStackFrame(frame_index_, pc); |
387 frame_index_++; | 380 frame_index_++; |
388 total_frames_++; | 381 total_frames_++; |
389 return true; | 382 return true; |
390 } | 383 } |
391 if (total_frames_ >= FLAG_max_profile_depth) { | 384 if (total_frames_ >= FLAG_max_profile_depth) { |
392 sample_->set_truncated_trace(true); | 385 sample_->set_truncated_trace(true); |
393 return false; | 386 return false; |
394 } | 387 } |
395 ASSERT(sample_ != NULL); | 388 ASSERT(sample_ != NULL); |
396 if (frame_index_ == kSampleSize) { | 389 if (frame_index_ == kSampleSize) { |
397 Sample* new_sample = sample_buffer_->ReserveSampleAndLink(sample_); | 390 Sample* new_sample = sample_buffer_->ReserveSampleAndLink(sample_); |
398 if (new_sample == NULL) { | 391 if (new_sample == NULL) { |
399 // Could not reserve new sample- mark this as truncated. | 392 // Could not reserve new sample- mark this as truncated. |
400 sample_->set_truncated_trace(true); | 393 sample_->set_truncated_trace(true); |
401 return false; | 394 return false; |
402 } | 395 } |
403 frame_index_ = 0; | 396 frame_index_ = 0; |
404 sample_ = new_sample; | 397 sample_ = new_sample; |
405 } | 398 } |
406 ASSERT(frame_index_ < kSampleSize); | 399 ASSERT(frame_index_ < kSampleSize); |
407 sample_->SetAt(frame_index_, pc); | 400 sample_->SetAt(frame_index_, pc); |
408 frame_index_++; | 401 frame_index_++; |
409 total_frames_++; | 402 total_frames_++; |
410 return true; | 403 return true; |
411 } | 404 } |
412 | 405 |
413 protected: | 406 protected: |
414 Dart_Port port_id_; | 407 Isolate* isolate_; |
415 Sample* sample_; | 408 Sample* sample_; |
416 SampleBuffer* sample_buffer_; | 409 SampleBuffer* sample_buffer_; |
417 intptr_t skip_count_; | |
418 intptr_t frames_skipped_; | |
419 intptr_t frame_index_; | 410 intptr_t frame_index_; |
420 intptr_t total_frames_; | 411 intptr_t total_frames_; |
421 }; | 412 }; |
422 | 413 |
423 | 414 |
424 // Executing Dart code, walk the stack. | 415 // Executing Dart code, walk the stack. |
425 class ProfilerDartStackWalker : public ProfilerStackWalker { | 416 class ProfilerDartStackWalker : public ProfilerStackWalker { |
426 public: | 417 public: |
427 ProfilerDartStackWalker(Thread* thread, | 418 ProfilerDartStackWalker(Thread* thread, |
428 Sample* sample, | 419 Sample* sample, |
429 SampleBuffer* sample_buffer, | 420 SampleBuffer* sample_buffer, |
430 uword stack_lower, | 421 uword stack_lower, |
431 uword stack_upper, | 422 uword stack_upper, |
432 uword pc, | 423 uword pc, |
433 uword fp, | 424 uword fp, |
434 uword sp, | 425 uword sp, |
435 bool exited_dart_code, | 426 bool exited_dart_code, |
436 bool allocation_sample, | 427 bool allocation_sample) |
437 intptr_t skip_count = 0) | 428 : ProfilerStackWalker(thread->isolate(), sample, sample_buffer), |
438 : ProfilerStackWalker((thread->isolate() != NULL) | |
439 ? thread->isolate()->main_port() | |
440 : ILLEGAL_PORT, | |
441 sample, | |
442 sample_buffer, | |
443 skip_count), | |
444 pc_(reinterpret_cast<uword*>(pc)), | 429 pc_(reinterpret_cast<uword*>(pc)), |
445 fp_(reinterpret_cast<uword*>(fp)), | 430 fp_(reinterpret_cast<uword*>(fp)), |
446 sp_(reinterpret_cast<uword*>(sp)), | 431 sp_(reinterpret_cast<uword*>(sp)), |
447 stack_upper_(stack_upper), | 432 stack_upper_(stack_upper), |
448 stack_lower_(stack_lower), | 433 stack_lower_(stack_lower), |
449 has_exit_frame_(exited_dart_code) { | 434 has_exit_frame_(exited_dart_code) { |
450 if (exited_dart_code) { | 435 if (exited_dart_code) { |
451 StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames, | 436 StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames, |
452 thread); | 437 thread); |
453 pc_ = NULL; | 438 pc_ = NULL; |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
605 bool has_exit_frame_; | 590 bool has_exit_frame_; |
606 }; | 591 }; |
607 | 592 |
608 | 593 |
609 // If the VM is compiled without frame pointers (which is the default on | 594 // If the VM is compiled without frame pointers (which is the default on |
610 // recent GCC versions with optimizing enabled) the stack walking code may | 595 // recent GCC versions with optimizing enabled) the stack walking code may |
611 // fail. | 596 // fail. |
612 // | 597 // |
613 class ProfilerNativeStackWalker : public ProfilerStackWalker { | 598 class ProfilerNativeStackWalker : public ProfilerStackWalker { |
614 public: | 599 public: |
615 ProfilerNativeStackWalker(Dart_Port port_id, | 600 ProfilerNativeStackWalker(Isolate* isolate, |
616 Sample* sample, | 601 Sample* sample, |
617 SampleBuffer* sample_buffer, | 602 SampleBuffer* sample_buffer, |
618 uword stack_lower, | 603 uword stack_lower, |
619 uword stack_upper, | 604 uword stack_upper, |
620 uword pc, | 605 uword pc, |
621 uword fp, | 606 uword fp, |
622 uword sp, | 607 uword sp) |
623 intptr_t skip_count = 0) | 608 : ProfilerStackWalker(isolate, sample, sample_buffer), |
624 : ProfilerStackWalker(port_id, sample, sample_buffer, skip_count), | |
625 stack_upper_(stack_upper), | 609 stack_upper_(stack_upper), |
626 original_pc_(pc), | 610 original_pc_(pc), |
627 original_fp_(fp), | 611 original_fp_(fp), |
628 original_sp_(sp), | 612 original_sp_(sp), |
629 lower_bound_(stack_lower) {} | 613 lower_bound_(stack_lower) {} |
630 | 614 |
631 void walk() { | 615 void walk() { |
632 const uword kMaxStep = VirtualMemory::PageSize(); | 616 const uword kMaxStep = VirtualMemory::PageSize(); |
633 | |
634 Append(original_pc_); | 617 Append(original_pc_); |
635 | 618 |
636 uword* pc = reinterpret_cast<uword*>(original_pc_); | 619 uword* pc = reinterpret_cast<uword*>(original_pc_); |
637 uword* fp = reinterpret_cast<uword*>(original_fp_); | 620 uword* fp = reinterpret_cast<uword*>(original_fp_); |
638 uword* previous_fp = fp; | 621 uword* previous_fp = fp; |
639 | 622 |
640 uword gap = original_fp_ - original_sp_; | 623 uword gap = original_fp_ - original_sp_; |
641 if (gap >= kMaxStep) { | 624 if (gap >= kMaxStep) { |
642 // Gap between frame pointer and stack pointer is | 625 // Gap between frame pointer and stack pointer is |
643 // too large. | 626 // too large. |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
806 VirtualProtect(reinterpret_cast<void*>(fault_address), | 789 VirtualProtect(reinterpret_cast<void*>(fault_address), |
807 sizeof(fault_address), new_protect, &old_protect); | 790 sizeof(fault_address), new_protect, &old_protect); |
808 USE(success); | 791 USE(success); |
809 ASSERT(success); | 792 ASSERT(success); |
810 ASSERT(old_protect == PAGE_READWRITE); | 793 ASSERT(old_protect == PAGE_READWRITE); |
811 } | 794 } |
812 #endif | 795 #endif |
813 } | 796 } |
814 | 797 |
815 | 798 |
816 static bool ValidateThreadStackBounds(uintptr_t fp, | |
817 uintptr_t sp, | |
818 uword stack_lower, | |
819 uword stack_upper) { | |
820 if (stack_lower >= stack_upper) { | |
821 // Stack boundary is invalid. | |
822 return false; | |
823 } | |
824 | |
825 if ((sp < stack_lower) || (sp >= stack_upper)) { | |
826 // Stack pointer is outside thread's stack boundary. | |
827 return false; | |
828 } | |
829 | |
830 if ((fp < stack_lower) || (fp >= stack_upper)) { | |
831 // Frame pointer is outside threads's stack boundary. | |
832 return false; | |
833 } | |
834 | |
835 return true; | |
836 } | |
837 | |
838 | |
839 // Get |isolate|'s stack boundary and verify that |sp| and |fp| are within | 799 // Get |isolate|'s stack boundary and verify that |sp| and |fp| are within |
840 // it. If |get_os_thread_bounds| is true then if |isolate| stackbounds are | 800 // it. If |get_os_thread_bounds| is true then if |isolate| stackbounds are |
841 // not available we fallback to using underlying OS thread bounds. This only | 801 // not available we fallback to using underlying OS thread bounds. This only |
842 // works for the current thread. | 802 // works for the current thread. |
843 // Return |false| if anything looks suspicious. | 803 // Return |false| if anything looks suspicious. |
844 static bool GetAndValidateThreadStackBounds(Thread* thread, | 804 static bool GetAndValidateThreadStackBounds(Thread* thread, |
845 uintptr_t fp, | 805 uintptr_t fp, |
846 uintptr_t sp, | 806 uintptr_t sp, |
847 uword* stack_lower, | 807 uword* stack_lower, |
848 uword* stack_upper, | 808 uword* stack_upper, |
849 bool get_os_thread_bounds = false) { | 809 bool get_os_thread_bounds = false) { |
850 OSThread* os_thread = NULL; | 810 ASSERT(thread != NULL); |
851 if (thread != NULL) { | 811 OSThread* os_thread = thread->os_thread(); |
852 os_thread = thread->os_thread(); | |
853 } else { | |
854 os_thread = OSThread::Current(); | |
855 } | |
856 ASSERT(os_thread != NULL); | 812 ASSERT(os_thread != NULL); |
857 ASSERT(stack_lower != NULL); | 813 ASSERT(stack_lower != NULL); |
858 ASSERT(stack_upper != NULL); | 814 ASSERT(stack_upper != NULL); |
859 ASSERT(!get_os_thread_bounds || (Thread::Current() == thread)); | 815 ASSERT(!get_os_thread_bounds || (Thread::Current() == thread)); |
860 | 816 |
861 #if defined(USING_SIMULATOR) | 817 #if defined(USING_SIMULATOR) |
862 const bool use_simulator_stack_bounds = thread->IsExecutingDartCode(); | 818 const bool use_simulator_stack_bounds = thread->IsExecutingDartCode(); |
863 if (use_simulator_stack_bounds) { | 819 if (use_simulator_stack_bounds) { |
864 Isolate* isolate = thread->isolate(); | 820 Isolate* isolate = thread->isolate(); |
865 ASSERT(isolate != NULL); | 821 ASSERT(isolate != NULL); |
(...skipping 15 matching lines...) Expand all Loading... |
881 | 837 |
882 if ((*stack_lower == 0) || (*stack_upper == 0)) { | 838 if ((*stack_lower == 0) || (*stack_upper == 0)) { |
883 return false; | 839 return false; |
884 } | 840 } |
885 | 841 |
886 if (!use_simulator_stack_bounds && (sp > *stack_lower)) { | 842 if (!use_simulator_stack_bounds && (sp > *stack_lower)) { |
887 // The stack pointer gives us a tighter lower bound. | 843 // The stack pointer gives us a tighter lower bound. |
888 *stack_lower = sp; | 844 *stack_lower = sp; |
889 } | 845 } |
890 | 846 |
891 return ValidateThreadStackBounds(fp, sp, *stack_lower, *stack_upper); | 847 if (*stack_lower >= *stack_upper) { |
| 848 // Stack boundary is invalid. |
| 849 return false; |
| 850 } |
| 851 |
| 852 if ((sp < *stack_lower) || (sp >= *stack_upper)) { |
| 853 // Stack pointer is outside thread's stack boundary. |
| 854 return false; |
| 855 } |
| 856 |
| 857 if ((fp < *stack_lower) || (fp >= *stack_upper)) { |
| 858 // Frame pointer is outside threads's stack boundary. |
| 859 return false; |
| 860 } |
| 861 |
| 862 return true; |
892 } | 863 } |
893 | 864 |
894 | 865 |
895 // Some simple sanity checking of |pc|, |fp|, and |sp|. | 866 // Some simple sanity checking of |pc|, |fp|, and |sp|. |
896 static bool InitialRegisterCheck(uintptr_t pc, uintptr_t fp, uintptr_t sp) { | 867 static bool InitialRegisterCheck(uintptr_t pc, uintptr_t fp, uintptr_t sp) { |
897 if ((sp == 0) || (fp == 0) || (pc == 0)) { | 868 if ((sp == 0) || (fp == 0) || (pc == 0)) { |
898 // None of these registers should be zero. | 869 // None of these registers should be zero. |
899 return false; | 870 return false; |
900 } | 871 } |
901 | 872 |
902 if (sp > fp) { | 873 if (sp > fp) { |
903 // Assuming the stack grows down, we should never have a stack pointer above | 874 // Assuming the stack grows down, we should never have a stack pointer above |
904 // the frame pointer. | 875 // the frame pointer. |
905 return false; | 876 return false; |
906 } | 877 } |
907 | 878 |
908 return true; | 879 return true; |
909 } | 880 } |
910 | 881 |
911 | 882 |
912 static Sample* SetupSample(Thread* thread, | 883 static Sample* SetupSample(Thread* thread, |
913 SampleBuffer* sample_buffer, | 884 SampleBuffer* sample_buffer, |
914 ThreadId tid) { | 885 ThreadId tid) { |
915 ASSERT(thread != NULL); | 886 ASSERT(thread != NULL); |
916 Isolate* isolate = thread->isolate(); | 887 Isolate* isolate = thread->isolate(); |
917 ASSERT(sample_buffer != NULL); | 888 ASSERT(sample_buffer != NULL); |
918 Sample* sample = sample_buffer->ReserveSample(); | 889 Sample* sample = sample_buffer->ReserveSample(); |
919 sample->Init(isolate->main_port(), OS::GetCurrentMonotonicMicros(), tid); | 890 sample->Init(isolate, OS::GetCurrentMonotonicMicros(), tid); |
920 uword vm_tag = thread->vm_tag(); | 891 uword vm_tag = thread->vm_tag(); |
921 #if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC) | 892 #if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC) |
922 // When running in the simulator, the runtime entry function address | 893 // When running in the simulator, the runtime entry function address |
923 // (stored as the vm tag) is the address of a redirect function. | 894 // (stored as the vm tag) is the address of a redirect function. |
924 // Attempt to find the real runtime entry function address and use that. | 895 // Attempt to find the real runtime entry function address and use that. |
925 uword redirect_vm_tag = Simulator::FunctionForRedirect(vm_tag); | 896 uword redirect_vm_tag = Simulator::FunctionForRedirect(vm_tag); |
926 if (redirect_vm_tag != 0) { | 897 if (redirect_vm_tag != 0) { |
927 vm_tag = redirect_vm_tag; | 898 vm_tag = redirect_vm_tag; |
928 } | 899 } |
929 #endif | 900 #endif |
930 sample->set_vm_tag(vm_tag); | 901 sample->set_vm_tag(vm_tag); |
931 sample->set_user_tag(isolate->user_tag()); | 902 sample->set_user_tag(isolate->user_tag()); |
932 sample->set_thread_task(thread->task_kind()); | 903 sample->set_thread_task(thread->task_kind()); |
933 return sample; | 904 return sample; |
934 } | 905 } |
935 | 906 |
936 | 907 |
937 static Sample* SetupSampleNative(SampleBuffer* sample_buffer, ThreadId tid) { | |
938 Sample* sample = sample_buffer->ReserveSample(); | |
939 sample->Init(ILLEGAL_PORT, OS::GetCurrentMonotonicMicros(), tid); | |
940 sample->set_is_native_allocation_sample(true); | |
941 | |
942 Thread* thread = Thread::Current(); | |
943 | |
944 // TODO(bkonyi) Any samples created while a current thread doesn't exist are | |
945 // ignored by the NativeAllocationSampleFilter since the default task is | |
946 // kUnknownTask. Is this what we want to do? | |
947 if (thread != NULL) { | |
948 sample->set_thread_task(thread->task_kind()); | |
949 } | |
950 return sample; | |
951 } | |
952 | |
953 | |
954 static bool CheckIsolate(Isolate* isolate) { | 908 static bool CheckIsolate(Isolate* isolate) { |
955 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) { | 909 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) { |
956 // No isolate. | 910 // No isolate. |
957 return false; | 911 return false; |
958 } | 912 } |
959 return isolate != Dart::vm_isolate(); | 913 return isolate != Dart::vm_isolate(); |
960 } | 914 } |
961 | 915 |
962 | 916 |
| 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 |
963 void Profiler::DumpStackTrace(void* context) { | 929 void Profiler::DumpStackTrace(void* context) { |
964 #if defined(TARGET_OS_LINUX) || defined(TARGET_OS_MACOS) | 930 #if defined(TARGET_OS_LINUX) || defined(TARGET_OS_MACOS) |
965 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); | 931 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); |
966 mcontext_t mcontext = ucontext->uc_mcontext; | 932 mcontext_t mcontext = ucontext->uc_mcontext; |
967 uword pc = SignalHandler::GetProgramCounter(mcontext); | 933 uword pc = SignalHandler::GetProgramCounter(mcontext); |
968 uword fp = SignalHandler::GetFramePointer(mcontext); | 934 uword fp = SignalHandler::GetFramePointer(mcontext); |
969 uword sp = SignalHandler::GetCStackPointer(mcontext); | 935 uword sp = SignalHandler::GetCStackPointer(mcontext); |
970 DumpStackTrace(sp, fp, pc); | 936 DumpStackTrace(sp, fp, pc); |
971 #else | 937 #else |
972 // TODO(fschneider): Add support for more platforms. | 938 // TODO(fschneider): Add support for more platforms. |
973 // Do nothing on unsupported platforms. | 939 // Do nothing on unsupported platforms. |
974 #endif | 940 #endif |
975 } | 941 } |
976 | 942 |
977 | 943 |
978 void Profiler::DumpStackTrace() { | 944 void Profiler::DumpStackTrace() { |
979 uintptr_t sp = Thread::GetCurrentStackPointer(); | 945 uintptr_t sp = Thread::GetCurrentStackPointer(); |
980 uintptr_t fp = 0; | 946 uintptr_t fp = 0; |
981 uintptr_t pc = OS::GetProgramCounter(); | 947 uintptr_t pc = GetProgramCounter(); |
982 | 948 |
983 COPY_FP_REGISTER(fp); | 949 COPY_FP_REGISTER(fp); |
984 | 950 |
985 DumpStackTrace(sp, fp, pc); | 951 DumpStackTrace(sp, fp, pc); |
986 } | 952 } |
987 | 953 |
988 | 954 |
989 void Profiler::DumpStackTrace(uword sp, uword fp, uword pc) { | 955 void Profiler::DumpStackTrace(uword sp, uword fp, uword pc) { |
990 // Allow only one stack trace to prevent recursively printing stack traces if | 956 // Allow only one stack trace to prevent recursively printing stack traces if |
991 // we hit an assert while printing the stack. | 957 // we hit an assert while printing the stack. |
(...skipping 27 matching lines...) Expand all Loading... |
1019 | 985 |
1020 if (!GetAndValidateThreadStackBounds(thread, fp, sp, &stack_lower, | 986 if (!GetAndValidateThreadStackBounds(thread, fp, sp, &stack_lower, |
1021 &stack_upper, | 987 &stack_upper, |
1022 /*get_os_thread_bounds=*/true)) { | 988 /*get_os_thread_bounds=*/true)) { |
1023 OS::PrintErr( | 989 OS::PrintErr( |
1024 "Stack dump aborted because GetAndValidateThreadStackBounds.\n"); | 990 "Stack dump aborted because GetAndValidateThreadStackBounds.\n"); |
1025 return; | 991 return; |
1026 } | 992 } |
1027 | 993 |
1028 ProfilerNativeStackWalker native_stack_walker( | 994 ProfilerNativeStackWalker native_stack_walker( |
1029 (isolate != NULL) ? isolate->main_port() : ILLEGAL_PORT, NULL, NULL, | 995 isolate, NULL, NULL, stack_lower, stack_upper, pc, fp, sp); |
1030 stack_lower, stack_upper, pc, fp, sp); | |
1031 native_stack_walker.walk(); | 996 native_stack_walker.walk(); |
1032 OS::PrintErr("-- End of DumpStackTrace\n"); | 997 OS::PrintErr("-- End of DumpStackTrace\n"); |
1033 } | 998 } |
1034 | 999 |
1035 | 1000 |
1036 void Profiler::SampleAllocation(Thread* thread, intptr_t cid) { | 1001 void Profiler::SampleAllocation(Thread* thread, intptr_t cid) { |
1037 ASSERT(thread != NULL); | 1002 ASSERT(thread != NULL); |
1038 OSThread* os_thread = thread->os_thread(); | 1003 OSThread* os_thread = thread->os_thread(); |
1039 ASSERT(os_thread != NULL); | 1004 ASSERT(os_thread != NULL); |
1040 Isolate* isolate = thread->isolate(); | 1005 Isolate* isolate = thread->isolate(); |
1041 if (!CheckIsolate(isolate)) { | 1006 if (!CheckIsolate(isolate)) { |
1042 return; | 1007 return; |
1043 } | 1008 } |
1044 | 1009 |
1045 const bool exited_dart_code = thread->HasExitedDartCode(); | 1010 const bool exited_dart_code = thread->HasExitedDartCode(); |
1046 | 1011 |
1047 SampleBuffer* sample_buffer = Profiler::sample_buffer(); | 1012 SampleBuffer* sample_buffer = Profiler::sample_buffer(); |
1048 if (sample_buffer == NULL) { | 1013 if (sample_buffer == NULL) { |
1049 // Profiler not initialized. | 1014 // Profiler not initialized. |
1050 return; | 1015 return; |
1051 } | 1016 } |
1052 | 1017 |
1053 uintptr_t sp = Thread::GetCurrentStackPointer(); | 1018 uintptr_t sp = Thread::GetCurrentStackPointer(); |
1054 uintptr_t fp = 0; | 1019 uintptr_t fp = 0; |
1055 uintptr_t pc = OS::GetProgramCounter(); | 1020 uintptr_t pc = GetProgramCounter(); |
1056 | 1021 |
1057 COPY_FP_REGISTER(fp); | 1022 COPY_FP_REGISTER(fp); |
1058 | 1023 |
1059 uword stack_lower = 0; | 1024 uword stack_lower = 0; |
1060 uword stack_upper = 0; | 1025 uword stack_upper = 0; |
1061 | 1026 |
1062 if (!InitialRegisterCheck(pc, fp, sp)) { | 1027 if (!InitialRegisterCheck(pc, fp, sp)) { |
1063 return; | 1028 return; |
1064 } | 1029 } |
1065 | 1030 |
1066 if (!GetAndValidateThreadStackBounds(thread, fp, sp, &stack_lower, | 1031 if (!GetAndValidateThreadStackBounds(thread, fp, sp, &stack_lower, |
1067 &stack_upper)) { | 1032 &stack_upper)) { |
1068 // Could not get stack boundary. | 1033 // Could not get stack boundary. |
1069 return; | 1034 return; |
1070 } | 1035 } |
1071 | 1036 |
1072 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id()); | 1037 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id()); |
1073 sample->SetAllocationCid(cid); | 1038 sample->SetAllocationCid(cid); |
1074 | 1039 |
1075 if (FLAG_profile_vm) { | 1040 if (FLAG_profile_vm) { |
1076 ProfilerNativeStackWalker native_stack_walker( | 1041 ProfilerNativeStackWalker native_stack_walker( |
1077 (isolate != NULL) ? isolate->main_port() : ILLEGAL_PORT, sample, | 1042 isolate, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp); |
1078 sample_buffer, stack_lower, stack_upper, pc, fp, sp); | |
1079 native_stack_walker.walk(); | 1043 native_stack_walker.walk(); |
1080 } else if (exited_dart_code) { | 1044 } else if (exited_dart_code) { |
1081 ProfilerDartStackWalker dart_exit_stack_walker( | 1045 ProfilerDartStackWalker dart_exit_stack_walker( |
1082 thread, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp, | 1046 thread, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp, |
1083 exited_dart_code, true); | 1047 exited_dart_code, true); |
1084 dart_exit_stack_walker.walk(); | 1048 dart_exit_stack_walker.walk(); |
1085 } else { | 1049 } else { |
1086 // Fall back. | 1050 // Fall back. |
1087 uintptr_t pc = OS::GetProgramCounter(); | 1051 uintptr_t pc = GetProgramCounter(); |
1088 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id()); | 1052 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id()); |
1089 sample->SetAllocationCid(cid); | 1053 sample->SetAllocationCid(cid); |
1090 sample->SetAt(0, pc); | 1054 sample->SetAt(0, pc); |
1091 } | 1055 } |
1092 } | 1056 } |
1093 | 1057 |
1094 | 1058 |
1095 Sample* Profiler::SampleNativeAllocation(intptr_t skip_count) { | |
1096 SampleBuffer* sample_buffer = Profiler::sample_buffer(); | |
1097 if (sample_buffer == NULL) { | |
1098 return NULL; | |
1099 } | |
1100 | |
1101 uintptr_t sp = Thread::GetCurrentStackPointer(); | |
1102 uintptr_t fp = 0; | |
1103 uintptr_t pc = OS::GetProgramCounter(); | |
1104 | |
1105 COPY_FP_REGISTER(fp); | |
1106 | |
1107 uword stack_lower = 0; | |
1108 uword stack_upper = 0; | |
1109 if (!InitialRegisterCheck(pc, fp, sp)) { | |
1110 AtomicOperations::IncrementInt64By( | |
1111 &counters_.failure_native_allocation_sample, 1); | |
1112 return NULL; | |
1113 } | |
1114 | |
1115 if (!(OSThread::GetCurrentStackBounds(&stack_lower, &stack_upper) && | |
1116 ValidateThreadStackBounds(fp, sp, stack_lower, stack_upper))) { | |
1117 // Could not get stack boundary. | |
1118 AtomicOperations::IncrementInt64By( | |
1119 &counters_.failure_native_allocation_sample, 1); | |
1120 return NULL; | |
1121 } | |
1122 | |
1123 OSThread* os_thread = OSThread::Current(); | |
1124 Sample* sample = SetupSampleNative(sample_buffer, os_thread->trace_id()); | |
1125 ProfilerNativeStackWalker native_stack_walker( | |
1126 ILLEGAL_PORT, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp, | |
1127 skip_count); | |
1128 native_stack_walker.walk(); | |
1129 return sample; | |
1130 } | |
1131 | |
1132 | |
1133 void Profiler::SampleThreadSingleFrame(Thread* thread, uintptr_t pc) { | 1059 void Profiler::SampleThreadSingleFrame(Thread* thread, uintptr_t pc) { |
1134 ASSERT(thread != NULL); | 1060 ASSERT(thread != NULL); |
1135 OSThread* os_thread = thread->os_thread(); | 1061 OSThread* os_thread = thread->os_thread(); |
1136 ASSERT(os_thread != NULL); | 1062 ASSERT(os_thread != NULL); |
1137 Isolate* isolate = thread->isolate(); | 1063 Isolate* isolate = thread->isolate(); |
1138 | 1064 |
1139 SampleBuffer* sample_buffer = Profiler::sample_buffer(); | 1065 SampleBuffer* sample_buffer = Profiler::sample_buffer(); |
1140 if (sample_buffer == NULL) { | 1066 if (sample_buffer == NULL) { |
1141 // Profiler not initialized. | 1067 // Profiler not initialized. |
1142 return; | 1068 return; |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1248 // Setup sample. | 1174 // Setup sample. |
1249 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id()); | 1175 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id()); |
1250 // Increment counter for vm tag. | 1176 // Increment counter for vm tag. |
1251 VMTagCounters* counters = isolate->vm_tag_counters(); | 1177 VMTagCounters* counters = isolate->vm_tag_counters(); |
1252 ASSERT(counters != NULL); | 1178 ASSERT(counters != NULL); |
1253 if (thread->IsMutatorThread()) { | 1179 if (thread->IsMutatorThread()) { |
1254 counters->Increment(sample->vm_tag()); | 1180 counters->Increment(sample->vm_tag()); |
1255 } | 1181 } |
1256 | 1182 |
1257 ProfilerNativeStackWalker native_stack_walker( | 1183 ProfilerNativeStackWalker native_stack_walker( |
1258 (isolate != NULL) ? isolate->main_port() : ILLEGAL_PORT, sample, | 1184 isolate, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp); |
1259 sample_buffer, stack_lower, stack_upper, pc, fp, sp); | |
1260 const bool exited_dart_code = thread->HasExitedDartCode(); | 1185 const bool exited_dart_code = thread->HasExitedDartCode(); |
1261 ProfilerDartStackWalker dart_stack_walker(thread, sample, sample_buffer, | 1186 ProfilerDartStackWalker dart_stack_walker(thread, sample, sample_buffer, |
1262 stack_lower, stack_upper, pc, fp, | 1187 stack_lower, stack_upper, pc, fp, |
1263 sp, exited_dart_code, false); | 1188 sp, exited_dart_code, false); |
1264 | 1189 |
1265 // All memory access is done inside CollectSample. | 1190 // All memory access is done inside CollectSample. |
1266 CollectSample(isolate, exited_dart_code, in_dart_code, sample, | 1191 CollectSample(isolate, exited_dart_code, in_dart_code, sample, |
1267 &native_stack_walker, &dart_stack_walker, pc, fp, sp, | 1192 &native_stack_walker, &dart_stack_walker, pc, fp, sp, |
1268 &counters_); | 1193 &counters_); |
1269 } | 1194 } |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1409 for (intptr_t i = 0; i < length; i++) { | 1334 for (intptr_t i = 0; i < length; i++) { |
1410 Sample* sample = At(i); | 1335 Sample* sample = At(i); |
1411 if (sample->ignore_sample()) { | 1336 if (sample->ignore_sample()) { |
1412 // Bad sample. | 1337 // Bad sample. |
1413 continue; | 1338 continue; |
1414 } | 1339 } |
1415 if (!sample->head_sample()) { | 1340 if (!sample->head_sample()) { |
1416 // An inner sample in a chain of samples. | 1341 // An inner sample in a chain of samples. |
1417 continue; | 1342 continue; |
1418 } | 1343 } |
1419 // If we're requesting all the native allocation samples, we don't care | 1344 if (sample->isolate() != filter->isolate()) { |
1420 // whether or not we're in the same isolate as the sample. | |
1421 if (sample->port() != filter->port()) { | |
1422 // Another isolate. | 1345 // Another isolate. |
1423 continue; | 1346 continue; |
1424 } | 1347 } |
1425 if (sample->timestamp() == 0) { | 1348 if (sample->timestamp() == 0) { |
1426 // Empty. | 1349 // Empty. |
1427 continue; | 1350 continue; |
1428 } | 1351 } |
1429 if (sample->At(0) == 0) { | 1352 if (sample->At(0) == 0) { |
1430 // No frames. | 1353 // No frames. |
1431 continue; | 1354 continue; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1490 return processed_sample; | 1413 return processed_sample; |
1491 } | 1414 } |
1492 | 1415 |
1493 | 1416 |
1494 Sample* SampleBuffer::Next(Sample* sample) { | 1417 Sample* SampleBuffer::Next(Sample* sample) { |
1495 if (!sample->is_continuation_sample()) return NULL; | 1418 if (!sample->is_continuation_sample()) return NULL; |
1496 Sample* next_sample = At(sample->continuation_index()); | 1419 Sample* next_sample = At(sample->continuation_index()); |
1497 // Sanity check. | 1420 // Sanity check. |
1498 ASSERT(sample != next_sample); | 1421 ASSERT(sample != next_sample); |
1499 // Detect invalid chaining. | 1422 // Detect invalid chaining. |
1500 if (sample->port() != next_sample->port()) { | 1423 if (sample->isolate() != next_sample->isolate()) { |
1501 return NULL; | 1424 return NULL; |
1502 } | 1425 } |
1503 if (sample->timestamp() != next_sample->timestamp()) { | 1426 if (sample->timestamp() != next_sample->timestamp()) { |
1504 return NULL; | 1427 return NULL; |
1505 } | 1428 } |
1506 if (sample->tid() != next_sample->tid()) { | 1429 if (sample->tid() != next_sample->tid()) { |
1507 return NULL; | 1430 return NULL; |
1508 } | 1431 } |
1509 return next_sample; | 1432 return next_sample; |
1510 } | 1433 } |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1592 | 1515 |
1593 | 1516 |
1594 ProcessedSampleBuffer::ProcessedSampleBuffer() | 1517 ProcessedSampleBuffer::ProcessedSampleBuffer() |
1595 : code_lookup_table_(new CodeLookupTable(Thread::Current())) { | 1518 : code_lookup_table_(new CodeLookupTable(Thread::Current())) { |
1596 ASSERT(code_lookup_table_ != NULL); | 1519 ASSERT(code_lookup_table_ != NULL); |
1597 } | 1520 } |
1598 | 1521 |
1599 #endif // !PRODUCT | 1522 #endif // !PRODUCT |
1600 | 1523 |
1601 } // namespace dart | 1524 } // namespace dart |
OLD | NEW |