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" |
(...skipping 1666 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 |
OLD | NEW |