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

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

Issue 131853007: Add flag to control number of stack frames collected by profiler (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 11 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 | Annotate | Revision Log
« no previous file with comments | « runtime/vm/profiler.h ('k') | runtime/vm/profiler_test.cc » ('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/utils.h" 5 #include "platform/utils.h"
6 6
7 #include "vm/allocation.h" 7 #include "vm/allocation.h"
8 #include "vm/atomic.h" 8 #include "vm/atomic.h"
9 #include "vm/code_patcher.h" 9 #include "vm/code_patcher.h"
10 #include "vm/isolate.h" 10 #include "vm/isolate.h"
11 #include "vm/json_stream.h" 11 #include "vm/json_stream.h"
12 #include "vm/native_symbol.h" 12 #include "vm/native_symbol.h"
13 #include "vm/object.h" 13 #include "vm/object.h"
14 #include "vm/os.h" 14 #include "vm/os.h"
15 #include "vm/profiler.h" 15 #include "vm/profiler.h"
16 #include "vm/signal_handler.h" 16 #include "vm/signal_handler.h"
17 #include "vm/simulator.h" 17 #include "vm/simulator.h"
18 18
19 namespace dart { 19 namespace dart {
20 20
21 21
22 // Notes on stack frame walking:
23 //
24 // The sampling profiler will collect up to Sample::kNumStackFrames stack frames
25 // The stack frame walking code uses the frame pointer to traverse the stack.
26 // If the VM is compiled without frame pointers (which is the default on
27 // recent GCC versions with optimizing enabled) the stack walking code may
28 // fail (sometimes leading to a crash).
29 //
30
31 #if defined(USING_SIMULATOR) || defined(TARGET_OS_WINDOWS) || \ 22 #if defined(USING_SIMULATOR) || defined(TARGET_OS_WINDOWS) || \
32 defined(TARGET_OS_MACOS) || defined(TARGET_OS_ANDROID) 23 defined(TARGET_OS_MACOS) || defined(TARGET_OS_ANDROID)
33 DEFINE_FLAG(bool, profile, false, "Enable Sampling Profiler"); 24 DEFINE_FLAG(bool, profile, false, "Enable Sampling Profiler");
34 #else 25 #else
35 DEFINE_FLAG(bool, profile, true, "Enable Sampling Profiler"); 26 DEFINE_FLAG(bool, profile, true, "Enable Sampling Profiler");
36 #endif 27 #endif
37 DEFINE_FLAG(bool, trace_profiled_isolates, false, "Trace profiled isolates."); 28 DEFINE_FLAG(bool, trace_profiled_isolates, false, "Trace profiled isolates.");
38 DEFINE_FLAG(charp, profile_dir, NULL, 29 DEFINE_FLAG(charp, profile_dir, NULL,
39 "Enable writing profile data into specified directory."); 30 "Enable writing profile data into specified directory.");
40 DEFINE_FLAG(int, profile_period, 1000, 31 DEFINE_FLAG(int, profile_period, 1000,
41 "Time between profiler samples in microseconds. Minimum 250."); 32 "Time between profiler samples in microseconds. Minimum 250.");
33 DEFINE_FLAG(int, profile_depth, 8,
34 "Maximum number stack frames walked. Minimum 1. Maximum 128.");
42 35
43 bool Profiler::initialized_ = false; 36 bool Profiler::initialized_ = false;
44 Monitor* Profiler::monitor_ = NULL;
45 SampleBuffer* Profiler::sample_buffer_ = NULL; 37 SampleBuffer* Profiler::sample_buffer_ = NULL;
46 38
47 void Profiler::InitOnce() { 39 void Profiler::InitOnce() {
48 const int kMinimumProfilePeriod = 250; 40 const int kMinimumProfilePeriod = 250;
41 const int kMinimumDepth = 1;
42 const int kMaximumDepth = 128;
49 if (!FLAG_profile) { 43 if (!FLAG_profile) {
50 return; 44 return;
51 } 45 }
52 ASSERT(!initialized_); 46 ASSERT(!initialized_);
53 initialized_ = true; 47 // Place some sane restrictions on user controlled flags.
54 monitor_ = new Monitor(); 48 if (FLAG_profile_period < kMinimumProfilePeriod) {
49 FLAG_profile_period = kMinimumProfilePeriod;
50 }
51 if (FLAG_profile_depth < kMinimumDepth) {
52 FLAG_profile_depth = kMinimumDepth;
53 } else if (FLAG_profile_depth > kMaximumDepth) {
54 FLAG_profile_depth = kMaximumDepth;
55 }
56 Sample::InitOnce();
55 sample_buffer_ = new SampleBuffer(); 57 sample_buffer_ = new SampleBuffer();
56 NativeSymbolResolver::InitOnce(); 58 NativeSymbolResolver::InitOnce();
57 ThreadInterrupter::InitOnce(); 59 ThreadInterrupter::InitOnce();
58 if (FLAG_profile_period < kMinimumProfilePeriod) {
59 FLAG_profile_period = kMinimumProfilePeriod;
60 }
61 ThreadInterrupter::SetInterruptPeriod(FLAG_profile_period); 60 ThreadInterrupter::SetInterruptPeriod(FLAG_profile_period);
61 initialized_ = true;
62 } 62 }
63 63
64 64
65 void Profiler::Shutdown() { 65 void Profiler::Shutdown() {
66 if (!FLAG_profile) { 66 if (!FLAG_profile) {
67 return; 67 return;
68 } 68 }
69 ASSERT(initialized_); 69 ASSERT(initialized_);
70 ThreadInterrupter::Shutdown(); 70 ThreadInterrupter::Shutdown();
71 NativeSymbolResolver::ShutdownOnce(); 71 NativeSymbolResolver::ShutdownOnce();
72 } 72 }
73 73
74 74
75 void Profiler::InitProfilingForIsolate(Isolate* isolate, bool shared_buffer) { 75 void Profiler::InitProfilingForIsolate(Isolate* isolate, bool shared_buffer) {
76 if (!FLAG_profile) { 76 if (!FLAG_profile) {
77 return; 77 return;
78 } 78 }
79 ASSERT(isolate != NULL); 79 ASSERT(isolate != NULL);
80 ASSERT(sample_buffer_ != NULL); 80 ASSERT(sample_buffer_ != NULL);
81 MonitorLocker ml(monitor_);
82 { 81 {
83 MutexLocker profiler_data_lock(isolate->profiler_data_mutex()); 82 MutexLocker profiler_data_lock(isolate->profiler_data_mutex());
84 SampleBuffer* sample_buffer = sample_buffer_; 83 SampleBuffer* sample_buffer = sample_buffer_;
85 if (!shared_buffer) { 84 if (!shared_buffer) {
86 sample_buffer = new SampleBuffer(); 85 sample_buffer = new SampleBuffer();
87 } 86 }
88 IsolateProfilerData* profiler_data = 87 IsolateProfilerData* profiler_data =
89 new IsolateProfilerData(sample_buffer, !shared_buffer); 88 new IsolateProfilerData(sample_buffer, !shared_buffer);
90 ASSERT(profiler_data != NULL); 89 ASSERT(profiler_data != NULL);
91 isolate->set_profiler_data(profiler_data); 90 isolate->set_profiler_data(profiler_data);
92 if (FLAG_trace_profiled_isolates) { 91 if (FLAG_trace_profiled_isolates) {
93 OS::Print("Profiler Setup %p %s\n", isolate, isolate->name()); 92 OS::Print("Profiler Setup %p %s\n", isolate, isolate->name());
94 } 93 }
95 } 94 }
96 } 95 }
97 96
98 97
99 void Profiler::ShutdownProfilingForIsolate(Isolate* isolate) { 98 void Profiler::ShutdownProfilingForIsolate(Isolate* isolate) {
100 ASSERT(isolate != NULL); 99 ASSERT(isolate != NULL);
101 if (!FLAG_profile) { 100 if (!FLAG_profile) {
102 return; 101 return;
103 } 102 }
104 // We do not have a current isolate. 103 // We do not have a current isolate.
105 ASSERT(Isolate::Current() == NULL); 104 ASSERT(Isolate::Current() == NULL);
106 MonitorLocker ml(monitor_);
107 { 105 {
108 MutexLocker profiler_data_lock(isolate->profiler_data_mutex()); 106 MutexLocker profiler_data_lock(isolate->profiler_data_mutex());
109 IsolateProfilerData* profiler_data = isolate->profiler_data(); 107 IsolateProfilerData* profiler_data = isolate->profiler_data();
110 if (profiler_data == NULL) { 108 if (profiler_data == NULL) {
111 // Already freed. 109 // Already freed.
112 return; 110 return;
113 } 111 }
114 isolate->set_profiler_data(NULL); 112 isolate->set_profiler_data(NULL);
115 delete profiler_data; 113 delete profiler_data;
116 if (FLAG_trace_profiled_isolates) { 114 if (FLAG_trace_profiled_isolates) {
(...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after
533 // Enable profile interrupts. 531 // Enable profile interrupts.
534 BeginExecution(isolate); 532 BeginExecution(isolate);
535 } 533 }
536 534
537 535
538 intptr_t Profiler::ProcessSamples(Isolate* isolate, 536 intptr_t Profiler::ProcessSamples(Isolate* isolate,
539 ProfilerCodeRegionTable* code_region_table, 537 ProfilerCodeRegionTable* code_region_table,
540 SampleBuffer* sample_buffer) { 538 SampleBuffer* sample_buffer) {
541 int64_t start = OS::GetCurrentTimeMillis(); 539 int64_t start = OS::GetCurrentTimeMillis();
542 intptr_t samples = 0; 540 intptr_t samples = 0;
541 Sample* sample = Sample::Allocate();
543 for (intptr_t i = 0; i < sample_buffer->capacity(); i++) { 542 for (intptr_t i = 0; i < sample_buffer->capacity(); i++) {
544 Sample sample = sample_buffer->GetSample(i); 543 sample_buffer->CopySample(i, sample);
545 if (sample.isolate != isolate) { 544 if (sample->isolate() != isolate) {
546 continue; 545 continue;
547 } 546 }
548 if (sample.timestamp == 0) { 547 if (sample->timestamp() == 0) {
549 continue; 548 continue;
550 } 549 }
551 samples += ProcessSample(isolate, code_region_table, &sample); 550 samples += ProcessSample(isolate, code_region_table, sample);
552 } 551 }
552 free(sample);
553 int64_t end = OS::GetCurrentTimeMillis(); 553 int64_t end = OS::GetCurrentTimeMillis();
554 if (FLAG_trace_profiled_isolates) { 554 if (FLAG_trace_profiled_isolates) {
555 int64_t delta = end - start; 555 int64_t delta = end - start;
556 OS::Print("Processed %" Pd " samples from %s in %" Pd64 " milliseconds.\n", 556 OS::Print("Processed %" Pd " samples from %s in %" Pd64 " milliseconds.\n",
557 samples, 557 samples,
558 isolate->name(), 558 isolate->name(),
559 delta); 559 delta);
560 } 560 }
561 return samples; 561 return samples;
562 } 562 }
563 563
564 564
565 intptr_t Profiler::ProcessSample(Isolate* isolate, 565 intptr_t Profiler::ProcessSample(Isolate* isolate,
566 ProfilerCodeRegionTable* code_region_table, 566 ProfilerCodeRegionTable* code_region_table,
567 Sample* sample) { 567 Sample* sample) {
568 Sample::SampleType type = sample->type; 568 if (sample->type() != Sample::kIsolateSample) {
569 if (type != Sample::kIsolateSample) {
570 return 0; 569 return 0;
571 } 570 }
572 if (sample->pcs[0] == 0) { 571 if (sample->At(0) == 0) {
573 // No frames in this sample. 572 // No frames in this sample.
574 return 0; 573 return 0;
575 } 574 }
576 intptr_t i = 0;
577 // i points to the leaf (exclusive) PC sample. Do not tick the address. 575 // i points to the leaf (exclusive) PC sample. Do not tick the address.
578 code_region_table->AddTick(sample->pcs[i], true, false); 576 code_region_table->AddTick(sample->At(0), true, false);
579 // Give all frames an inclusive tick and tick the address. 577 // Give all frames an inclusive tick and tick the address.
580 for (; i < Sample::kNumStackFrames; i++) { 578 for (intptr_t i = 0; i < FLAG_profile_depth; i++) {
581 if (sample->pcs[i] == 0) { 579 if (sample->At(i) == 0) {
582 break; 580 break;
583 } 581 }
584 code_region_table->AddTick(sample->pcs[i], false, true); 582 code_region_table->AddTick(sample->At(i), false, true);
585 } 583 }
586 return 1; 584 return 1;
587 } 585 }
588 586
589 587
590 void Profiler::WriteProfile(Isolate* isolate) { 588 void Profiler::WriteProfile(Isolate* isolate) {
591 if (isolate == NULL) { 589 if (isolate == NULL) {
592 return; 590 return;
593 } 591 }
594 if (!FLAG_profile) { 592 if (!FLAG_profile) {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
638 636
639 IsolateProfilerData::~IsolateProfilerData() { 637 IsolateProfilerData::~IsolateProfilerData() {
640 if (own_sample_buffer_) { 638 if (own_sample_buffer_) {
641 delete sample_buffer_; 639 delete sample_buffer_;
642 sample_buffer_ = NULL; 640 sample_buffer_ = NULL;
643 own_sample_buffer_ = false; 641 own_sample_buffer_ = false;
644 } 642 }
645 } 643 }
646 644
647 645
646 intptr_t Sample::instance_size_ = 0;
647
648 void Sample::InitOnce() {
649 ASSERT(FLAG_profile_depth >= 1);
650 instance_size_ =
651 sizeof(Sample) + (sizeof(intptr_t) * FLAG_profile_depth); // NOLINT.
652 }
653
654
655 uintptr_t Sample::At(intptr_t i) const {
656 ASSERT(i >= 0);
657 ASSERT(i < FLAG_profile_depth);
658 return pcs_[i];
659 }
660
661
662 void Sample::SetAt(intptr_t i, uintptr_t pc) {
663 ASSERT(i >= 0);
664 ASSERT(i < FLAG_profile_depth);
665 pcs_[i] = pc;
666 }
667
668
648 void Sample::Init(SampleType type, Isolate* isolate, int64_t timestamp, 669 void Sample::Init(SampleType type, Isolate* isolate, int64_t timestamp,
649 ThreadId tid) { 670 ThreadId tid) {
650 this->timestamp = timestamp; 671 timestamp_ = timestamp;
651 this->tid = tid; 672 tid_ = tid;
652 this->isolate = isolate; 673 isolate_ = isolate;
653 for (intptr_t i = 0; i < kNumStackFrames; i++) { 674 type_ = type;
654 pcs[i] = 0; 675 for (int i = 0; i < FLAG_profile_depth; i++) {
676 pcs_[i] = 0;
655 } 677 }
656 this->type = type;
657 vm_tags = 0;
658 runtime_tags = 0;
659 } 678 }
660 679
680
681 void Sample::CopyInto(Sample* dst) const {
682 ASSERT(dst != NULL);
683 dst->timestamp_ = timestamp_;
684 dst->tid_ = tid_;
685 dst->isolate_ = isolate_;
686 dst->type_ = type_;
687 for (intptr_t i = 0; i < FLAG_profile_depth; i++) {
688 dst->pcs_[i] = pcs_[i];
689 }
690 }
691
692
693 Sample* Sample::Allocate() {
694 return reinterpret_cast<Sample*>(malloc(instance_size()));
695 }
696
697
661 SampleBuffer::SampleBuffer(intptr_t capacity) { 698 SampleBuffer::SampleBuffer(intptr_t capacity) {
662 capacity_ = capacity; 699 capacity_ = capacity;
663 samples_ = reinterpret_cast<Sample*>(calloc(capacity, sizeof(Sample))); 700 samples_ = reinterpret_cast<Sample*>(
701 calloc(capacity, Sample::instance_size()));
664 cursor_ = 0; 702 cursor_ = 0;
665 } 703 }
666 704
667 705
668 SampleBuffer::~SampleBuffer() { 706 SampleBuffer::~SampleBuffer() {
669 if (samples_ != NULL) { 707 if (samples_ != NULL) {
670 free(samples_); 708 free(samples_);
671 samples_ = NULL; 709 samples_ = NULL;
672 cursor_ = 0; 710 cursor_ = 0;
673 capacity_ = 0; 711 capacity_ = 0;
674 } 712 }
675 } 713 }
676 714
677 715
678 Sample* SampleBuffer::ReserveSample() { 716 Sample* SampleBuffer::ReserveSample() {
679 ASSERT(samples_ != NULL); 717 ASSERT(samples_ != NULL);
680 uintptr_t cursor = AtomicOperations::FetchAndIncrement(&cursor_); 718 uintptr_t cursor = AtomicOperations::FetchAndIncrement(&cursor_);
681 // Map back into sample buffer range. 719 // Map back into sample buffer range.
682 cursor = cursor % capacity_; 720 cursor = cursor % capacity_;
683 return &samples_[cursor]; 721 return At(cursor);
684 } 722 }
685 723
686 724
725 void SampleBuffer::CopySample(intptr_t i, Sample* sample) const {
726 At(i)->CopyInto(sample);
727 }
728
729
730 Sample* SampleBuffer::At(intptr_t idx) const {
731 ASSERT(idx >= 0);
732 ASSERT(idx < capacity_);
733 intptr_t offset = idx * Sample::instance_size();
734 uint8_t* samples = reinterpret_cast<uint8_t*>(samples_);
735 return reinterpret_cast<Sample*>(samples + offset);
736 }
737
738
687 ProfilerSampleStackWalker::ProfilerSampleStackWalker(Sample* sample, 739 ProfilerSampleStackWalker::ProfilerSampleStackWalker(Sample* sample,
688 uintptr_t stack_lower, 740 uintptr_t stack_lower,
689 uintptr_t stack_upper, 741 uintptr_t stack_upper,
690 uintptr_t pc, 742 uintptr_t pc,
691 uintptr_t fp, 743 uintptr_t fp,
692 uintptr_t sp) : 744 uintptr_t sp) :
693 sample_(sample), 745 sample_(sample),
694 stack_lower_(stack_lower), 746 stack_lower_(stack_lower),
695 stack_upper_(stack_upper), 747 stack_upper_(stack_upper),
696 original_pc_(pc), 748 original_pc_(pc),
697 original_fp_(fp), 749 original_fp_(fp),
698 original_sp_(sp), 750 original_sp_(sp),
699 lower_bound_(stack_lower) { 751 lower_bound_(stack_lower) {
700 ASSERT(sample_ != NULL); 752 ASSERT(sample_ != NULL);
701 // Zero out the PCs before (re)using the sample.
702 for (int i = 0; i < Sample::kNumStackFrames; i++) {
703 sample_->pcs[i] = 0;
704 }
705 } 753 }
706 754
707 755
756 // Notes on stack frame walking:
757 //
758 // The sampling profiler will collect up to Sample::kNumStackFrames stack frames
759 // The stack frame walking code uses the frame pointer to traverse the stack.
760 // If the VM is compiled without frame pointers (which is the default on
761 // recent GCC versions with optimizing enabled) the stack walking code may
762 // fail (sometimes leading to a crash).
763 //
764
708 int ProfilerSampleStackWalker::walk() { 765 int ProfilerSampleStackWalker::walk() {
709 const intptr_t kMaxStep = 0x1000; // 4K. 766 const intptr_t kMaxStep = 0x1000; // 4K.
767 const bool kWalkStack = true; // Walk the stack.
768 // Always store the exclusive PC.
769 sample_->SetAt(0, original_pc_);
770 if (!kWalkStack) {
771 // Not walking the stack, only took exclusive sample.
772 return 1;
773 }
710 uword* pc = reinterpret_cast<uword*>(original_pc_); 774 uword* pc = reinterpret_cast<uword*>(original_pc_);
711 // Always store the exclusive PC.
712 sample_->pcs[0] = original_pc_;
713 #define WALK_STACK
714 #if defined(WALK_STACK)
715 uword* fp = reinterpret_cast<uword*>(original_fp_); 775 uword* fp = reinterpret_cast<uword*>(original_fp_);
716 uword* previous_fp = fp; 776 uword* previous_fp = fp;
717 if (original_sp_ > original_fp_) { 777 if (original_sp_ > original_fp_) {
718 // Stack pointer should not be above frame pointer. 778 // Stack pointer should not be above frame pointer.
719 return 1; 779 return 1;
720 } 780 }
721 intptr_t gap = original_fp_ - original_sp_; 781 intptr_t gap = original_fp_ - original_sp_;
722 if (gap >= kMaxStep) { 782 if (gap >= kMaxStep) {
723 // Gap between frame pointer and stack pointer is 783 // Gap between frame pointer and stack pointer is
724 // too large. 784 // too large.
725 return 1; 785 return 1;
726 } 786 }
727 if (original_sp_ < lower_bound_) { 787 if (original_sp_ < lower_bound_) {
728 // The stack pointer gives us a better lower bound than 788 // The stack pointer gives us a better lower bound than
729 // the isolates stack limit. 789 // the isolates stack limit.
730 lower_bound_ = original_sp_; 790 lower_bound_ = original_sp_;
731 } 791 }
732 int i = 0; 792 int i = 0;
733 for (; i < Sample::kNumStackFrames; i++) { 793 for (; i < FLAG_profile_depth; i++) {
734 sample_->pcs[i] = reinterpret_cast<uintptr_t>(pc); 794 sample_->SetAt(i, reinterpret_cast<uintptr_t>(pc));
735 if (!ValidFramePointer(fp)) { 795 if (!ValidFramePointer(fp)) {
736 return i + 1; 796 return i + 1;
737 } 797 }
738 pc = CallerPC(fp); 798 pc = CallerPC(fp);
739 previous_fp = fp; 799 previous_fp = fp;
740 fp = CallerFP(fp); 800 fp = CallerFP(fp);
741 intptr_t step = fp - previous_fp; 801 intptr_t step = fp - previous_fp;
742 if ((step >= kMaxStep) || (fp <= previous_fp) || !ValidFramePointer(fp)) { 802 if ((step >= kMaxStep) || (fp <= previous_fp) || !ValidFramePointer(fp)) {
743 // Frame pointer step is too large. 803 // Frame pointer step is too large.
744 // Frame pointer did not move to a higher address. 804 // Frame pointer did not move to a higher address.
745 // Frame pointer is outside of isolate stack bounds. 805 // Frame pointer is outside of isolate stack bounds.
746 return i + 1; 806 return i + 1;
747 } 807 }
748 // Move the lower bound up. 808 // Move the lower bound up.
749 lower_bound_ = reinterpret_cast<uintptr_t>(fp); 809 lower_bound_ = reinterpret_cast<uintptr_t>(fp);
750 } 810 }
751 return i; 811 return i;
752 #else
753 sample_->pcs[0] = reinterpret_cast<uintptr_t>(pc);
754 return 0;
755 #endif
756 } 812 }
757 813
758 814
759 uword* ProfilerSampleStackWalker::CallerPC(uword* fp) { 815 uword* ProfilerSampleStackWalker::CallerPC(uword* fp) {
760 ASSERT(fp != NULL); 816 ASSERT(fp != NULL);
761 return reinterpret_cast<uword*>(*(fp + 1)); 817 return reinterpret_cast<uword*>(*(fp + 1));
762 } 818 }
763 819
764 820
765 uword* ProfilerSampleStackWalker::CallerFP(uword* fp) { 821 uword* ProfilerSampleStackWalker::CallerFP(uword* fp) {
766 ASSERT(fp != NULL); 822 ASSERT(fp != NULL);
767 return reinterpret_cast<uword*>(*fp); 823 return reinterpret_cast<uword*>(*fp);
768 } 824 }
769 825
770 826
771 bool ProfilerSampleStackWalker::ValidFramePointer(uword* fp) { 827 bool ProfilerSampleStackWalker::ValidFramePointer(uword* fp) {
772 if (fp == NULL) { 828 if (fp == NULL) {
773 return false; 829 return false;
774 } 830 }
775 uintptr_t cursor = reinterpret_cast<uintptr_t>(fp); 831 uintptr_t cursor = reinterpret_cast<uintptr_t>(fp);
776 cursor += sizeof(fp); 832 cursor += sizeof(fp);
777 bool r = cursor >= lower_bound_ && cursor < stack_upper_; 833 bool r = cursor >= lower_bound_ && cursor < stack_upper_;
778 return r; 834 return r;
779 } 835 }
780 836
781 837
782 } // namespace dart 838 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/profiler.h ('k') | runtime/vm/profiler_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698