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

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

Issue 397163002: Profiler cleanup (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 5 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 | « no previous file | no next file » | 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"
(...skipping 16 matching lines...) Expand all
27 #else 27 #else
28 DEFINE_FLAG(bool, profile, true, "Enable Sampling Profiler"); 28 DEFINE_FLAG(bool, profile, true, "Enable Sampling Profiler");
29 #endif 29 #endif
30 DEFINE_FLAG(bool, trace_profiled_isolates, false, "Trace profiled isolates."); 30 DEFINE_FLAG(bool, trace_profiled_isolates, false, "Trace profiled isolates.");
31 DEFINE_FLAG(charp, profile_dir, NULL, 31 DEFINE_FLAG(charp, profile_dir, NULL,
32 "Enable writing profile data into specified directory."); 32 "Enable writing profile data into specified directory.");
33 DEFINE_FLAG(int, profile_period, 1000, 33 DEFINE_FLAG(int, profile_period, 1000,
34 "Time between profiler samples in microseconds. Minimum 50."); 34 "Time between profiler samples in microseconds. Minimum 50.");
35 DEFINE_FLAG(int, profile_depth, 8, 35 DEFINE_FLAG(int, profile_depth, 8,
36 "Maximum number stack frames walked. Minimum 1. Maximum 255."); 36 "Maximum number stack frames walked. Minimum 1. Maximum 255.");
37 DEFINE_FLAG(bool, profile_verify_stack_walk, false,
38 "Verify instruction addresses while walking the stack.");
39 DEFINE_FLAG(bool, profile_vm, false, 37 DEFINE_FLAG(bool, profile_vm, false,
40 "Always collect native stack traces."); 38 "Always collect native stack traces.");
41 39
42 bool Profiler::initialized_ = false; 40 bool Profiler::initialized_ = false;
43 SampleBuffer* Profiler::sample_buffer_ = NULL; 41 SampleBuffer* Profiler::sample_buffer_ = NULL;
44 42
45 void Profiler::InitOnce() { 43 void Profiler::InitOnce() {
46 // Place some sane restrictions on user controlled flags. 44 // Place some sane restrictions on user controlled flags.
47 SetSamplePeriod(FLAG_profile_period); 45 SetSamplePeriod(FLAG_profile_period);
48 SetSampleDepth(FLAG_profile_depth); 46 SetSampleDepth(FLAG_profile_depth);
(...skipping 1607 matching lines...) Expand 10 before | Expand all | Expand 10 after
1656 1654
1657 Sample* SampleBuffer::ReserveSample() { 1655 Sample* SampleBuffer::ReserveSample() {
1658 ASSERT(samples_ != NULL); 1656 ASSERT(samples_ != NULL);
1659 uintptr_t cursor = AtomicOperations::FetchAndIncrement(&cursor_); 1657 uintptr_t cursor = AtomicOperations::FetchAndIncrement(&cursor_);
1660 // Map back into sample buffer range. 1658 // Map back into sample buffer range.
1661 cursor = cursor % capacity_; 1659 cursor = cursor % capacity_;
1662 return At(cursor); 1660 return At(cursor);
1663 } 1661 }
1664 1662
1665 1663
1664 static void SetPCMarkerIfSafe(Sample* sample) {
1665 ASSERT(sample != NULL);
1666
1667 uword* fp = reinterpret_cast<uword*>(sample->fp());
1668 uword* sp = reinterpret_cast<uword*>(sample->sp());
1669
1670 // If FP == SP, the pc marker hasn't been pushed.
1671 if (fp > sp) {
1672 #if defined(TARGET_OS_WINDOWS)
1673 // If the fp is at the beginning of a page, it may be unsafe to access
1674 // the pc marker, because we are reading it from a different thread on
1675 // Windows. The next page may be a guard page.
1676 const intptr_t kPageMask = VirtualMemory::PageSize() - 1;
1677 if ((sample->fp() & kPageMask) == 0) {
1678 return;
1679 }
1680 #endif
1681 const uword pc_marker = *(fp + kPcMarkerSlotFromFp);
1682 sample->set_pc_marker(pc_marker);
1683 }
1684 }
1685
1686
1666 class ProfilerDartStackWalker : public ValueObject { 1687 class ProfilerDartStackWalker : public ValueObject {
1667 public: 1688 public:
1668 ProfilerDartStackWalker(Isolate* isolate, Sample* sample) 1689 ProfilerDartStackWalker(Isolate* isolate, Sample* sample)
1669 : sample_(sample), 1690 : sample_(sample),
1670 frame_iterator_(isolate) { 1691 frame_iterator_(isolate) {
1671 ASSERT(sample_ != NULL); 1692 ASSERT(sample_ != NULL);
1672 } 1693 }
1673 1694
1674 ProfilerDartStackWalker(Isolate* isolate, Sample* sample, uword fp) 1695 ProfilerDartStackWalker(Isolate* isolate, Sample* sample, uword fp)
1675 : sample_(sample), 1696 : sample_(sample),
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1715 uword sp) 1736 uword sp)
1716 : sample_(sample), 1737 : sample_(sample),
1717 stack_upper_(stack_upper), 1738 stack_upper_(stack_upper),
1718 original_pc_(pc), 1739 original_pc_(pc),
1719 original_fp_(fp), 1740 original_fp_(fp),
1720 original_sp_(sp), 1741 original_sp_(sp),
1721 lower_bound_(stack_lower) { 1742 lower_bound_(stack_lower) {
1722 ASSERT(sample_ != NULL); 1743 ASSERT(sample_ != NULL);
1723 } 1744 }
1724 1745
1725 int walk(Heap* heap) { 1746 void walk(Heap* heap) {
1726 const intptr_t kMaxStep = 0x1000; // 4K. 1747 const intptr_t kMaxStep = VirtualMemory::PageSize();
1727 const bool kWalkStack = true; // Walk the stack. 1748
1728 // Always store the exclusive PC.
1729 sample_->SetAt(0, original_pc_); 1749 sample_->SetAt(0, original_pc_);
1730 if (!kWalkStack) { 1750
1731 // Not walking the stack, only took exclusive sample.
1732 return 1;
1733 }
1734 uword* pc = reinterpret_cast<uword*>(original_pc_); 1751 uword* pc = reinterpret_cast<uword*>(original_pc_);
1735 uword* fp = reinterpret_cast<uword*>(original_fp_); 1752 uword* fp = reinterpret_cast<uword*>(original_fp_);
1736 uword* previous_fp = fp; 1753 uword* previous_fp = fp;
1737 if (original_sp_ > original_fp_) { 1754
1738 // Stack pointer should not be above frame pointer. 1755 if ((original_fp_ - original_sp_) >= kMaxStep) {
1739 return 1;
1740 }
1741 const intptr_t gap = original_fp_ - original_sp_;
1742 if (gap >= kMaxStep) {
1743 // Gap between frame pointer and stack pointer is 1756 // Gap between frame pointer and stack pointer is
1744 // too large. 1757 // too large.
1745 return 1; 1758 return;
1746 } 1759 }
1747 if (original_sp_ < lower_bound_) { 1760
1748 // The stack pointer gives us a better lower bound than 1761 if (!ValidFramePointer(fp)) {
1749 // the isolates stack limit. 1762 return;
1750 lower_bound_ = original_sp_;
1751 } 1763 }
1752 #if defined(TARGET_OS_WINDOWS) 1764
1753 // If the original_fp_ is at the beginning of a page, it may be unsafe 1765 for (int i = 0; i < FLAG_profile_depth; i++) {
1754 // to access the pc marker, because we are reading it from a different
1755 // thread on Windows. The next page may be a guard page.
1756 const intptr_t kPageMask = kMaxStep - 1;
1757 bool safe_to_read_pc_marker = (original_fp_ & kPageMask) != 0;
1758 #else
1759 bool safe_to_read_pc_marker = true;
1760 #endif
1761 if (safe_to_read_pc_marker && (gap > 0)) {
1762 // Store the PC marker for the top frame.
1763 sample_->set_pc_marker(GetCurrentFramePcMarker(fp));
1764 }
1765 int i = 0;
1766 for (; i < FLAG_profile_depth; i++) {
1767 if (FLAG_profile_verify_stack_walk) {
1768 VerifyCodeAddress(heap, i, reinterpret_cast<uword>(pc));
1769 }
1770 sample_->SetAt(i, reinterpret_cast<uword>(pc)); 1766 sample_->SetAt(i, reinterpret_cast<uword>(pc));
1771 if (fp == NULL) { 1767
1772 return i + 1;
1773 }
1774 if (!ValidFramePointer(fp)) {
1775 return i + 1;
1776 }
1777 pc = CallerPC(fp); 1768 pc = CallerPC(fp);
1778 previous_fp = fp; 1769 previous_fp = fp;
1779 fp = CallerFP(fp); 1770 fp = CallerFP(fp);
1780 intptr_t step = fp - previous_fp; 1771
1781 if (fp == NULL) { 1772 if (fp == NULL) {
1782 return i + 1; 1773 return;
1783 } 1774 }
1784 if ((step >= kMaxStep)) { 1775
1776 if (fp <= previous_fp) {
1777 // Frame pointer did not move to a higher address.
1778 return;
1779 }
1780
1781 if ((fp - previous_fp) >= kMaxStep) {
1785 // Frame pointer step is too large. 1782 // Frame pointer step is too large.
1786 return i + 1; 1783 return;
1787 } 1784 }
1788 if ((fp <= previous_fp)) { 1785
1789 // Frame pointer did not move to a higher address. 1786 if (!ValidFramePointer(fp)) {
1790 return i + 1; 1787 // Frame pointer is outside of isolate stack boundary.
1788 return;
1791 } 1789 }
1792 if (!ValidFramePointer(fp)) { 1790
1793 // Frame pointer is outside of isolate stack bounds.
1794 return i + 1;
1795 }
1796 // Move the lower bound up. 1791 // Move the lower bound up.
1797 lower_bound_ = reinterpret_cast<uword>(fp); 1792 lower_bound_ = reinterpret_cast<uword>(fp);
1798 } 1793 }
1799 return i;
1800 } 1794 }
1801 1795
1802 private: 1796 private:
1803 void VerifyCodeAddress(Heap* heap, int i, uword pc) {
1804 if (heap != NULL) {
1805 if (heap->Contains(pc) && !heap->CodeContains(pc)) {
1806 for (int j = 0; j < i; j++) {
1807 OS::Print("%d %" Px "\n", j, sample_->At(j));
1808 }
1809 OS::Print("%d %" Px " <--\n", i, pc);
1810 OS::Print("---ASSERT-FAILED---\n");
1811 OS::Print("%" Px " %" Px "\n", original_pc_, original_fp_);
1812 UNREACHABLE();
1813 }
1814 }
1815 }
1816
1817 uword* CallerPC(uword* fp) const { 1797 uword* CallerPC(uword* fp) const {
1818 ASSERT(fp != NULL); 1798 ASSERT(fp != NULL);
1819 return reinterpret_cast<uword*>(*(fp + kSavedCallerPcSlotFromFp)); 1799 return reinterpret_cast<uword*>(*(fp + kSavedCallerPcSlotFromFp));
1820 } 1800 }
1821 1801
1822 uword* CallerFP(uword* fp) const { 1802 uword* CallerFP(uword* fp) const {
1823 ASSERT(fp != NULL); 1803 ASSERT(fp != NULL);
1824 return reinterpret_cast<uword*>(*(fp + kSavedCallerFpSlotFromFp)); 1804 return reinterpret_cast<uword*>(*(fp + kSavedCallerFpSlotFromFp));
1825 } 1805 }
1826 1806
1827 uword GetCurrentFramePcMarker(uword* fp) const {
1828 if (!ValidFramePointer(fp)) {
1829 return 0;
1830 }
1831 return *(fp + kPcMarkerSlotFromFp);
1832 }
1833
1834 bool ValidFramePointer(uword* fp) const { 1807 bool ValidFramePointer(uword* fp) const {
1835 if (fp == NULL) { 1808 if (fp == NULL) {
1836 return false; 1809 return false;
1837 } 1810 }
1838 uword cursor = reinterpret_cast<uword>(fp); 1811 uword cursor = reinterpret_cast<uword>(fp);
1839 cursor += sizeof(fp); 1812 cursor += sizeof(fp);
1840 bool r = cursor >= lower_bound_ && cursor < stack_upper_; 1813 bool r = (cursor >= lower_bound_) && (cursor < stack_upper_);
1841 return r; 1814 return r;
1842 } 1815 }
1843 1816
1844 Sample* sample_; 1817 Sample* sample_;
1845 const uword stack_upper_; 1818 const uword stack_upper_;
1846 const uword original_pc_; 1819 const uword original_pc_;
1847 const uword original_fp_; 1820 const uword original_fp_;
1848 const uword original_sp_; 1821 const uword original_sp_;
1849 uword lower_bound_; 1822 uword lower_bound_;
1850 }; 1823 };
1851 1824
1852 1825
1853 void Profiler::RecordSampleInterruptCallback( 1826 void Profiler::RecordSampleInterruptCallback(
1854 const InterruptedThreadState& state, 1827 const InterruptedThreadState& state,
1855 void* data) { 1828 void* data) {
1856 Isolate* isolate = reinterpret_cast<Isolate*>(data); 1829 Isolate* isolate = reinterpret_cast<Isolate*>(data);
1857 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) { 1830 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) {
1831 // No isolate.
1858 return; 1832 return;
1859 } 1833 }
1834
1860 ASSERT(isolate != Dart::vm_isolate()); 1835 ASSERT(isolate != Dart::vm_isolate());
1836
1837 IsolateProfilerData* profiler_data = isolate->profiler_data();
1838 if (profiler_data == NULL) {
1839 // Profiler not initialized.
1840 return;
1841 }
1842
1843 SampleBuffer* sample_buffer = profiler_data->sample_buffer();
1844 if (sample_buffer == NULL) {
1845 // Profiler not initialized.
1846 return;
1847 }
1848
1849 if ((state.sp == 0) || (state.fp == 0) || (state.pc == 0)) {
1850 // None of these registers should be zero.
1851 return;
1852 }
1853
1854 if (state.sp > state.fp) {
1855 // Assuming the stack grows down, we should never have a stack pointer above
1856 // the frame pointer.
1857 return;
1858 }
1859
1861 if (StubCode::InJumpToExceptionHandlerStub(state.pc)) { 1860 if (StubCode::InJumpToExceptionHandlerStub(state.pc)) {
1862 // The JumpToExceptionHandler stub manually adjusts the stack pointer, 1861 // The JumpToExceptionHandler stub manually adjusts the stack pointer,
1863 // frame pointer, and some isolate state before jumping to a catch entry. 1862 // frame pointer, and some isolate state before jumping to a catch entry.
1864 // It is not safe to walk the stack when executing this stub. 1863 // It is not safe to walk the stack when executing this stub.
1865 return; 1864 return;
1866 } 1865 }
1866
1867 uword stack_lower = 0;
1868 uword stack_upper = 0;
1869 isolate->GetStackBounds(&stack_lower, &stack_upper);
1870 if ((stack_lower == 0) || (stack_upper == 0)) {
1871 // Could not get stack boundary.
1872 return;
1873 }
1874
1875 if (state.sp > stack_lower) {
1876 // The stack pointer gives us a tighter lower bound.
1877 stack_lower = state.sp;
1878 }
1879
1880 if (stack_lower >= stack_upper) {
1881 // Stack boundary is invalid.
1882 return;
1883 }
1884
1885 if ((state.sp < stack_lower) || (state.sp >= stack_upper)) {
1886 // Stack pointer is outside isolate stack boundary.
1887 return;
1888 }
1889
1890 if ((state.fp < stack_lower) || (state.fp >= stack_upper)) {
1891 // Frame pointer is outside isolate stack boundary.
1892 return;
1893 }
1894
1895 // At this point we have a valid stack boundary for this isolate and
1896 // know that our initial stack and frame pointers are within the boundary.
1897
1898 // Increment counter for vm tag.
1867 VMTagCounters* counters = isolate->vm_tag_counters(); 1899 VMTagCounters* counters = isolate->vm_tag_counters();
1868 ASSERT(counters != NULL); 1900 ASSERT(counters != NULL);
1869 counters->Increment(isolate->vm_tag()); 1901 counters->Increment(isolate->vm_tag());
1870 IsolateProfilerData* profiler_data = isolate->profiler_data(); 1902
1871 if (profiler_data == NULL) { 1903 // Setup sample.
1872 return;
1873 }
1874 SampleBuffer* sample_buffer = profiler_data->sample_buffer();
1875 if (sample_buffer == NULL) {
1876 return;
1877 }
1878 Sample* sample = sample_buffer->ReserveSample(); 1904 Sample* sample = sample_buffer->ReserveSample();
1879 sample->Init(isolate, OS::GetCurrentTimeMicros(), state.tid); 1905 sample->Init(isolate, OS::GetCurrentTimeMicros(), state.tid);
1880 sample->set_vm_tag(isolate->vm_tag()); 1906 sample->set_vm_tag(isolate->vm_tag());
1881 sample->set_user_tag(isolate->user_tag()); 1907 sample->set_user_tag(isolate->user_tag());
1882 sample->set_sp(state.sp); 1908 sample->set_sp(state.sp);
1883 sample->set_fp(state.fp); 1909 sample->set_fp(state.fp);
1910 SetPCMarkerIfSafe(sample);
1884 1911
1885 uword stack_lower = 0; 1912 // Walk the call stack.
1886 uword stack_upper = 0;
1887 isolate->GetStackBounds(&stack_lower, &stack_upper);
1888 if ((stack_lower == 0) || (stack_upper == 0)) {
1889 stack_lower = 0;
1890 stack_upper = 0;
1891 }
1892 if (FLAG_profile_vm) { 1913 if (FLAG_profile_vm) {
1893 // Collect native and Dart frames. 1914 // Always walk the native stack collecting both native and Dart frames.
1894 ProfilerNativeStackWalker stackWalker(sample, stack_lower, stack_upper, 1915 ProfilerNativeStackWalker stackWalker(sample, stack_lower, stack_upper,
1895 state.pc, state.fp, state.sp); 1916 state.pc, state.fp, state.sp);
1896 stackWalker.walk(isolate->heap()); 1917 stackWalker.walk(isolate->heap());
1897 } else { 1918 } else {
1919 // Attempt to walk only the Dart call stack, falling back to walking
1920 // the native stack.
1898 if ((isolate->stub_code() != NULL) && 1921 if ((isolate->stub_code() != NULL) &&
1899 (isolate->top_exit_frame_info() != 0) && 1922 (isolate->top_exit_frame_info() != 0) &&
1900 (isolate->vm_tag() != VMTag::kScriptTagId)) { 1923 (isolate->vm_tag() != VMTag::kScriptTagId)) {
1901 // We have a valid exit frame info, use the Dart stack walker. 1924 // We have a valid exit frame info, use the Dart stack walker.
1902 ProfilerDartStackWalker stackWalker(isolate, sample); 1925 ProfilerDartStackWalker stackWalker(isolate, sample);
1903 stackWalker.walk(); 1926 stackWalker.walk();
1904 } else { 1927 } else {
1905 // Collect native and Dart frames.
1906 ProfilerNativeStackWalker stackWalker(sample, stack_lower, stack_upper, 1928 ProfilerNativeStackWalker stackWalker(sample, stack_lower, stack_upper,
1907 state.pc, state.fp, state.sp); 1929 state.pc, state.fp, state.sp);
1908 stackWalker.walk(isolate->heap()); 1930 stackWalker.walk(isolate->heap());
1909 } 1931 }
1910 } 1932 }
1911 } 1933 }
1912 1934
1913 } // namespace dart 1935 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698