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

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

Issue 408663004: Add Dart stack walker (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 | « runtime/vm/profiler.h ('k') | 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 1666 matching lines...) Expand 10 before | Expand all | Expand 10 after
1677 if ((sample->fp() & kPageMask) == 0) { 1677 if ((sample->fp() & kPageMask) == 0) {
1678 return; 1678 return;
1679 } 1679 }
1680 #endif 1680 #endif
1681 const uword pc_marker = *(fp + kPcMarkerSlotFromFp); 1681 const uword pc_marker = *(fp + kPcMarkerSlotFromFp);
1682 sample->set_pc_marker(pc_marker); 1682 sample->set_pc_marker(pc_marker);
1683 } 1683 }
1684 } 1684 }
1685 1685
1686 1686
1687 class ProfilerDartStackWalker : public ValueObject { 1687 // Given an exit frame, walk the Dart stack.
1688 class ProfilerDartExitStackWalker : public ValueObject {
1688 public: 1689 public:
1689 ProfilerDartStackWalker(Isolate* isolate, Sample* sample) 1690 ProfilerDartExitStackWalker(Isolate* isolate, Sample* sample)
1690 : sample_(sample), 1691 : sample_(sample),
1691 frame_iterator_(isolate) { 1692 frame_iterator_(isolate) {
1692 ASSERT(sample_ != NULL); 1693 ASSERT(sample_ != NULL);
1693 } 1694 }
1694 1695
1695 ProfilerDartStackWalker(Isolate* isolate, Sample* sample, uword fp) 1696 void walk() {
1696 : sample_(sample),
1697 frame_iterator_(fp, isolate) {
1698 ASSERT(sample_ != NULL);
1699 }
1700
1701 int walk() {
1702 intptr_t frame_index = 0; 1697 intptr_t frame_index = 0;
1703 StackFrame* frame = frame_iterator_.NextFrame(); 1698 StackFrame* frame = frame_iterator_.NextFrame();
1704 while (frame != NULL) { 1699 while (frame != NULL) {
1705 sample_->SetAt(frame_index, frame->pc()); 1700 sample_->SetAt(frame_index, frame->pc());
1706 frame_index++; 1701 frame_index++;
1707 if (frame_index >= FLAG_profile_depth) { 1702 if (frame_index >= FLAG_profile_depth) {
1708 break; 1703 break;
1709 } 1704 }
1710 frame = frame_iterator_.NextFrame(); 1705 frame = frame_iterator_.NextFrame();
1711 } 1706 }
1712 return frame_index;
1713 } 1707 }
1714 1708
1715 private: 1709 private:
1716 Sample* sample_; 1710 Sample* sample_;
1717 DartFrameIterator frame_iterator_; 1711 DartFrameIterator frame_iterator_;
1718 }; 1712 };
1719 1713
1720 1714
1721 // Notes on stack frame walking: 1715 // Executing Dart code, walk the stack.
1722 // 1716 class ProfilerDartStackWalker : public ValueObject {
1723 // The sampling profiler will collect up to Sample::kNumStackFrames stack frames 1717 public:
1724 // The stack frame walking code uses the frame pointer to traverse the stack. 1718 ProfilerDartStackWalker(Isolate* isolate,
1719 Sample* sample,
1720 uword stack_lower,
1721 uword stack_upper,
1722 uword pc,
1723 uword fp,
1724 uword sp)
1725 : isolate_(isolate),
1726 sample_(sample),
1727 stack_upper_(stack_upper),
1728 stack_lower_(stack_lower) {
1729 ASSERT(sample_ != NULL);
1730 pc_ = reinterpret_cast<uword*>(pc);
1731 fp_ = reinterpret_cast<uword*>(fp);
1732 sp_ = reinterpret_cast<uword*>(sp);
1733 }
1734
1735 void walk() {
1736 if (!ValidFramePointer()) {
1737 sample_->set_ignore_sample(true);
1738 return;
1739 }
1740 ASSERT(ValidFramePointer());
1741 uword return_pc = InitialReturnAddress();
1742 if (StubCode::InInvocationStubForIsolate(isolate_, return_pc)) {
1743 // Edge case- we have called out from the Invocation Stub but have not
1744 // created the stack frame of the callee. Attempt to locate the exit
1745 // frame before walking the stack.
1746 if (!NextExit() || !ValidFramePointer()) {
1747 // Nothing to sample.
1748 sample_->set_ignore_sample(true);
1749 return;
1750 }
1751 }
1752 for (int i = 0; i < FLAG_profile_depth; i++) {
1753 sample_->SetAt(i, reinterpret_cast<uword>(pc_));
1754 if (!Next()) {
1755 return;
1756 }
1757 }
1758 }
1759
1760 private:
1761 bool Next() {
1762 if (!ValidFramePointer()) {
1763 return false;
1764 }
1765 uword pc = reinterpret_cast<uword>(pc_);
1766 if (StubCode::InInvocationStubForIsolate(isolate_, pc)) {
1767 // In invocation stub.
1768 return NextExit();
1769 }
1770 // In regular Dart frame.
1771 pc_ = CallerPC();
1772 // Check if we've moved into the invocation stub.
1773 pc = reinterpret_cast<uword>(pc_);
1774 if (StubCode::InInvocationStubForIsolate(isolate_, pc)) {
1775 // New PC is inside invocation stub, skip.
1776 return NextExit();
1777 }
1778 uword* old_fp = fp_;
1779 fp_ = CallerFP();
1780 if (fp_ <= old_fp) {
1781 // FP didn't move to a higher address.
1782 return false;
1783 }
siva 2014/07/22 20:31:12 set pc_ only after determining that you are about
Cutch 2014/07/22 20:50:12 Done.
1784 return true;
1785 }
1786
1787 bool NextExit() {
1788 if (!ValidFramePointer()) {
1789 return false;
1790 }
1791 uword* old_fp = fp_;
1792 fp_ = ExitLink();
1793 if (fp_ == NULL) {
1794 // No exit link.
1795 return false;
1796 }
1797 if (!ValidFramePointer()) {
1798 return false;
1799 }
1800 if (fp_ <= old_fp) {
1801 // FP didn't move to a higher address.
1802 return false;
1803 }
siva 2014/07/22 20:31:12 In all the case where you return false, I feel you
Cutch 2014/07/22 20:50:12 Done.
1804 pc_ = CallerPC();
1805 return true;
1806 }
1807
1808 uword InitialReturnAddress() const {
1809 ASSERT(sp_ != NULL);
siva 2014/07/22 20:31:12 Probably need to assert ASSERT(FindCodeForPC(*sp
Cutch 2014/07/22 20:50:12 It's not guaranteed that we are reading a PC from
1810 return *(sp_);
1811 }
1812
1813 uword* CallerPC() const {
1814 ASSERT(fp_ != NULL);
1815 return reinterpret_cast<uword*>(*(fp_ + kSavedCallerPcSlotFromFp));
1816 }
1817
1818 uword* CallerFP() const {
1819 ASSERT(fp_ != NULL);
1820 return reinterpret_cast<uword*>(*(fp_ + kSavedCallerFpSlotFromFp));
1821 }
1822
1823 uword* ExitLink() const {
1824 ASSERT(fp_ != NULL);
1825 return reinterpret_cast<uword*>(*(fp_ + kExitLinkSlotFromEntryFp));
1826 }
1827
1828 bool ValidFramePointer() const {
1829 if (fp_ == NULL) {
1830 return false;
1831 }
1832 uword cursor = reinterpret_cast<uword>(fp_);
1833 cursor += sizeof(fp_);
1834 return (cursor >= stack_lower_) && (cursor < stack_upper_);
1835 }
1836
1837 uword* pc_;
1838 uword* fp_;
1839 uword* sp_;
1840 Isolate* isolate_;
1841 Sample* sample_;
1842 const uword stack_upper_;
1843 uword stack_lower_;
1844 };
1845
1846
1725 // If the VM is compiled without frame pointers (which is the default on 1847 // If the VM is compiled without frame pointers (which is the default on
1726 // recent GCC versions with optimizing enabled) the stack walking code may 1848 // recent GCC versions with optimizing enabled) the stack walking code may
1727 // fail (sometimes leading to a crash). 1849 // fail.
1728 // 1850 //
1729 class ProfilerNativeStackWalker : public ValueObject { 1851 class ProfilerNativeStackWalker : public ValueObject {
1730 public: 1852 public:
1731 ProfilerNativeStackWalker(Sample* sample, 1853 ProfilerNativeStackWalker(Sample* sample,
1732 uword stack_lower, 1854 uword stack_lower,
1733 uword stack_upper, 1855 uword stack_upper,
1734 uword pc, 1856 uword pc,
1735 uword fp, 1857 uword fp,
1736 uword sp) 1858 uword sp)
1737 : sample_(sample), 1859 : sample_(sample),
1738 stack_upper_(stack_upper), 1860 stack_upper_(stack_upper),
1739 original_pc_(pc), 1861 original_pc_(pc),
1740 original_fp_(fp), 1862 original_fp_(fp),
1741 original_sp_(sp), 1863 original_sp_(sp),
1742 lower_bound_(stack_lower) { 1864 lower_bound_(stack_lower) {
1743 ASSERT(sample_ != NULL); 1865 ASSERT(sample_ != NULL);
1744 } 1866 }
1745 1867
1746 void walk(Heap* heap) { 1868 void walk() {
1747 const uword kMaxStep = VirtualMemory::PageSize(); 1869 const uword kMaxStep = VirtualMemory::PageSize();
1748 1870
1749 sample_->SetAt(0, original_pc_); 1871 sample_->SetAt(0, original_pc_);
1750 1872
1751 uword* pc = reinterpret_cast<uword*>(original_pc_); 1873 uword* pc = reinterpret_cast<uword*>(original_pc_);
1752 uword* fp = reinterpret_cast<uword*>(original_fp_); 1874 uword* fp = reinterpret_cast<uword*>(original_fp_);
1753 uword* previous_fp = fp; 1875 uword* previous_fp = fp;
1754 1876
1755 uword gap = original_fp_ - original_sp_; 1877 uword gap = original_fp_ - original_sp_;
1756 if (gap >= kMaxStep) { 1878 if (gap >= kMaxStep) {
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
1907 sample->Init(isolate, OS::GetCurrentTimeMicros(), state.tid); 2029 sample->Init(isolate, OS::GetCurrentTimeMicros(), state.tid);
1908 sample->set_vm_tag(isolate->vm_tag()); 2030 sample->set_vm_tag(isolate->vm_tag());
1909 sample->set_user_tag(isolate->user_tag()); 2031 sample->set_user_tag(isolate->user_tag());
1910 sample->set_sp(state.sp); 2032 sample->set_sp(state.sp);
1911 sample->set_fp(state.fp); 2033 sample->set_fp(state.fp);
1912 SetPCMarkerIfSafe(sample); 2034 SetPCMarkerIfSafe(sample);
1913 2035
1914 // Walk the call stack. 2036 // Walk the call stack.
1915 if (FLAG_profile_vm) { 2037 if (FLAG_profile_vm) {
1916 // Always walk the native stack collecting both native and Dart frames. 2038 // Always walk the native stack collecting both native and Dart frames.
1917 ProfilerNativeStackWalker stackWalker(sample, stack_lower, stack_upper, 2039 ProfilerNativeStackWalker stackWalker(sample,
1918 state.pc, state.fp, state.sp); 2040 stack_lower,
1919 stackWalker.walk(isolate->heap()); 2041 stack_upper,
2042 state.pc,
2043 state.fp,
2044 state.sp);
2045 stackWalker.walk();
1920 } else { 2046 } else {
1921 // Attempt to walk only the Dart call stack, falling back to walking 2047 // Attempt to walk only the Dart call stack, falling back to walking
1922 // the native stack. 2048 // the native stack.
1923 if ((isolate->stub_code() != NULL) && 2049 if ((isolate->stub_code() != NULL) &&
1924 (isolate->top_exit_frame_info() != 0) && 2050 (isolate->top_exit_frame_info() != 0) &&
1925 (isolate->vm_tag() != VMTag::kScriptTagId)) { 2051 (isolate->vm_tag() != VMTag::kScriptTagId)) {
1926 // We have a valid exit frame info, use the Dart stack walker. 2052 // We have a valid exit frame info, use the Dart stack walker.
1927 ProfilerDartStackWalker stackWalker(isolate, sample); 2053 ProfilerDartExitStackWalker stackWalker(isolate, sample);
2054 stackWalker.walk();
2055 } else if ((isolate->stub_code() != NULL) &&
2056 (isolate->top_exit_frame_info() == 0) &&
2057 (isolate->vm_tag() == VMTag::kScriptTagId)) {
2058 // We are executing Dart code. We have frame pointers.
2059 ProfilerDartStackWalker stackWalker(isolate,
2060 sample,
2061 stack_lower,
2062 stack_upper,
2063 state.pc,
2064 state.fp,
2065 state.sp);
1928 stackWalker.walk(); 2066 stackWalker.walk();
1929 } else { 2067 } else {
1930 ProfilerNativeStackWalker stackWalker(sample, stack_lower, stack_upper, 2068 // Fall back to an extremely conservative stack walker.
1931 state.pc, state.fp, state.sp); 2069 ProfilerNativeStackWalker stackWalker(sample,
1932 stackWalker.walk(isolate->heap()); 2070 stack_lower,
2071 stack_upper,
2072 state.pc,
2073 state.fp,
2074 state.sp);
2075 stackWalker.walk();
1933 } 2076 }
1934 } 2077 }
1935 } 2078 }
1936 2079
1937 } // namespace dart 2080 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/profiler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698