Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "platform/address_sanitizer.h" | 5 #include "platform/address_sanitizer.h" |
| 6 #include "platform/memory_sanitizer.h" | 6 #include "platform/memory_sanitizer.h" |
| 7 #include "platform/utils.h" | 7 #include "platform/utils.h" |
| 8 | 8 |
| 9 #include "vm/allocation.h" | 9 #include "vm/allocation.h" |
| 10 #include "vm/atomic.h" | 10 #include "vm/atomic.h" |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 161 | 161 |
| 162 Sample* SampleBuffer::ReserveSample() { | 162 Sample* SampleBuffer::ReserveSample() { |
| 163 return At(ReserveSampleSlot()); | 163 return At(ReserveSampleSlot()); |
| 164 } | 164 } |
| 165 | 165 |
| 166 | 166 |
| 167 Sample* SampleBuffer::ReserveSampleAndLink(Sample* previous) { | 167 Sample* SampleBuffer::ReserveSampleAndLink(Sample* previous) { |
| 168 ASSERT(previous != NULL); | 168 ASSERT(previous != NULL); |
| 169 intptr_t next_index = ReserveSampleSlot(); | 169 intptr_t next_index = ReserveSampleSlot(); |
| 170 Sample* next = At(next_index); | 170 Sample* next = At(next_index); |
| 171 next->Init(previous->isolate(), previous->timestamp(), previous->tid()); | 171 next->Init(previous->port(), previous->timestamp(), previous->tid()); |
| 172 next->set_head_sample(false); | 172 next->set_head_sample(false); |
| 173 // Mark that previous continues at next. | 173 // Mark that previous continues at next. |
| 174 previous->SetContinuationIndex(next_index); | 174 previous->SetContinuationIndex(next_index); |
| 175 return next; | 175 return next; |
| 176 } | 176 } |
| 177 | 177 |
| 178 | 178 |
| 179 // Attempts to find the true return address when a Dart frame is being setup | 179 // Attempts to find the true return address when a Dart frame is being setup |
| 180 // or torn down. | 180 // or torn down. |
| 181 // NOTE: Architecture specific implementations below. | 181 // NOTE: Architecture specific implementations below. |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 314 } | 314 } |
| 315 | 315 |
| 316 | 316 |
| 317 bool SampleFilter::TaskFilterSample(Sample* sample) { | 317 bool SampleFilter::TaskFilterSample(Sample* sample) { |
| 318 const intptr_t task = static_cast<intptr_t>(sample->thread_task()); | 318 const intptr_t task = static_cast<intptr_t>(sample->thread_task()); |
| 319 return (task & thread_task_mask_) != 0; | 319 return (task & thread_task_mask_) != 0; |
| 320 } | 320 } |
| 321 | 321 |
| 322 | 322 |
| 323 ClearProfileVisitor::ClearProfileVisitor(Isolate* isolate) | 323 ClearProfileVisitor::ClearProfileVisitor(Isolate* isolate) |
| 324 : SampleVisitor(isolate) {} | 324 : SampleVisitor(isolate->main_port()) {} |
| 325 | 325 |
| 326 | 326 |
| 327 void ClearProfileVisitor::VisitSample(Sample* sample) { | 327 void ClearProfileVisitor::VisitSample(Sample* sample) { |
| 328 sample->Clear(); | 328 sample->Clear(); |
| 329 } | 329 } |
| 330 | 330 |
| 331 | 331 |
| 332 static void DumpStackFrame(intptr_t frame_index, uword pc) { | 332 static void DumpStackFrame(intptr_t frame_index, uword pc) { |
| 333 Isolate* isolate = Isolate::Current(); | 333 Isolate* isolate = Isolate::Current(); |
| 334 if ((isolate != NULL) && isolate->is_runnable()) { | 334 if ((isolate != NULL) && isolate->is_runnable()) { |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 350 OS::PrintErr(" [0x%" Pp "] Unknown symbol\n", pc); | 350 OS::PrintErr(" [0x%" Pp "] Unknown symbol\n", pc); |
| 351 } else { | 351 } else { |
| 352 OS::PrintErr(" [0x%" Pp "] %s\n", pc, native_symbol_name); | 352 OS::PrintErr(" [0x%" Pp "] %s\n", pc, native_symbol_name); |
| 353 NativeSymbolResolver::FreeSymbolName(native_symbol_name); | 353 NativeSymbolResolver::FreeSymbolName(native_symbol_name); |
| 354 } | 354 } |
| 355 } | 355 } |
| 356 | 356 |
| 357 | 357 |
| 358 class ProfilerStackWalker : public ValueObject { | 358 class ProfilerStackWalker : public ValueObject { |
| 359 public: | 359 public: |
| 360 ProfilerStackWalker(Isolate* isolate, | 360 ProfilerStackWalker(Dart_Port port_id, |
| 361 Sample* head_sample, | 361 Sample* head_sample, |
| 362 SampleBuffer* sample_buffer) | 362 SampleBuffer* sample_buffer) |
| 363 : isolate_(isolate), | 363 : 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |