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/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_frames, 8, | |
| 34 "Maximum number stack frames walked. Minimum 1."); | |
|
siva
2014/01/16 23:34:23
maybe profile_frames_depth
Cutch
2014/01/17 16:02:25
profile_depth.
| |
| 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 kMinimumFrames = 1; | |
|
siva
2014/01/16 23:34:23
We probably also want a max (not letting people ar
Cutch
2014/01/17 16:02:25
Max of 128.
| |
| 49 if (!FLAG_profile) { | 42 if (!FLAG_profile) { |
| 50 return; | 43 return; |
| 51 } | 44 } |
| 52 ASSERT(!initialized_); | 45 ASSERT(!initialized_); |
| 53 initialized_ = true; | 46 if (FLAG_profile_period < kMinimumProfilePeriod) { |
| 54 monitor_ = new Monitor(); | 47 FLAG_profile_period = kMinimumProfilePeriod; |
| 48 } | |
| 49 if (FLAG_profile_frames < kMinimumFrames) { | |
| 50 FLAG_profile_frames = kMinimumFrames; | |
| 51 } | |
| 55 sample_buffer_ = new SampleBuffer(); | 52 sample_buffer_ = new SampleBuffer(); |
| 56 NativeSymbolResolver::InitOnce(); | 53 NativeSymbolResolver::InitOnce(); |
| 57 ThreadInterrupter::InitOnce(); | 54 ThreadInterrupter::InitOnce(); |
| 58 if (FLAG_profile_period < kMinimumProfilePeriod) { | |
| 59 FLAG_profile_period = kMinimumProfilePeriod; | |
| 60 } | |
| 61 ThreadInterrupter::SetInterruptPeriod(FLAG_profile_period); | 55 ThreadInterrupter::SetInterruptPeriod(FLAG_profile_period); |
| 56 initialized_ = true; | |
| 62 } | 57 } |
| 63 | 58 |
| 64 | 59 |
| 65 void Profiler::Shutdown() { | 60 void Profiler::Shutdown() { |
| 66 if (!FLAG_profile) { | 61 if (!FLAG_profile) { |
| 67 return; | 62 return; |
| 68 } | 63 } |
| 69 ASSERT(initialized_); | 64 ASSERT(initialized_); |
| 70 ThreadInterrupter::Shutdown(); | 65 ThreadInterrupter::Shutdown(); |
| 71 NativeSymbolResolver::ShutdownOnce(); | 66 NativeSymbolResolver::ShutdownOnce(); |
| 72 } | 67 } |
| 73 | 68 |
| 74 | 69 |
| 75 void Profiler::InitProfilingForIsolate(Isolate* isolate, bool shared_buffer) { | 70 void Profiler::InitProfilingForIsolate(Isolate* isolate, bool shared_buffer) { |
| 76 if (!FLAG_profile) { | 71 if (!FLAG_profile) { |
| 77 return; | 72 return; |
| 78 } | 73 } |
| 79 ASSERT(isolate != NULL); | 74 ASSERT(isolate != NULL); |
| 80 ASSERT(sample_buffer_ != NULL); | 75 ASSERT(sample_buffer_ != NULL); |
| 81 MonitorLocker ml(monitor_); | |
| 82 { | 76 { |
| 83 MutexLocker profiler_data_lock(isolate->profiler_data_mutex()); | 77 MutexLocker profiler_data_lock(isolate->profiler_data_mutex()); |
| 84 SampleBuffer* sample_buffer = sample_buffer_; | 78 SampleBuffer* sample_buffer = sample_buffer_; |
| 85 if (!shared_buffer) { | 79 if (!shared_buffer) { |
| 86 sample_buffer = new SampleBuffer(); | 80 sample_buffer = new SampleBuffer(); |
| 87 } | 81 } |
| 88 IsolateProfilerData* profiler_data = | 82 IsolateProfilerData* profiler_data = |
| 89 new IsolateProfilerData(sample_buffer, !shared_buffer); | 83 new IsolateProfilerData(sample_buffer, !shared_buffer); |
| 90 ASSERT(profiler_data != NULL); | 84 ASSERT(profiler_data != NULL); |
| 91 isolate->set_profiler_data(profiler_data); | 85 isolate->set_profiler_data(profiler_data); |
| 92 if (FLAG_trace_profiled_isolates) { | 86 if (FLAG_trace_profiled_isolates) { |
| 93 OS::Print("Profiler Setup %p %s\n", isolate, isolate->name()); | 87 OS::Print("Profiler Setup %p %s\n", isolate, isolate->name()); |
| 94 } | 88 } |
| 95 } | 89 } |
| 96 } | 90 } |
| 97 | 91 |
| 98 | 92 |
| 99 void Profiler::ShutdownProfilingForIsolate(Isolate* isolate) { | 93 void Profiler::ShutdownProfilingForIsolate(Isolate* isolate) { |
| 100 ASSERT(isolate != NULL); | 94 ASSERT(isolate != NULL); |
| 101 if (!FLAG_profile) { | 95 if (!FLAG_profile) { |
| 102 return; | 96 return; |
| 103 } | 97 } |
| 104 // We do not have a current isolate. | 98 // We do not have a current isolate. |
| 105 ASSERT(Isolate::Current() == NULL); | 99 ASSERT(Isolate::Current() == NULL); |
| 106 MonitorLocker ml(monitor_); | |
| 107 { | 100 { |
| 108 MutexLocker profiler_data_lock(isolate->profiler_data_mutex()); | 101 MutexLocker profiler_data_lock(isolate->profiler_data_mutex()); |
| 109 IsolateProfilerData* profiler_data = isolate->profiler_data(); | 102 IsolateProfilerData* profiler_data = isolate->profiler_data(); |
| 110 if (profiler_data == NULL) { | 103 if (profiler_data == NULL) { |
| 111 // Already freed. | 104 // Already freed. |
| 112 return; | 105 return; |
| 113 } | 106 } |
| 114 isolate->set_profiler_data(NULL); | 107 isolate->set_profiler_data(NULL); |
| 115 delete profiler_data; | 108 delete profiler_data; |
| 116 if (FLAG_trace_profiled_isolates) { | 109 if (FLAG_trace_profiled_isolates) { |
| (...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 533 // Enable profile interrupts. | 526 // Enable profile interrupts. |
| 534 BeginExecution(isolate); | 527 BeginExecution(isolate); |
| 535 } | 528 } |
| 536 | 529 |
| 537 | 530 |
| 538 intptr_t Profiler::ProcessSamples(Isolate* isolate, | 531 intptr_t Profiler::ProcessSamples(Isolate* isolate, |
| 539 ProfilerCodeRegionTable* code_region_table, | 532 ProfilerCodeRegionTable* code_region_table, |
| 540 SampleBuffer* sample_buffer) { | 533 SampleBuffer* sample_buffer) { |
| 541 int64_t start = OS::GetCurrentTimeMillis(); | 534 int64_t start = OS::GetCurrentTimeMillis(); |
| 542 intptr_t samples = 0; | 535 intptr_t samples = 0; |
| 536 Sample* sample = Sample::Allocate(); | |
| 543 for (intptr_t i = 0; i < sample_buffer->capacity(); i++) { | 537 for (intptr_t i = 0; i < sample_buffer->capacity(); i++) { |
| 544 Sample sample = sample_buffer->GetSample(i); | 538 sample_buffer->CopySample(i, sample); |
| 545 if (sample.isolate != isolate) { | 539 if (sample->isolate != isolate) { |
| 546 continue; | 540 continue; |
| 547 } | 541 } |
| 548 if (sample.timestamp == 0) { | 542 if (sample->timestamp == 0) { |
| 549 continue; | 543 continue; |
| 550 } | 544 } |
| 551 samples += ProcessSample(isolate, code_region_table, &sample); | 545 samples += ProcessSample(isolate, code_region_table, sample); |
| 552 } | 546 } |
| 547 free(sample); | |
| 553 int64_t end = OS::GetCurrentTimeMillis(); | 548 int64_t end = OS::GetCurrentTimeMillis(); |
| 554 if (FLAG_trace_profiled_isolates) { | 549 if (FLAG_trace_profiled_isolates) { |
| 555 int64_t delta = end - start; | 550 int64_t delta = end - start; |
| 556 OS::Print("Processed %" Pd " samples from %s in %" Pd64 " milliseconds.\n", | 551 OS::Print("Processed %" Pd " samples from %s in %" Pd64 " milliseconds.\n", |
| 557 samples, | 552 samples, |
| 558 isolate->name(), | 553 isolate->name(), |
| 559 delta); | 554 delta); |
| 560 } | 555 } |
| 561 return samples; | 556 return samples; |
| 562 } | 557 } |
| 563 | 558 |
| 564 | 559 |
| 565 intptr_t Profiler::ProcessSample(Isolate* isolate, | 560 intptr_t Profiler::ProcessSample(Isolate* isolate, |
| 566 ProfilerCodeRegionTable* code_region_table, | 561 ProfilerCodeRegionTable* code_region_table, |
| 567 Sample* sample) { | 562 Sample* sample) { |
| 568 Sample::SampleType type = sample->type; | 563 Sample::SampleType type = sample->type; |
| 569 if (type != Sample::kIsolateSample) { | 564 if (type != Sample::kIsolateSample) { |
| 570 return 0; | 565 return 0; |
| 571 } | 566 } |
| 572 if (sample->pcs[0] == 0) { | 567 if (sample->pcs[0] == 0) { |
| 573 // No frames in this sample. | 568 // No frames in this sample. |
| 574 return 0; | 569 return 0; |
| 575 } | 570 } |
| 576 intptr_t i = 0; | 571 intptr_t i = 0; |
| 577 // i points to the leaf (exclusive) PC sample. Do not tick the address. | 572 // i points to the leaf (exclusive) PC sample. Do not tick the address. |
| 578 code_region_table->AddTick(sample->pcs[i], true, false); | 573 code_region_table->AddTick(sample->pcs[i], true, false); |
| 579 // Give all frames an inclusive tick and tick the address. | 574 // Give all frames an inclusive tick and tick the address. |
| 580 for (; i < Sample::kNumStackFrames; i++) { | 575 for (; i < FLAG_profile_frames; i++) { |
| 581 if (sample->pcs[i] == 0) { | 576 if (sample->pcs[i] == 0) { |
| 582 break; | 577 break; |
| 583 } | 578 } |
| 584 code_region_table->AddTick(sample->pcs[i], false, true); | 579 code_region_table->AddTick(sample->pcs[i], false, true); |
| 585 } | 580 } |
| 586 return 1; | 581 return 1; |
| 587 } | 582 } |
| 588 | 583 |
| 589 | 584 |
| 590 void Profiler::WriteProfile(Isolate* isolate) { | 585 void Profiler::WriteProfile(Isolate* isolate) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 638 | 633 |
| 639 IsolateProfilerData::~IsolateProfilerData() { | 634 IsolateProfilerData::~IsolateProfilerData() { |
| 640 if (own_sample_buffer_) { | 635 if (own_sample_buffer_) { |
| 641 delete sample_buffer_; | 636 delete sample_buffer_; |
| 642 sample_buffer_ = NULL; | 637 sample_buffer_ = NULL; |
| 643 own_sample_buffer_ = false; | 638 own_sample_buffer_ = false; |
| 644 } | 639 } |
| 645 } | 640 } |
| 646 | 641 |
| 647 | 642 |
| 643 void Sample::CopyInto(Sample* dst) const { | |
| 644 ASSERT(dst != NULL); | |
| 645 dst->timestamp = timestamp; | |
| 646 dst->tid = tid; | |
| 647 dst->isolate = isolate; | |
| 648 dst->type = type; | |
| 649 dst->vm_tags = vm_tags; | |
| 650 dst->runtime_tags = runtime_tags; | |
| 651 for (intptr_t i = 0; i < FLAG_profile_frames; i++) { | |
| 652 dst->pcs[i] = pcs[i]; | |
| 653 } | |
| 654 } | |
| 655 | |
| 656 | |
| 657 Sample* Sample::Allocate() { | |
| 658 return reinterpret_cast<Sample*>(malloc(InstanceSize())); | |
| 659 } | |
| 660 | |
| 661 | |
| 662 intptr_t Sample::InstanceSize() { | |
| 663 ASSERT(FLAG_profile_frames >= 1); | |
| 664 return sizeof(Sample) + (sizeof(intptr_t) * FLAG_profile_frames); // NOLINT. | |
|
siva
2014/01/16 23:34:23
Why did you choose this to be a function instead o
Cutch
2014/01/17 16:02:25
Done.
| |
| 665 } | |
| 666 | |
| 667 | |
| 648 void Sample::Init(SampleType type, Isolate* isolate, int64_t timestamp, | 668 void Sample::Init(SampleType type, Isolate* isolate, int64_t timestamp, |
| 649 ThreadId tid) { | 669 ThreadId tid) { |
| 650 this->timestamp = timestamp; | 670 this->timestamp = timestamp; |
| 651 this->tid = tid; | 671 this->tid = tid; |
| 652 this->isolate = isolate; | 672 this->isolate = isolate; |
| 653 for (intptr_t i = 0; i < kNumStackFrames; i++) { | |
| 654 pcs[i] = 0; | |
| 655 } | |
| 656 this->type = type; | 673 this->type = type; |
| 657 vm_tags = 0; | 674 vm_tags = 0; |
| 658 runtime_tags = 0; | 675 runtime_tags = 0; |
| 676 for (int i = 0; i < FLAG_profile_frames; i++) { | |
| 677 pcs[i] = 0; | |
| 678 } | |
| 659 } | 679 } |
| 660 | 680 |
| 681 | |
| 661 SampleBuffer::SampleBuffer(intptr_t capacity) { | 682 SampleBuffer::SampleBuffer(intptr_t capacity) { |
| 662 capacity_ = capacity; | 683 capacity_ = capacity; |
| 663 samples_ = reinterpret_cast<Sample*>(calloc(capacity, sizeof(Sample))); | 684 samples_ = reinterpret_cast<Sample*>( |
| 685 calloc(capacity, Sample::InstanceSize())); | |
| 664 cursor_ = 0; | 686 cursor_ = 0; |
| 665 } | 687 } |
| 666 | 688 |
| 667 | 689 |
| 668 SampleBuffer::~SampleBuffer() { | 690 SampleBuffer::~SampleBuffer() { |
| 669 if (samples_ != NULL) { | 691 if (samples_ != NULL) { |
| 670 free(samples_); | 692 free(samples_); |
| 671 samples_ = NULL; | 693 samples_ = NULL; |
| 672 cursor_ = 0; | 694 cursor_ = 0; |
| 673 capacity_ = 0; | 695 capacity_ = 0; |
| 674 } | 696 } |
| 675 } | 697 } |
| 676 | 698 |
| 677 | 699 |
| 678 Sample* SampleBuffer::ReserveSample() { | 700 Sample* SampleBuffer::ReserveSample() { |
| 679 ASSERT(samples_ != NULL); | 701 ASSERT(samples_ != NULL); |
| 680 uintptr_t cursor = AtomicOperations::FetchAndIncrement(&cursor_); | 702 uintptr_t cursor = AtomicOperations::FetchAndIncrement(&cursor_); |
| 681 // Map back into sample buffer range. | 703 // Map back into sample buffer range. |
| 682 cursor = cursor % capacity_; | 704 cursor = cursor % capacity_; |
| 683 return &samples_[cursor]; | 705 return At(cursor); |
| 684 } | 706 } |
| 685 | 707 |
| 686 | 708 |
| 709 void SampleBuffer::CopySample(intptr_t i, Sample* sample) const { | |
| 710 At(i)->CopyInto(sample); | |
| 711 } | |
| 712 | |
| 713 | |
| 714 Sample* SampleBuffer::At(intptr_t idx) const { | |
| 715 ASSERT(idx >= 0); | |
| 716 ASSERT(idx < capacity_); | |
| 717 intptr_t offset = idx * Sample::InstanceSize(); | |
| 718 uint8_t* samples = reinterpret_cast<uint8_t*>(samples_); | |
| 719 return reinterpret_cast<Sample*>(samples + offset); | |
| 720 } | |
| 721 | |
| 722 | |
| 687 ProfilerSampleStackWalker::ProfilerSampleStackWalker(Sample* sample, | 723 ProfilerSampleStackWalker::ProfilerSampleStackWalker(Sample* sample, |
| 688 uintptr_t stack_lower, | 724 uintptr_t stack_lower, |
| 689 uintptr_t stack_upper, | 725 uintptr_t stack_upper, |
| 690 uintptr_t pc, | 726 uintptr_t pc, |
| 691 uintptr_t fp, | 727 uintptr_t fp, |
| 692 uintptr_t sp) : | 728 uintptr_t sp) : |
| 693 sample_(sample), | 729 sample_(sample), |
| 694 stack_lower_(stack_lower), | 730 stack_lower_(stack_lower), |
| 695 stack_upper_(stack_upper), | 731 stack_upper_(stack_upper), |
| 696 original_pc_(pc), | 732 original_pc_(pc), |
| 697 original_fp_(fp), | 733 original_fp_(fp), |
| 698 original_sp_(sp), | 734 original_sp_(sp), |
| 699 lower_bound_(stack_lower) { | 735 lower_bound_(stack_lower) { |
| 700 ASSERT(sample_ != NULL); | 736 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 } | 737 } |
| 706 | 738 |
| 707 | 739 |
| 740 // Notes on stack frame walking: | |
| 741 // | |
| 742 // The sampling profiler will collect up to Sample::kNumStackFrames stack frames | |
| 743 // The stack frame walking code uses the frame pointer to traverse the stack. | |
| 744 // If the VM is compiled without frame pointers (which is the default on | |
| 745 // recent GCC versions with optimizing enabled) the stack walking code may | |
| 746 // fail (sometimes leading to a crash). | |
| 747 // | |
| 748 | |
| 708 int ProfilerSampleStackWalker::walk() { | 749 int ProfilerSampleStackWalker::walk() { |
| 709 const intptr_t kMaxStep = 0x1000; // 4K. | 750 const intptr_t kMaxStep = 0x1000; // 4K. |
| 710 uword* pc = reinterpret_cast<uword*>(original_pc_); | 751 uword* pc = reinterpret_cast<uword*>(original_pc_); |
| 711 // Always store the exclusive PC. | 752 // Always store the exclusive PC. |
| 712 sample_->pcs[0] = original_pc_; | 753 sample_->pcs[0] = original_pc_; |
| 713 #define WALK_STACK | 754 #define WALK_STACK |
| 714 #if defined(WALK_STACK) | 755 #if defined(WALK_STACK) |
| 715 uword* fp = reinterpret_cast<uword*>(original_fp_); | 756 uword* fp = reinterpret_cast<uword*>(original_fp_); |
| 716 uword* previous_fp = fp; | 757 uword* previous_fp = fp; |
| 717 if (original_sp_ > original_fp_) { | 758 if (original_sp_ > original_fp_) { |
| 718 // Stack pointer should not be above frame pointer. | 759 // Stack pointer should not be above frame pointer. |
| 719 return 1; | 760 return 1; |
| 720 } | 761 } |
| 721 intptr_t gap = original_fp_ - original_sp_; | 762 intptr_t gap = original_fp_ - original_sp_; |
| 722 if (gap >= kMaxStep) { | 763 if (gap >= kMaxStep) { |
| 723 // Gap between frame pointer and stack pointer is | 764 // Gap between frame pointer and stack pointer is |
| 724 // too large. | 765 // too large. |
| 725 return 1; | 766 return 1; |
| 726 } | 767 } |
| 727 if (original_sp_ < lower_bound_) { | 768 if (original_sp_ < lower_bound_) { |
| 728 // The stack pointer gives us a better lower bound than | 769 // The stack pointer gives us a better lower bound than |
| 729 // the isolates stack limit. | 770 // the isolates stack limit. |
| 730 lower_bound_ = original_sp_; | 771 lower_bound_ = original_sp_; |
| 731 } | 772 } |
| 732 int i = 0; | 773 int i = 0; |
| 733 for (; i < Sample::kNumStackFrames; i++) { | 774 for (; i < FLAG_profile_frames; i++) { |
| 734 sample_->pcs[i] = reinterpret_cast<uintptr_t>(pc); | 775 sample_->pcs[i] = reinterpret_cast<uintptr_t>(pc); |
| 735 if (!ValidFramePointer(fp)) { | 776 if (!ValidFramePointer(fp)) { |
| 736 return i + 1; | 777 return i + 1; |
| 737 } | 778 } |
| 738 pc = CallerPC(fp); | 779 pc = CallerPC(fp); |
| 739 previous_fp = fp; | 780 previous_fp = fp; |
| 740 fp = CallerFP(fp); | 781 fp = CallerFP(fp); |
| 741 intptr_t step = fp - previous_fp; | 782 intptr_t step = fp - previous_fp; |
| 742 if ((step >= kMaxStep) || (fp <= previous_fp) || !ValidFramePointer(fp)) { | 783 if ((step >= kMaxStep) || (fp <= previous_fp) || !ValidFramePointer(fp)) { |
| 743 // Frame pointer step is too large. | 784 // Frame pointer step is too large. |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 773 return false; | 814 return false; |
| 774 } | 815 } |
| 775 uintptr_t cursor = reinterpret_cast<uintptr_t>(fp); | 816 uintptr_t cursor = reinterpret_cast<uintptr_t>(fp); |
| 776 cursor += sizeof(fp); | 817 cursor += sizeof(fp); |
| 777 bool r = cursor >= lower_bound_ && cursor < stack_upper_; | 818 bool r = cursor >= lower_bound_ && cursor < stack_upper_; |
| 778 return r; | 819 return r; |
| 779 } | 820 } |
| 780 | 821 |
| 781 | 822 |
| 782 } // namespace dart | 823 } // namespace dart |
| OLD | NEW |