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

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

Issue 2680213002: Updated MallocHooks to collect stack traces when memory is allocated. (Closed)
Patch Set: Added tests and modified stack walker to allow for skipping an arbitrary number of frames before co… 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
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 : port_id_(port_id),
364 sample_(head_sample), 364 sample_(head_sample),
365 sample_buffer_(sample_buffer), 365 sample_buffer_(sample_buffer),
366 frame_index_(0), 366 frame_index_(0),
367 total_frames_(0) { 367 total_frames_(0) {
368 ASSERT(isolate_ != NULL);
369 if (sample_ == NULL) { 368 if (sample_ == NULL) {
370 ASSERT(sample_buffer_ == NULL); 369 ASSERT(sample_buffer_ == NULL);
371 } else { 370 } else {
372 ASSERT(sample_buffer_ != NULL); 371 ASSERT(sample_buffer_ != NULL);
373 ASSERT(sample_->head_sample()); 372 ASSERT(sample_->head_sample());
374 } 373 }
375 } 374 }
376 375
377 bool Append(uword pc) { 376 bool Append(uword pc) {
378 if (sample_ == NULL) { 377 if (sample_ == NULL) {
(...skipping 18 matching lines...) Expand all
397 sample_ = new_sample; 396 sample_ = new_sample;
398 } 397 }
399 ASSERT(frame_index_ < kSampleSize); 398 ASSERT(frame_index_ < kSampleSize);
400 sample_->SetAt(frame_index_, pc); 399 sample_->SetAt(frame_index_, pc);
401 frame_index_++; 400 frame_index_++;
402 total_frames_++; 401 total_frames_++;
403 return true; 402 return true;
404 } 403 }
405 404
406 protected: 405 protected:
407 Isolate* isolate_; 406 Dart_Port port_id_;
408 Sample* sample_; 407 Sample* sample_;
409 SampleBuffer* sample_buffer_; 408 SampleBuffer* sample_buffer_;
410 intptr_t frame_index_; 409 intptr_t frame_index_;
411 intptr_t total_frames_; 410 intptr_t total_frames_;
412 }; 411 };
413 412
414 413
415 // Executing Dart code, walk the stack. 414 // Executing Dart code, walk the stack.
416 class ProfilerDartStackWalker : public ProfilerStackWalker { 415 class ProfilerDartStackWalker : public ProfilerStackWalker {
417 public: 416 public:
418 ProfilerDartStackWalker(Thread* thread, 417 ProfilerDartStackWalker(Thread* thread,
419 Sample* sample, 418 Sample* sample,
420 SampleBuffer* sample_buffer, 419 SampleBuffer* sample_buffer,
421 uword stack_lower, 420 uword stack_lower,
422 uword stack_upper, 421 uword stack_upper,
423 uword pc, 422 uword pc,
424 uword fp, 423 uword fp,
425 uword sp, 424 uword sp,
426 bool exited_dart_code, 425 bool exited_dart_code,
427 bool allocation_sample) 426 bool allocation_sample)
428 : ProfilerStackWalker(thread->isolate(), sample, sample_buffer), 427 : ProfilerStackWalker((thread->isolate() != NULL)
428 ? thread->isolate()->main_port()
429 : ILLEGAL_PORT,
430 sample,
431 sample_buffer),
429 pc_(reinterpret_cast<uword*>(pc)), 432 pc_(reinterpret_cast<uword*>(pc)),
430 fp_(reinterpret_cast<uword*>(fp)), 433 fp_(reinterpret_cast<uword*>(fp)),
431 sp_(reinterpret_cast<uword*>(sp)), 434 sp_(reinterpret_cast<uword*>(sp)),
432 stack_upper_(stack_upper), 435 stack_upper_(stack_upper),
433 stack_lower_(stack_lower), 436 stack_lower_(stack_lower),
434 has_exit_frame_(exited_dart_code) { 437 has_exit_frame_(exited_dart_code) {
435 if (exited_dart_code) { 438 if (exited_dart_code) {
436 StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames, 439 StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames,
437 thread); 440 thread);
438 pc_ = NULL; 441 pc_ = NULL;
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 bool has_exit_frame_; 593 bool has_exit_frame_;
591 }; 594 };
592 595
593 596
594 // If the VM is compiled without frame pointers (which is the default on 597 // 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 598 // recent GCC versions with optimizing enabled) the stack walking code may
596 // fail. 599 // fail.
597 // 600 //
598 class ProfilerNativeStackWalker : public ProfilerStackWalker { 601 class ProfilerNativeStackWalker : public ProfilerStackWalker {
599 public: 602 public:
600 ProfilerNativeStackWalker(Isolate* isolate, 603 ProfilerNativeStackWalker(Dart_Port port_id,
601 Sample* sample, 604 Sample* sample,
602 SampleBuffer* sample_buffer, 605 SampleBuffer* sample_buffer,
603 uword stack_lower, 606 uword stack_lower,
604 uword stack_upper, 607 uword stack_upper,
605 uword pc, 608 uword pc,
606 uword fp, 609 uword fp,
607 uword sp) 610 uword sp,
608 : ProfilerStackWalker(isolate, sample, sample_buffer), 611 intptr_t skip_count = 0)
Cutch 2017/02/15 08:21:00 Support for skip count should be generalized and p
bkonyi 2017/02/16 00:28:28 Done.
612 : ProfilerStackWalker(port_id, sample, sample_buffer),
609 stack_upper_(stack_upper), 613 stack_upper_(stack_upper),
610 original_pc_(pc), 614 original_pc_(pc),
611 original_fp_(fp), 615 original_fp_(fp),
612 original_sp_(sp), 616 original_sp_(sp),
613 lower_bound_(stack_lower) {} 617 lower_bound_(stack_lower),
618 skip_count_(skip_count) {}
614 619
615 void walk() { 620 void walk() {
616 const uword kMaxStep = VirtualMemory::PageSize(); 621 const uword kMaxStep = VirtualMemory::PageSize();
617 Append(original_pc_); 622 intptr_t frame_count = 0;
623
624 if (frame_count >= skip_count_) {
625 Append(original_pc_);
626 }
627 ++frame_count;
618 628
619 uword* pc = reinterpret_cast<uword*>(original_pc_); 629 uword* pc = reinterpret_cast<uword*>(original_pc_);
620 uword* fp = reinterpret_cast<uword*>(original_fp_); 630 uword* fp = reinterpret_cast<uword*>(original_fp_);
621 uword* previous_fp = fp; 631 uword* previous_fp = fp;
622 632
623 uword gap = original_fp_ - original_sp_; 633 uword gap = original_fp_ - original_sp_;
624 if (gap >= kMaxStep) { 634 if (gap >= kMaxStep) {
625 // Gap between frame pointer and stack pointer is 635 // Gap between frame pointer and stack pointer is
626 // too large. 636 // too large.
627 return; 637 return;
628 } 638 }
629 639
630 if (!ValidFramePointer(fp)) { 640 if (!ValidFramePointer(fp)) {
631 return; 641 return;
632 } 642 }
633 643
634 while (true) { 644 while (true) {
635 if (!Append(reinterpret_cast<uword>(pc))) { 645 if (frame_count >= skip_count_ && !Append(reinterpret_cast<uword>(pc))) {
Cutch 2017/02/15 08:21:00 wrap in parens: (frame_count >= skip_count_) Also
bkonyi 2017/02/16 00:28:29 Acknowledged.
636 return; 646 return;
637 } 647 }
638 648
639 pc = CallerPC(fp); 649 pc = CallerPC(fp);
640 previous_fp = fp; 650 previous_fp = fp;
641 fp = CallerFP(fp); 651 fp = CallerFP(fp);
642 652
643 if (fp == NULL) { 653 if (fp == NULL) {
644 return; 654 return;
645 } 655 }
646 656
647 if (fp <= previous_fp) { 657 if (fp <= previous_fp) {
648 // Frame pointer did not move to a higher address. 658 // Frame pointer did not move to a higher address.
649 return; 659 return;
650 } 660 }
651 661
652 gap = fp - previous_fp; 662 gap = fp - previous_fp;
653 if (gap >= kMaxStep) { 663 if (gap >= kMaxStep) {
654 // Frame pointer step is too large. 664 // Frame pointer step is too large.
655 return; 665 return;
656 } 666 }
657 667
658 if (!ValidFramePointer(fp)) { 668 if (!ValidFramePointer(fp)) {
659 // Frame pointer is outside of isolate stack boundary. 669 // Frame pointer is outside of isolate stack boundary.
660 return; 670 return;
661 } 671 }
662 672
663 // Move the lower bound up. 673 // Move the lower bound up.
664 lower_bound_ = reinterpret_cast<uword>(fp); 674 lower_bound_ = reinterpret_cast<uword>(fp);
675 ++frame_count;
Cutch 2017/02/15 08:21:00 You should bump frame_count immediately after the
bkonyi 2017/02/16 00:28:29 Acknowledged.
665 } 676 }
666 } 677 }
667 678
668 private: 679 private:
669 uword* CallerPC(uword* fp) const { 680 uword* CallerPC(uword* fp) const {
670 ASSERT(fp != NULL); 681 ASSERT(fp != NULL);
671 uword* caller_pc_ptr = fp + kSavedCallerPcSlotFromFp; 682 uword* caller_pc_ptr = fp + kSavedCallerPcSlotFromFp;
672 // This may actually be uninitialized, by design (see class comment above). 683 // This may actually be uninitialized, by design (see class comment above).
673 MSAN_UNPOISON(caller_pc_ptr, kWordSize); 684 MSAN_UNPOISON(caller_pc_ptr, kWordSize);
674 ASAN_UNPOISON(caller_pc_ptr, kWordSize); 685 ASAN_UNPOISON(caller_pc_ptr, kWordSize);
(...skipping 17 matching lines...) Expand all
692 cursor += sizeof(fp); 703 cursor += sizeof(fp);
693 bool r = (cursor >= lower_bound_) && (cursor < stack_upper_); 704 bool r = (cursor >= lower_bound_) && (cursor < stack_upper_);
694 return r; 705 return r;
695 } 706 }
696 707
697 const uword stack_upper_; 708 const uword stack_upper_;
698 const uword original_pc_; 709 const uword original_pc_;
699 const uword original_fp_; 710 const uword original_fp_;
700 const uword original_sp_; 711 const uword original_sp_;
701 uword lower_bound_; 712 uword lower_bound_;
713 intptr_t skip_count_;
702 }; 714 };
703 715
704 716
705 static void CopyStackBuffer(Sample* sample, uword sp_addr) { 717 static void CopyStackBuffer(Sample* sample, uword sp_addr) {
706 ASSERT(sample != NULL); 718 ASSERT(sample != NULL);
707 uword* sp = reinterpret_cast<uword*>(sp_addr); 719 uword* sp = reinterpret_cast<uword*>(sp_addr);
708 uword* buffer = sample->GetStackBuffer(); 720 uword* buffer = sample->GetStackBuffer();
709 if (sp != NULL) { 721 if (sp != NULL) {
710 for (intptr_t i = 0; i < Sample::kStackBufferSizeInWords; i++) { 722 for (intptr_t i = 0; i < Sample::kStackBufferSizeInWords; i++) {
711 MSAN_UNPOISON(sp, kWordSize); 723 MSAN_UNPOISON(sp, kWordSize);
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
791 USE(success); 803 USE(success);
792 ASSERT(success); 804 ASSERT(success);
793 ASSERT(old_protect == PAGE_READWRITE); 805 ASSERT(old_protect == PAGE_READWRITE);
794 } 806 }
795 #endif 807 #endif
796 } 808 }
797 809
798 810
799 // Get |isolate|'s stack boundary and verify that |sp| and |fp| are within 811 // Get |isolate|'s stack boundary and verify that |sp| and |fp| are within
800 // it. Return |false| if anything looks suspicious. 812 // it. Return |false| if anything looks suspicious.
801 static bool GetAndValidateIsolateStackBounds(Thread* thread, 813 static bool GetAndValidateStackBounds(Thread* thread,
Cutch 2017/02/15 08:21:00 Seems like a bad merge here. Please see this CL:
bkonyi 2017/02/16 00:28:29 Not a bad merge, just haven't rebased in awhile. D
802 uintptr_t fp, 814 uintptr_t fp,
803 uintptr_t sp, 815 uintptr_t sp,
804 uword* stack_lower, 816 uword* stack_lower,
805 uword* stack_upper) { 817 uword* stack_upper) {
806 ASSERT(thread != NULL); 818 OSThread* os_thread = NULL;
807 OSThread* os_thread = thread->os_thread(); 819 if (thread != NULL) {
820 os_thread = thread->os_thread();
821 } else {
822 os_thread = OSThread::Current();
823 }
808 ASSERT(os_thread != NULL); 824 ASSERT(os_thread != NULL);
809 ASSERT(stack_lower != NULL); 825 ASSERT(stack_lower != NULL);
810 ASSERT(stack_upper != NULL); 826 ASSERT(stack_upper != NULL);
811 #if defined(USING_SIMULATOR) 827 #if defined(USING_SIMULATOR)
812 const bool in_dart_code = thread->IsExecutingDartCode(); 828 const bool in_dart_code =
829 (thread == NULL) ? false : thread->IsExecutingDartCode();
813 if (in_dart_code) { 830 if (in_dart_code) {
814 Isolate* isolate = thread->isolate(); 831 Isolate* isolate = thread->isolate();
815 ASSERT(isolate != NULL); 832 ASSERT(isolate != NULL);
816 Simulator* simulator = isolate->simulator(); 833 Simulator* simulator = isolate->simulator();
817 *stack_lower = simulator->StackBase(); 834 *stack_lower = simulator->StackBase();
818 *stack_upper = simulator->StackTop(); 835 *stack_upper = simulator->StackTop();
819 } else if (!os_thread->GetProfilerStackBounds(stack_lower, stack_upper)) { 836 } else if (!os_thread->GetProfilerStackBounds(stack_lower, stack_upper)) {
820 // Could not get stack boundary. 837 // Could not get stack boundary.
821 return false; 838 return false;
822 } 839 }
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
879 } 896 }
880 897
881 898
882 static Sample* SetupSample(Thread* thread, 899 static Sample* SetupSample(Thread* thread,
883 SampleBuffer* sample_buffer, 900 SampleBuffer* sample_buffer,
884 ThreadId tid) { 901 ThreadId tid) {
885 ASSERT(thread != NULL); 902 ASSERT(thread != NULL);
886 Isolate* isolate = thread->isolate(); 903 Isolate* isolate = thread->isolate();
887 ASSERT(sample_buffer != NULL); 904 ASSERT(sample_buffer != NULL);
888 Sample* sample = sample_buffer->ReserveSample(); 905 Sample* sample = sample_buffer->ReserveSample();
889 sample->Init(isolate, OS::GetCurrentMonotonicMicros(), tid); 906 sample->Init(isolate->main_port(), OS::GetCurrentMonotonicMicros(), tid);
890 uword vm_tag = thread->vm_tag(); 907 uword vm_tag = thread->vm_tag();
891 #if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC) 908 #if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC)
892 // When running in the simulator, the runtime entry function address 909 // When running in the simulator, the runtime entry function address
893 // (stored as the vm tag) is the address of a redirect function. 910 // (stored as the vm tag) is the address of a redirect function.
894 // Attempt to find the real runtime entry function address and use that. 911 // Attempt to find the real runtime entry function address and use that.
895 uword redirect_vm_tag = Simulator::FunctionForRedirect(vm_tag); 912 uword redirect_vm_tag = Simulator::FunctionForRedirect(vm_tag);
896 if (redirect_vm_tag != 0) { 913 if (redirect_vm_tag != 0) {
897 vm_tag = redirect_vm_tag; 914 vm_tag = redirect_vm_tag;
898 } 915 }
899 #endif 916 #endif
900 sample->set_vm_tag(vm_tag); 917 sample->set_vm_tag(vm_tag);
901 sample->set_user_tag(isolate->user_tag()); 918 sample->set_user_tag(isolate->user_tag());
902 sample->set_thread_task(thread->task_kind()); 919 sample->set_thread_task(thread->task_kind());
903 return sample; 920 return sample;
904 } 921 }
905 922
906 923
924 static Sample* SetupSampleNative(SampleBuffer* sample_buffer, ThreadId tid) {
925 Sample* sample = sample_buffer->ReserveSample();
926 sample->Init(ILLEGAL_PORT, OS::GetCurrentMonotonicMicros(), tid);
927 sample->set_is_native_allocation_sample(true);
928
929 Thread* thread = Thread::Current();
930
931 // TODO(bkonyi) Any samples created while a current thread doesn't exist are
932 // ignored by the NativeAllocationSampleFilter since the default task is
933 // kUnknownTask. Is this what we want to do?
934 if (thread != NULL) {
935 sample->set_thread_task(thread->task_kind());
936 }
937 return sample;
938 }
939
940
907 static bool CheckIsolate(Isolate* isolate) { 941 static bool CheckIsolate(Isolate* isolate) {
908 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) { 942 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) {
909 // No isolate. 943 // No isolate.
910 return false; 944 return false;
911 } 945 }
912 return isolate != Dart::vm_isolate(); 946 return isolate != Dart::vm_isolate();
913 } 947 }
914 948
915 949
916 #if defined(TARGET_OS_WINDOWS) 950 #if defined(TARGET_OS_WINDOWS)
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
975 OSThread::ThreadIdToIntPtr(os_thread->trace_id())); 1009 OSThread::ThreadIdToIntPtr(os_thread->trace_id()));
976 1010
977 uword stack_lower = 0; 1011 uword stack_lower = 0;
978 uword stack_upper = 0; 1012 uword stack_upper = 0;
979 1013
980 if (!InitialRegisterCheck(pc, fp, sp)) { 1014 if (!InitialRegisterCheck(pc, fp, sp)) {
981 OS::PrintErr("Stack dump aborted because InitialRegisterCheck.\n"); 1015 OS::PrintErr("Stack dump aborted because InitialRegisterCheck.\n");
982 return; 1016 return;
983 } 1017 }
984 1018
985 if (!GetAndValidateIsolateStackBounds(thread, fp, sp, &stack_lower, 1019 if (!GetAndValidateStackBounds(thread, fp, sp, &stack_lower, &stack_upper)) {
986 &stack_upper)) { 1020 OS::PrintErr("Stack dump aborted because GetAndValidateStackBounds.\n");
987 OS::PrintErr(
988 "Stack dump aborted because GetAndValidateIsolateStackBounds.\n");
989 return; 1021 return;
990 } 1022 }
991 1023
992 ProfilerNativeStackWalker native_stack_walker( 1024 ProfilerNativeStackWalker native_stack_walker(
993 isolate, NULL, NULL, stack_lower, stack_upper, pc, fp, sp); 1025 (isolate != NULL) ? isolate->main_port() : ILLEGAL_PORT, NULL, NULL,
1026 stack_lower, stack_upper, pc, fp, sp);
994 native_stack_walker.walk(); 1027 native_stack_walker.walk();
995 OS::PrintErr("-- End of DumpStackTrace\n"); 1028 OS::PrintErr("-- End of DumpStackTrace\n");
996 } 1029 }
997 1030
998 1031
999 void Profiler::SampleAllocation(Thread* thread, intptr_t cid) { 1032 void Profiler::SampleAllocation(Thread* thread, intptr_t cid) {
1000 ASSERT(thread != NULL); 1033 ASSERT(thread != NULL);
1001 OSThread* os_thread = thread->os_thread(); 1034 OSThread* os_thread = thread->os_thread();
1002 ASSERT(os_thread != NULL); 1035 ASSERT(os_thread != NULL);
1003 Isolate* isolate = thread->isolate(); 1036 Isolate* isolate = thread->isolate();
(...skipping 15 matching lines...) Expand all
1019 1052
1020 COPY_FP_REGISTER(fp); 1053 COPY_FP_REGISTER(fp);
1021 1054
1022 uword stack_lower = 0; 1055 uword stack_lower = 0;
1023 uword stack_upper = 0; 1056 uword stack_upper = 0;
1024 1057
1025 if (!InitialRegisterCheck(pc, fp, sp)) { 1058 if (!InitialRegisterCheck(pc, fp, sp)) {
1026 return; 1059 return;
1027 } 1060 }
1028 1061
1029 if (!GetAndValidateIsolateStackBounds(thread, fp, sp, &stack_lower, 1062 if (!GetAndValidateStackBounds(thread, fp, sp, &stack_lower, &stack_upper)) {
1030 &stack_upper)) {
1031 // Could not get stack boundary. 1063 // Could not get stack boundary.
1032 return; 1064 return;
1033 } 1065 }
1034 1066
1035 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id()); 1067 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id());
1036 sample->SetAllocationCid(cid); 1068 sample->SetAllocationCid(cid);
1037 1069
1038 if (FLAG_profile_vm) { 1070 if (FLAG_profile_vm) {
1039 ProfilerNativeStackWalker native_stack_walker( 1071 ProfilerNativeStackWalker native_stack_walker(
1040 isolate, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp); 1072 (isolate != NULL) ? isolate->main_port() : ILLEGAL_PORT, sample,
1073 sample_buffer, stack_lower, stack_upper, pc, fp, sp);
1041 native_stack_walker.walk(); 1074 native_stack_walker.walk();
1042 } else if (exited_dart_code) { 1075 } else if (exited_dart_code) {
1043 ProfilerDartStackWalker dart_exit_stack_walker( 1076 ProfilerDartStackWalker dart_exit_stack_walker(
1044 thread, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp, 1077 thread, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp,
1045 exited_dart_code, true); 1078 exited_dart_code, true);
1046 dart_exit_stack_walker.walk(); 1079 dart_exit_stack_walker.walk();
1047 } else { 1080 } else {
1048 // Fall back. 1081 // Fall back.
1049 uintptr_t pc = GetProgramCounter(); 1082 uintptr_t pc = GetProgramCounter();
1050 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id()); 1083 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id());
1051 sample->SetAllocationCid(cid); 1084 sample->SetAllocationCid(cid);
1052 sample->SetAt(0, pc); 1085 sample->SetAt(0, pc);
1053 } 1086 }
1054 } 1087 }
1055 1088
1056 1089
1090 Sample* Profiler::SampleNativeAllocation(intptr_t skip_count) {
1091 SampleBuffer* sample_buffer = Profiler::sample_buffer();
1092 if (sample_buffer == NULL) {
1093 return NULL;
1094 }
1095
1096 uintptr_t sp = Thread::GetCurrentStackPointer();
1097 uintptr_t fp = 0;
1098 uintptr_t pc = GetProgramCounter();
1099
1100 COPY_FP_REGISTER(fp);
1101
1102 uword stack_lower = 0;
1103 uword stack_upper = 0;
1104 if (!InitialRegisterCheck(pc, fp, sp)) {
1105 return NULL;
1106 }
1107
1108 OSThread* os_thread = OSThread::Current();
1109 if (os_thread->stack_base() == 0) {
1110 stack_lower = sp;
1111 stack_upper = ~static_cast<uintptr_t>(0x0);
1112 } else {
1113 if (!GetAndValidateStackBounds(NULL, fp, sp, &stack_lower, &stack_upper)) {
1114 // Could not get stack boundary.
1115 return NULL;
1116 }
1117 }
1118 Sample* sample = SetupSampleNative(sample_buffer, os_thread->trace_id());
1119 ProfilerNativeStackWalker native_stack_walker(
1120 ILLEGAL_PORT, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp,
1121 skip_count);
1122 native_stack_walker.walk();
1123 return sample;
1124 }
1125
1126
1057 void Profiler::SampleThreadSingleFrame(Thread* thread, uintptr_t pc) { 1127 void Profiler::SampleThreadSingleFrame(Thread* thread, uintptr_t pc) {
1058 ASSERT(thread != NULL); 1128 ASSERT(thread != NULL);
1059 OSThread* os_thread = thread->os_thread(); 1129 OSThread* os_thread = thread->os_thread();
1060 ASSERT(os_thread != NULL); 1130 ASSERT(os_thread != NULL);
1061 Isolate* isolate = thread->isolate(); 1131 Isolate* isolate = thread->isolate();
1062 1132
1063 SampleBuffer* sample_buffer = Profiler::sample_buffer(); 1133 SampleBuffer* sample_buffer = Profiler::sample_buffer();
1064 if (sample_buffer == NULL) { 1134 if (sample_buffer == NULL) {
1065 // Profiler not initialized. 1135 // Profiler not initialized.
1066 return; 1136 return;
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1145 1215
1146 if (!InitialRegisterCheck(pc, fp, sp)) { 1216 if (!InitialRegisterCheck(pc, fp, sp)) {
1147 AtomicOperations::IncrementInt64By( 1217 AtomicOperations::IncrementInt64By(
1148 &counters_.single_frame_sample_register_check, 1); 1218 &counters_.single_frame_sample_register_check, 1);
1149 SampleThreadSingleFrame(thread, pc); 1219 SampleThreadSingleFrame(thread, pc);
1150 return; 1220 return;
1151 } 1221 }
1152 1222
1153 uword stack_lower = 0; 1223 uword stack_lower = 0;
1154 uword stack_upper = 0; 1224 uword stack_upper = 0;
1155 if (!GetAndValidateIsolateStackBounds(thread, fp, sp, &stack_lower, 1225 if (!GetAndValidateStackBounds(thread, fp, sp, &stack_lower, &stack_upper)) {
1156 &stack_upper)) {
1157 AtomicOperations::IncrementInt64By( 1226 AtomicOperations::IncrementInt64By(
1158 &counters_.single_frame_sample_get_and_validate_stack_bounds, 1); 1227 &counters_.single_frame_sample_get_and_validate_stack_bounds, 1);
1159 // Could not get stack boundary. 1228 // Could not get stack boundary.
1160 SampleThreadSingleFrame(thread, pc); 1229 SampleThreadSingleFrame(thread, pc);
1161 return; 1230 return;
1162 } 1231 }
1163 1232
1164 // At this point we have a valid stack boundary for this isolate and 1233 // At this point we have a valid stack boundary for this isolate and
1165 // know that our initial stack and frame pointers are within the boundary. 1234 // know that our initial stack and frame pointers are within the boundary.
1166 SampleBuffer* sample_buffer = Profiler::sample_buffer(); 1235 SampleBuffer* sample_buffer = Profiler::sample_buffer();
1167 if (sample_buffer == NULL) { 1236 if (sample_buffer == NULL) {
1168 // Profiler not initialized. 1237 // Profiler not initialized.
1169 return; 1238 return;
1170 } 1239 }
1171 1240
1172 // Setup sample. 1241 // Setup sample.
1173 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id()); 1242 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id());
1174 // Increment counter for vm tag. 1243 // Increment counter for vm tag.
1175 VMTagCounters* counters = isolate->vm_tag_counters(); 1244 VMTagCounters* counters = isolate->vm_tag_counters();
1176 ASSERT(counters != NULL); 1245 ASSERT(counters != NULL);
1177 if (thread->IsMutatorThread()) { 1246 if (thread->IsMutatorThread()) {
1178 counters->Increment(sample->vm_tag()); 1247 counters->Increment(sample->vm_tag());
1179 } 1248 }
1180 1249
1181 ProfilerNativeStackWalker native_stack_walker( 1250 ProfilerNativeStackWalker native_stack_walker(
1182 isolate, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp); 1251 (isolate != NULL) ? isolate->main_port() : ILLEGAL_PORT, sample,
1252 sample_buffer, stack_lower, stack_upper, pc, fp, sp);
1183 const bool exited_dart_code = thread->HasExitedDartCode(); 1253 const bool exited_dart_code = thread->HasExitedDartCode();
1184 ProfilerDartStackWalker dart_stack_walker(thread, sample, sample_buffer, 1254 ProfilerDartStackWalker dart_stack_walker(thread, sample, sample_buffer,
1185 stack_lower, stack_upper, pc, fp, 1255 stack_lower, stack_upper, pc, fp,
1186 sp, exited_dart_code, false); 1256 sp, exited_dart_code, false);
1187 1257
1188 // All memory access is done inside CollectSample. 1258 // All memory access is done inside CollectSample.
1189 CollectSample(isolate, exited_dart_code, in_dart_code, sample, 1259 CollectSample(isolate, exited_dart_code, in_dart_code, sample,
1190 &native_stack_walker, &dart_stack_walker, pc, fp, sp, 1260 &native_stack_walker, &dart_stack_walker, pc, fp, sp,
1191 &counters_); 1261 &counters_);
1192 } 1262 }
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
1332 for (intptr_t i = 0; i < length; i++) { 1402 for (intptr_t i = 0; i < length; i++) {
1333 Sample* sample = At(i); 1403 Sample* sample = At(i);
1334 if (sample->ignore_sample()) { 1404 if (sample->ignore_sample()) {
1335 // Bad sample. 1405 // Bad sample.
1336 continue; 1406 continue;
1337 } 1407 }
1338 if (!sample->head_sample()) { 1408 if (!sample->head_sample()) {
1339 // An inner sample in a chain of samples. 1409 // An inner sample in a chain of samples.
1340 continue; 1410 continue;
1341 } 1411 }
1342 if (sample->isolate() != filter->isolate()) { 1412 // If we're requesting all the native allocation samples, we don't care
1413 // whether or not we're in the same isolate as the sample.
1414 if (sample->port() != filter->port() &&
Cutch 2017/02/15 08:21:00 wrap in parens: (sample->port() != filter->port())
bkonyi 2017/02/16 00:28:29 Done.
1415 !sample->is_native_allocation_sample()) {
1343 // Another isolate. 1416 // Another isolate.
1344 continue; 1417 continue;
1345 } 1418 }
1346 if (sample->timestamp() == 0) { 1419 if (sample->timestamp() == 0) {
1347 // Empty. 1420 // Empty.
1348 continue; 1421 continue;
1349 } 1422 }
1350 if (sample->At(0) == 0) { 1423 if (sample->At(0) == 0) {
1351 // No frames. 1424 // No frames.
1352 continue; 1425 continue;
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1411 return processed_sample; 1484 return processed_sample;
1412 } 1485 }
1413 1486
1414 1487
1415 Sample* SampleBuffer::Next(Sample* sample) { 1488 Sample* SampleBuffer::Next(Sample* sample) {
1416 if (!sample->is_continuation_sample()) return NULL; 1489 if (!sample->is_continuation_sample()) return NULL;
1417 Sample* next_sample = At(sample->continuation_index()); 1490 Sample* next_sample = At(sample->continuation_index());
1418 // Sanity check. 1491 // Sanity check.
1419 ASSERT(sample != next_sample); 1492 ASSERT(sample != next_sample);
1420 // Detect invalid chaining. 1493 // Detect invalid chaining.
1421 if (sample->isolate() != next_sample->isolate()) { 1494 if (sample->port() != next_sample->port()) {
1422 return NULL; 1495 return NULL;
1423 } 1496 }
1424 if (sample->timestamp() != next_sample->timestamp()) { 1497 if (sample->timestamp() != next_sample->timestamp()) {
1425 return NULL; 1498 return NULL;
1426 } 1499 }
1427 if (sample->tid() != next_sample->tid()) { 1500 if (sample->tid() != next_sample->tid()) {
1428 return NULL; 1501 return NULL;
1429 } 1502 }
1430 return next_sample; 1503 return next_sample;
1431 } 1504 }
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
1513 1586
1514 1587
1515 ProcessedSampleBuffer::ProcessedSampleBuffer() 1588 ProcessedSampleBuffer::ProcessedSampleBuffer()
1516 : code_lookup_table_(new CodeLookupTable(Thread::Current())) { 1589 : code_lookup_table_(new CodeLookupTable(Thread::Current())) {
1517 ASSERT(code_lookup_table_ != NULL); 1590 ASSERT(code_lookup_table_ != NULL);
1518 } 1591 }
1519 1592
1520 #endif // !PRODUCT 1593 #endif // !PRODUCT
1521 1594
1522 } // namespace dart 1595 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698