Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(85)

Side by Side Diff: runtime/vm/profiler.cc

Issue 2680213002: Updated MallocHooks to collect stack traces when memory is allocated. (Closed)
Patch Set: Updated MallocHooks to collect stack traces when memory is allocated. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/profiler.h ('k') | runtime/vm/profiler_service.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
789 VirtualProtect(reinterpret_cast<void*>(fault_address), 806 VirtualProtect(reinterpret_cast<void*>(fault_address),
790 sizeof(fault_address), new_protect, &old_protect); 807 sizeof(fault_address), new_protect, &old_protect);
791 USE(success); 808 USE(success);
792 ASSERT(success); 809 ASSERT(success);
793 ASSERT(old_protect == PAGE_READWRITE); 810 ASSERT(old_protect == PAGE_READWRITE);
794 } 811 }
795 #endif 812 #endif
796 } 813 }
797 814
798 815
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
799 // Get |isolate|'s stack boundary and verify that |sp| and |fp| are within 839 // Get |isolate|'s stack boundary and verify that |sp| and |fp| are within
800 // it. If |get_os_thread_bounds| is true then if |isolate| stackbounds are 840 // 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 841 // not available we fallback to using underlying OS thread bounds. This only
802 // works for the current thread. 842 // works for the current thread.
803 // Return |false| if anything looks suspicious. 843 // Return |false| if anything looks suspicious.
804 static bool GetAndValidateThreadStackBounds(Thread* thread, 844 static bool GetAndValidateThreadStackBounds(Thread* thread,
805 uintptr_t fp, 845 uintptr_t fp,
806 uintptr_t sp, 846 uintptr_t sp,
807 uword* stack_lower, 847 uword* stack_lower,
808 uword* stack_upper, 848 uword* stack_upper,
809 bool get_os_thread_bounds = false) { 849 bool get_os_thread_bounds = false) {
810 ASSERT(thread != NULL); 850 OSThread* os_thread = NULL;
811 OSThread* os_thread = thread->os_thread(); 851 if (thread != NULL) {
852 os_thread = thread->os_thread();
853 } else {
854 os_thread = OSThread::Current();
855 }
812 ASSERT(os_thread != NULL); 856 ASSERT(os_thread != NULL);
813 ASSERT(stack_lower != NULL); 857 ASSERT(stack_lower != NULL);
814 ASSERT(stack_upper != NULL); 858 ASSERT(stack_upper != NULL);
815 ASSERT(!get_os_thread_bounds || (Thread::Current() == thread)); 859 ASSERT(!get_os_thread_bounds || (Thread::Current() == thread));
816 860
817 #if defined(USING_SIMULATOR) 861 #if defined(USING_SIMULATOR)
818 const bool use_simulator_stack_bounds = thread->IsExecutingDartCode(); 862 const bool use_simulator_stack_bounds = thread->IsExecutingDartCode();
819 if (use_simulator_stack_bounds) { 863 if (use_simulator_stack_bounds) {
820 Isolate* isolate = thread->isolate(); 864 Isolate* isolate = thread->isolate();
821 ASSERT(isolate != NULL); 865 ASSERT(isolate != NULL);
(...skipping 15 matching lines...) Expand all
837 881
838 if ((*stack_lower == 0) || (*stack_upper == 0)) { 882 if ((*stack_lower == 0) || (*stack_upper == 0)) {
839 return false; 883 return false;
840 } 884 }
841 885
842 if (!use_simulator_stack_bounds && (sp > *stack_lower)) { 886 if (!use_simulator_stack_bounds && (sp > *stack_lower)) {
843 // The stack pointer gives us a tighter lower bound. 887 // The stack pointer gives us a tighter lower bound.
844 *stack_lower = sp; 888 *stack_lower = sp;
845 } 889 }
846 890
847 if (*stack_lower >= *stack_upper) { 891 return ValidateThreadStackBounds(fp, sp, *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;
863 } 892 }
864 893
865 894
866 // Some simple sanity checking of |pc|, |fp|, and |sp|. 895 // Some simple sanity checking of |pc|, |fp|, and |sp|.
867 static bool InitialRegisterCheck(uintptr_t pc, uintptr_t fp, uintptr_t sp) { 896 static bool InitialRegisterCheck(uintptr_t pc, uintptr_t fp, uintptr_t sp) {
868 if ((sp == 0) || (fp == 0) || (pc == 0)) { 897 if ((sp == 0) || (fp == 0) || (pc == 0)) {
869 // None of these registers should be zero. 898 // None of these registers should be zero.
870 return false; 899 return false;
871 } 900 }
872 901
873 if (sp > fp) { 902 if (sp > fp) {
874 // Assuming the stack grows down, we should never have a stack pointer above 903 // Assuming the stack grows down, we should never have a stack pointer above
875 // the frame pointer. 904 // the frame pointer.
876 return false; 905 return false;
877 } 906 }
878 907
879 return true; 908 return true;
880 } 909 }
881 910
882 911
883 static Sample* SetupSample(Thread* thread, 912 static Sample* SetupSample(Thread* thread,
884 SampleBuffer* sample_buffer, 913 SampleBuffer* sample_buffer,
885 ThreadId tid) { 914 ThreadId tid) {
886 ASSERT(thread != NULL); 915 ASSERT(thread != NULL);
887 Isolate* isolate = thread->isolate(); 916 Isolate* isolate = thread->isolate();
888 ASSERT(sample_buffer != NULL); 917 ASSERT(sample_buffer != NULL);
889 Sample* sample = sample_buffer->ReserveSample(); 918 Sample* sample = sample_buffer->ReserveSample();
890 sample->Init(isolate, OS::GetCurrentMonotonicMicros(), tid); 919 sample->Init(isolate->main_port(), OS::GetCurrentMonotonicMicros(), tid);
891 uword vm_tag = thread->vm_tag(); 920 uword vm_tag = thread->vm_tag();
892 #if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC) 921 #if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC)
893 // When running in the simulator, the runtime entry function address 922 // When running in the simulator, the runtime entry function address
894 // (stored as the vm tag) is the address of a redirect function. 923 // (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. 924 // Attempt to find the real runtime entry function address and use that.
896 uword redirect_vm_tag = Simulator::FunctionForRedirect(vm_tag); 925 uword redirect_vm_tag = Simulator::FunctionForRedirect(vm_tag);
897 if (redirect_vm_tag != 0) { 926 if (redirect_vm_tag != 0) {
898 vm_tag = redirect_vm_tag; 927 vm_tag = redirect_vm_tag;
899 } 928 }
900 #endif 929 #endif
901 sample->set_vm_tag(vm_tag); 930 sample->set_vm_tag(vm_tag);
902 sample->set_user_tag(isolate->user_tag()); 931 sample->set_user_tag(isolate->user_tag());
903 sample->set_thread_task(thread->task_kind()); 932 sample->set_thread_task(thread->task_kind());
904 return sample; 933 return sample;
905 } 934 }
906 935
907 936
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
908 static bool CheckIsolate(Isolate* isolate) { 954 static bool CheckIsolate(Isolate* isolate) {
909 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) { 955 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) {
910 // No isolate. 956 // No isolate.
911 return false; 957 return false;
912 } 958 }
913 return isolate != Dart::vm_isolate(); 959 return isolate != Dart::vm_isolate();
914 } 960 }
915 961
916 962
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) { 963 void Profiler::DumpStackTrace(void* context) {
930 #if defined(TARGET_OS_LINUX) || defined(TARGET_OS_MACOS) 964 #if defined(TARGET_OS_LINUX) || defined(TARGET_OS_MACOS)
931 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); 965 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
932 mcontext_t mcontext = ucontext->uc_mcontext; 966 mcontext_t mcontext = ucontext->uc_mcontext;
933 uword pc = SignalHandler::GetProgramCounter(mcontext); 967 uword pc = SignalHandler::GetProgramCounter(mcontext);
934 uword fp = SignalHandler::GetFramePointer(mcontext); 968 uword fp = SignalHandler::GetFramePointer(mcontext);
935 uword sp = SignalHandler::GetCStackPointer(mcontext); 969 uword sp = SignalHandler::GetCStackPointer(mcontext);
936 DumpStackTrace(sp, fp, pc); 970 DumpStackTrace(sp, fp, pc);
937 #else 971 #else
938 // TODO(fschneider): Add support for more platforms. 972 // TODO(fschneider): Add support for more platforms.
939 // Do nothing on unsupported platforms. 973 // Do nothing on unsupported platforms.
940 #endif 974 #endif
941 } 975 }
942 976
943 977
944 void Profiler::DumpStackTrace() { 978 void Profiler::DumpStackTrace() {
945 uintptr_t sp = Thread::GetCurrentStackPointer(); 979 uintptr_t sp = Thread::GetCurrentStackPointer();
946 uintptr_t fp = 0; 980 uintptr_t fp = 0;
947 uintptr_t pc = GetProgramCounter(); 981 uintptr_t pc = OS::GetProgramCounter();
948 982
949 COPY_FP_REGISTER(fp); 983 COPY_FP_REGISTER(fp);
950 984
951 DumpStackTrace(sp, fp, pc); 985 DumpStackTrace(sp, fp, pc);
952 } 986 }
953 987
954 988
955 void Profiler::DumpStackTrace(uword sp, uword fp, uword pc) { 989 void Profiler::DumpStackTrace(uword sp, uword fp, uword pc) {
956 // Allow only one stack trace to prevent recursively printing stack traces if 990 // Allow only one stack trace to prevent recursively printing stack traces if
957 // we hit an assert while printing the stack. 991 // we hit an assert while printing the stack.
(...skipping 27 matching lines...) Expand all
985 1019
986 if (!GetAndValidateThreadStackBounds(thread, fp, sp, &stack_lower, 1020 if (!GetAndValidateThreadStackBounds(thread, fp, sp, &stack_lower,
987 &stack_upper, 1021 &stack_upper,
988 /*get_os_thread_bounds=*/true)) { 1022 /*get_os_thread_bounds=*/true)) {
989 OS::PrintErr( 1023 OS::PrintErr(
990 "Stack dump aborted because GetAndValidateThreadStackBounds.\n"); 1024 "Stack dump aborted because GetAndValidateThreadStackBounds.\n");
991 return; 1025 return;
992 } 1026 }
993 1027
994 ProfilerNativeStackWalker native_stack_walker( 1028 ProfilerNativeStackWalker native_stack_walker(
995 isolate, NULL, NULL, stack_lower, stack_upper, pc, fp, sp); 1029 (isolate != NULL) ? isolate->main_port() : ILLEGAL_PORT, NULL, NULL,
1030 stack_lower, stack_upper, pc, fp, sp);
996 native_stack_walker.walk(); 1031 native_stack_walker.walk();
997 OS::PrintErr("-- End of DumpStackTrace\n"); 1032 OS::PrintErr("-- End of DumpStackTrace\n");
998 } 1033 }
999 1034
1000 1035
1001 void Profiler::SampleAllocation(Thread* thread, intptr_t cid) { 1036 void Profiler::SampleAllocation(Thread* thread, intptr_t cid) {
1002 ASSERT(thread != NULL); 1037 ASSERT(thread != NULL);
1003 OSThread* os_thread = thread->os_thread(); 1038 OSThread* os_thread = thread->os_thread();
1004 ASSERT(os_thread != NULL); 1039 ASSERT(os_thread != NULL);
1005 Isolate* isolate = thread->isolate(); 1040 Isolate* isolate = thread->isolate();
1006 if (!CheckIsolate(isolate)) { 1041 if (!CheckIsolate(isolate)) {
1007 return; 1042 return;
1008 } 1043 }
1009 1044
1010 const bool exited_dart_code = thread->HasExitedDartCode(); 1045 const bool exited_dart_code = thread->HasExitedDartCode();
1011 1046
1012 SampleBuffer* sample_buffer = Profiler::sample_buffer(); 1047 SampleBuffer* sample_buffer = Profiler::sample_buffer();
1013 if (sample_buffer == NULL) { 1048 if (sample_buffer == NULL) {
1014 // Profiler not initialized. 1049 // Profiler not initialized.
1015 return; 1050 return;
1016 } 1051 }
1017 1052
1018 uintptr_t sp = Thread::GetCurrentStackPointer(); 1053 uintptr_t sp = Thread::GetCurrentStackPointer();
1019 uintptr_t fp = 0; 1054 uintptr_t fp = 0;
1020 uintptr_t pc = GetProgramCounter(); 1055 uintptr_t pc = OS::GetProgramCounter();
1021 1056
1022 COPY_FP_REGISTER(fp); 1057 COPY_FP_REGISTER(fp);
1023 1058
1024 uword stack_lower = 0; 1059 uword stack_lower = 0;
1025 uword stack_upper = 0; 1060 uword stack_upper = 0;
1026 1061
1027 if (!InitialRegisterCheck(pc, fp, sp)) { 1062 if (!InitialRegisterCheck(pc, fp, sp)) {
1028 return; 1063 return;
1029 } 1064 }
1030 1065
1031 if (!GetAndValidateThreadStackBounds(thread, fp, sp, &stack_lower, 1066 if (!GetAndValidateThreadStackBounds(thread, fp, sp, &stack_lower,
1032 &stack_upper)) { 1067 &stack_upper)) {
1033 // Could not get stack boundary. 1068 // Could not get stack boundary.
1034 return; 1069 return;
1035 } 1070 }
1036 1071
1037 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id()); 1072 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id());
1038 sample->SetAllocationCid(cid); 1073 sample->SetAllocationCid(cid);
1039 1074
1040 if (FLAG_profile_vm) { 1075 if (FLAG_profile_vm) {
1041 ProfilerNativeStackWalker native_stack_walker( 1076 ProfilerNativeStackWalker native_stack_walker(
1042 isolate, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp); 1077 (isolate != NULL) ? isolate->main_port() : ILLEGAL_PORT, sample,
1078 sample_buffer, stack_lower, stack_upper, pc, fp, sp);
1043 native_stack_walker.walk(); 1079 native_stack_walker.walk();
1044 } else if (exited_dart_code) { 1080 } else if (exited_dart_code) {
1045 ProfilerDartStackWalker dart_exit_stack_walker( 1081 ProfilerDartStackWalker dart_exit_stack_walker(
1046 thread, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp, 1082 thread, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp,
1047 exited_dart_code, true); 1083 exited_dart_code, true);
1048 dart_exit_stack_walker.walk(); 1084 dart_exit_stack_walker.walk();
1049 } else { 1085 } else {
1050 // Fall back. 1086 // Fall back.
1051 uintptr_t pc = GetProgramCounter(); 1087 uintptr_t pc = OS::GetProgramCounter();
1052 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id()); 1088 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id());
1053 sample->SetAllocationCid(cid); 1089 sample->SetAllocationCid(cid);
1054 sample->SetAt(0, pc); 1090 sample->SetAt(0, pc);
1055 } 1091 }
1056 } 1092 }
1057 1093
1058 1094
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
1059 void Profiler::SampleThreadSingleFrame(Thread* thread, uintptr_t pc) { 1133 void Profiler::SampleThreadSingleFrame(Thread* thread, uintptr_t pc) {
1060 ASSERT(thread != NULL); 1134 ASSERT(thread != NULL);
1061 OSThread* os_thread = thread->os_thread(); 1135 OSThread* os_thread = thread->os_thread();
1062 ASSERT(os_thread != NULL); 1136 ASSERT(os_thread != NULL);
1063 Isolate* isolate = thread->isolate(); 1137 Isolate* isolate = thread->isolate();
1064 1138
1065 SampleBuffer* sample_buffer = Profiler::sample_buffer(); 1139 SampleBuffer* sample_buffer = Profiler::sample_buffer();
1066 if (sample_buffer == NULL) { 1140 if (sample_buffer == NULL) {
1067 // Profiler not initialized. 1141 // Profiler not initialized.
1068 return; 1142 return;
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
1174 // Setup sample. 1248 // Setup sample.
1175 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id()); 1249 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id());
1176 // Increment counter for vm tag. 1250 // Increment counter for vm tag.
1177 VMTagCounters* counters = isolate->vm_tag_counters(); 1251 VMTagCounters* counters = isolate->vm_tag_counters();
1178 ASSERT(counters != NULL); 1252 ASSERT(counters != NULL);
1179 if (thread->IsMutatorThread()) { 1253 if (thread->IsMutatorThread()) {
1180 counters->Increment(sample->vm_tag()); 1254 counters->Increment(sample->vm_tag());
1181 } 1255 }
1182 1256
1183 ProfilerNativeStackWalker native_stack_walker( 1257 ProfilerNativeStackWalker native_stack_walker(
1184 isolate, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp); 1258 (isolate != NULL) ? isolate->main_port() : ILLEGAL_PORT, sample,
1259 sample_buffer, stack_lower, stack_upper, pc, fp, sp);
1185 const bool exited_dart_code = thread->HasExitedDartCode(); 1260 const bool exited_dart_code = thread->HasExitedDartCode();
1186 ProfilerDartStackWalker dart_stack_walker(thread, sample, sample_buffer, 1261 ProfilerDartStackWalker dart_stack_walker(thread, sample, sample_buffer,
1187 stack_lower, stack_upper, pc, fp, 1262 stack_lower, stack_upper, pc, fp,
1188 sp, exited_dart_code, false); 1263 sp, exited_dart_code, false);
1189 1264
1190 // All memory access is done inside CollectSample. 1265 // All memory access is done inside CollectSample.
1191 CollectSample(isolate, exited_dart_code, in_dart_code, sample, 1266 CollectSample(isolate, exited_dart_code, in_dart_code, sample,
1192 &native_stack_walker, &dart_stack_walker, pc, fp, sp, 1267 &native_stack_walker, &dart_stack_walker, pc, fp, sp,
1193 &counters_); 1268 &counters_);
1194 } 1269 }
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
1334 for (intptr_t i = 0; i < length; i++) { 1409 for (intptr_t i = 0; i < length; i++) {
1335 Sample* sample = At(i); 1410 Sample* sample = At(i);
1336 if (sample->ignore_sample()) { 1411 if (sample->ignore_sample()) {
1337 // Bad sample. 1412 // Bad sample.
1338 continue; 1413 continue;
1339 } 1414 }
1340 if (!sample->head_sample()) { 1415 if (!sample->head_sample()) {
1341 // An inner sample in a chain of samples. 1416 // An inner sample in a chain of samples.
1342 continue; 1417 continue;
1343 } 1418 }
1344 if (sample->isolate() != filter->isolate()) { 1419 // If we're requesting all the native allocation samples, we don't care
1420 // whether or not we're in the same isolate as the sample.
1421 if (sample->port() != filter->port()) {
1345 // Another isolate. 1422 // Another isolate.
1346 continue; 1423 continue;
1347 } 1424 }
1348 if (sample->timestamp() == 0) { 1425 if (sample->timestamp() == 0) {
1349 // Empty. 1426 // Empty.
1350 continue; 1427 continue;
1351 } 1428 }
1352 if (sample->At(0) == 0) { 1429 if (sample->At(0) == 0) {
1353 // No frames. 1430 // No frames.
1354 continue; 1431 continue;
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1413 return processed_sample; 1490 return processed_sample;
1414 } 1491 }
1415 1492
1416 1493
1417 Sample* SampleBuffer::Next(Sample* sample) { 1494 Sample* SampleBuffer::Next(Sample* sample) {
1418 if (!sample->is_continuation_sample()) return NULL; 1495 if (!sample->is_continuation_sample()) return NULL;
1419 Sample* next_sample = At(sample->continuation_index()); 1496 Sample* next_sample = At(sample->continuation_index());
1420 // Sanity check. 1497 // Sanity check.
1421 ASSERT(sample != next_sample); 1498 ASSERT(sample != next_sample);
1422 // Detect invalid chaining. 1499 // Detect invalid chaining.
1423 if (sample->isolate() != next_sample->isolate()) { 1500 if (sample->port() != next_sample->port()) {
1424 return NULL; 1501 return NULL;
1425 } 1502 }
1426 if (sample->timestamp() != next_sample->timestamp()) { 1503 if (sample->timestamp() != next_sample->timestamp()) {
1427 return NULL; 1504 return NULL;
1428 } 1505 }
1429 if (sample->tid() != next_sample->tid()) { 1506 if (sample->tid() != next_sample->tid()) {
1430 return NULL; 1507 return NULL;
1431 } 1508 }
1432 return next_sample; 1509 return next_sample;
1433 } 1510 }
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
1515 1592
1516 1593
1517 ProcessedSampleBuffer::ProcessedSampleBuffer() 1594 ProcessedSampleBuffer::ProcessedSampleBuffer()
1518 : code_lookup_table_(new CodeLookupTable(Thread::Current())) { 1595 : code_lookup_table_(new CodeLookupTable(Thread::Current())) {
1519 ASSERT(code_lookup_table_ != NULL); 1596 ASSERT(code_lookup_table_ != NULL);
1520 } 1597 }
1521 1598
1522 #endif // !PRODUCT 1599 #endif // !PRODUCT
1523 1600
1524 } // namespace dart 1601 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/profiler.h ('k') | runtime/vm/profiler_service.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698