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

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 if (StubCode::InInvocationStubForIsolate(isolate_,
1766 reinterpret_cast<uword>(pc_))) {
1767 // In invocation stub.
1768 return NextExit();
1769 }
1770 // In regular Dart frame.
1771 uword* new_pc = CallerPC();
1772 // Check if we've moved into the invocation stub.
1773 if (StubCode::InInvocationStubForIsolate(isolate_,
1774 reinterpret_cast<uword>(new_pc))) {
1775 // New PC is inside invocation stub, skip.
1776 return NextExit();
1777 }
1778 uword* new_fp = CallerFP();
1779 if (new_fp <= fp_) {
1780 // FP didn't move to a higher address.
1781 return false;
1782 }
1783 // Success, update fp and pc.
1784 fp_ = new_fp;
1785 pc_ = new_pc;
1786 return true;
1787 }
1788
1789 bool NextExit() {
1790 if (!ValidFramePointer()) {
1791 return false;
1792 }
1793 uword* new_fp = ExitLink();
1794 if (new_fp == NULL) {
1795 // No exit link.
1796 return false;
1797 }
1798 if (new_fp <= fp_) {
1799 // FP didn't move to a higher address.
1800 return false;
1801 }
1802 if (!ValidFramePointer(new_fp)) {
1803 return false;
1804 }
1805 // Success, update fp and pc.
1806 fp_ = new_fp;
1807 pc_ = CallerPC();
1808 return true;
1809 }
1810
1811 uword InitialReturnAddress() const {
1812 ASSERT(sp_ != NULL);
1813 return *(sp_);
1814 }
1815
1816 uword* CallerPC() const {
1817 ASSERT(fp_ != NULL);
1818 return reinterpret_cast<uword*>(*(fp_ + kSavedCallerPcSlotFromFp));
1819 }
1820
1821 uword* CallerFP() const {
1822 ASSERT(fp_ != NULL);
1823 return reinterpret_cast<uword*>(*(fp_ + kSavedCallerFpSlotFromFp));
1824 }
1825
1826 uword* ExitLink() const {
1827 ASSERT(fp_ != NULL);
1828 return reinterpret_cast<uword*>(*(fp_ + kExitLinkSlotFromEntryFp));
1829 }
1830
1831 bool ValidFramePointer() const {
1832 return ValidFramePointer(fp_);
1833 }
1834
1835 bool ValidFramePointer(uword* fp) const {
1836 if (fp == NULL) {
1837 return false;
1838 }
1839 uword cursor = reinterpret_cast<uword>(fp);
1840 cursor += sizeof(fp);
1841 return (cursor >= stack_lower_) && (cursor < stack_upper_);
1842 }
1843
1844 uword* pc_;
1845 uword* fp_;
1846 uword* sp_;
1847 Isolate* isolate_;
1848 Sample* sample_;
1849 const uword stack_upper_;
1850 uword stack_lower_;
1851 };
1852
1853
1725 // If the VM is compiled without frame pointers (which is the default on 1854 // 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 1855 // recent GCC versions with optimizing enabled) the stack walking code may
1727 // fail (sometimes leading to a crash). 1856 // fail.
1728 // 1857 //
1729 class ProfilerNativeStackWalker : public ValueObject { 1858 class ProfilerNativeStackWalker : public ValueObject {
1730 public: 1859 public:
1731 ProfilerNativeStackWalker(Sample* sample, 1860 ProfilerNativeStackWalker(Sample* sample,
1732 uword stack_lower, 1861 uword stack_lower,
1733 uword stack_upper, 1862 uword stack_upper,
1734 uword pc, 1863 uword pc,
1735 uword fp, 1864 uword fp,
1736 uword sp) 1865 uword sp)
1737 : sample_(sample), 1866 : sample_(sample),
1738 stack_upper_(stack_upper), 1867 stack_upper_(stack_upper),
1739 original_pc_(pc), 1868 original_pc_(pc),
1740 original_fp_(fp), 1869 original_fp_(fp),
1741 original_sp_(sp), 1870 original_sp_(sp),
1742 lower_bound_(stack_lower) { 1871 lower_bound_(stack_lower) {
1743 ASSERT(sample_ != NULL); 1872 ASSERT(sample_ != NULL);
1744 } 1873 }
1745 1874
1746 void walk(Heap* heap) { 1875 void walk() {
1747 const uword kMaxStep = VirtualMemory::PageSize(); 1876 const uword kMaxStep = VirtualMemory::PageSize();
1748 1877
1749 sample_->SetAt(0, original_pc_); 1878 sample_->SetAt(0, original_pc_);
1750 1879
1751 uword* pc = reinterpret_cast<uword*>(original_pc_); 1880 uword* pc = reinterpret_cast<uword*>(original_pc_);
1752 uword* fp = reinterpret_cast<uword*>(original_fp_); 1881 uword* fp = reinterpret_cast<uword*>(original_fp_);
1753 uword* previous_fp = fp; 1882 uword* previous_fp = fp;
1754 1883
1755 uword gap = original_fp_ - original_sp_; 1884 uword gap = original_fp_ - original_sp_;
1756 if (gap >= kMaxStep) { 1885 if (gap >= kMaxStep) {
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
1907 sample->Init(isolate, OS::GetCurrentTimeMicros(), state.tid); 2036 sample->Init(isolate, OS::GetCurrentTimeMicros(), state.tid);
1908 sample->set_vm_tag(isolate->vm_tag()); 2037 sample->set_vm_tag(isolate->vm_tag());
1909 sample->set_user_tag(isolate->user_tag()); 2038 sample->set_user_tag(isolate->user_tag());
1910 sample->set_sp(state.sp); 2039 sample->set_sp(state.sp);
1911 sample->set_fp(state.fp); 2040 sample->set_fp(state.fp);
1912 SetPCMarkerIfSafe(sample); 2041 SetPCMarkerIfSafe(sample);
1913 2042
1914 // Walk the call stack. 2043 // Walk the call stack.
1915 if (FLAG_profile_vm) { 2044 if (FLAG_profile_vm) {
1916 // Always walk the native stack collecting both native and Dart frames. 2045 // Always walk the native stack collecting both native and Dart frames.
1917 ProfilerNativeStackWalker stackWalker(sample, stack_lower, stack_upper, 2046 ProfilerNativeStackWalker stackWalker(sample,
1918 state.pc, state.fp, state.sp); 2047 stack_lower,
1919 stackWalker.walk(isolate->heap()); 2048 stack_upper,
2049 state.pc,
2050 state.fp,
2051 state.sp);
2052 stackWalker.walk();
1920 } else { 2053 } else {
1921 // Attempt to walk only the Dart call stack, falling back to walking 2054 // Attempt to walk only the Dart call stack, falling back to walking
1922 // the native stack. 2055 // the native stack.
1923 if ((isolate->stub_code() != NULL) && 2056 if ((isolate->stub_code() != NULL) &&
1924 (isolate->top_exit_frame_info() != 0) && 2057 (isolate->top_exit_frame_info() != 0) &&
1925 (isolate->vm_tag() != VMTag::kScriptTagId)) { 2058 (isolate->vm_tag() != VMTag::kScriptTagId)) {
1926 // We have a valid exit frame info, use the Dart stack walker. 2059 // We have a valid exit frame info, use the Dart stack walker.
1927 ProfilerDartStackWalker stackWalker(isolate, sample); 2060 ProfilerDartExitStackWalker stackWalker(isolate, sample);
2061 stackWalker.walk();
2062 } else if ((isolate->stub_code() != NULL) &&
2063 (isolate->top_exit_frame_info() == 0) &&
2064 (isolate->vm_tag() == VMTag::kScriptTagId)) {
2065 // We are executing Dart code. We have frame pointers.
2066 ProfilerDartStackWalker stackWalker(isolate,
2067 sample,
2068 stack_lower,
2069 stack_upper,
2070 state.pc,
2071 state.fp,
2072 state.sp);
1928 stackWalker.walk(); 2073 stackWalker.walk();
1929 } else { 2074 } else {
1930 ProfilerNativeStackWalker stackWalker(sample, stack_lower, stack_upper, 2075 // Fall back to an extremely conservative stack walker.
1931 state.pc, state.fp, state.sp); 2076 ProfilerNativeStackWalker stackWalker(sample,
1932 stackWalker.walk(isolate->heap()); 2077 stack_lower,
2078 stack_upper,
2079 state.pc,
2080 state.fp,
2081 state.sp);
2082 stackWalker.walk();
1933 } 2083 }
1934 } 2084 }
1935 } 2085 }
1936 2086
1937 } // namespace dart 2087 } // 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