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

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

Issue 1758653003: Add source position information to profile (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 9 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
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/assert.h" 5 #include "platform/assert.h"
6 6
7 #include "vm/dart_api_impl.h" 7 #include "vm/dart_api_impl.h"
8 #include "vm/dart_api_state.h" 8 #include "vm/dart_api_state.h"
9 #include "vm/globals.h" 9 #include "vm/globals.h"
10 #include "vm/profiler.h" 10 #include "vm/profiler.h"
11 #include "vm/profiler_service.h" 11 #include "vm/profiler_service.h"
12 #include "vm/unit_test.h" 12 #include "vm/unit_test.h"
13 13
14 namespace dart { 14 namespace dart {
15 15
16 #ifndef PRODUCT 16 #ifndef PRODUCT
17 17
18 DECLARE_FLAG(bool, profile_vm); 18 DECLARE_FLAG(bool, profile_vm);
19 DECLARE_FLAG(int, max_profile_depth); 19 DECLARE_FLAG(int, max_profile_depth);
20 DECLARE_FLAG(bool, enable_inlining_annotations);
21 DECLARE_FLAG(int, optimization_counter_threshold);
22
23 template<typename T>
24 class SetFlagScope : public ValueObject {
25 public:
26 SetFlagScope(T* flag, T value)
27 : flag_(flag),
28 original_value_(*flag) {
29 *flag_ = value;
30 }
31
32 ~SetFlagScope() {
33 *flag_ = original_value_;
34 }
35
36 private:
37 T* flag_;
38 T original_value_;
39 };
20 40
21 // Some tests are written assuming native stack trace profiling is disabled. 41 // Some tests are written assuming native stack trace profiling is disabled.
22 class DisableNativeProfileScope : public ValueObject { 42 class DisableNativeProfileScope : public ValueObject {
23 public: 43 public:
24 DisableNativeProfileScope() 44 DisableNativeProfileScope()
25 : FLAG_profile_vm_(FLAG_profile_vm) { 45 : FLAG_profile_vm_(FLAG_profile_vm) {
26 FLAG_profile_vm = false; 46 FLAG_profile_vm = false;
27 } 47 }
28 48
29 ~DisableNativeProfileScope() { 49 ~DisableNativeProfileScope() {
(...skipping 1621 matching lines...) Expand 10 before | Expand all | Expand 10 after
1651 EXPECT(walker.Down()); 1671 EXPECT(walker.Down());
1652 EXPECT_STREQ("init", walker.CurrentName()); 1672 EXPECT_STREQ("init", walker.CurrentName());
1653 EXPECT(walker.Down()); 1673 EXPECT(walker.Down());
1654 EXPECT_STREQ("go", walker.CurrentName()); 1674 EXPECT_STREQ("go", walker.CurrentName());
1655 EXPECT(walker.Down()); 1675 EXPECT(walker.Down());
1656 EXPECT_STREQ("main", walker.CurrentName()); 1676 EXPECT_STREQ("main", walker.CurrentName());
1657 EXPECT(!walker.Down()); 1677 EXPECT(!walker.Down());
1658 } 1678 }
1659 } 1679 }
1660 1680
1681
1682 TEST_CASE(Profiler_BasicSourcePosition) {
1683 DisableNativeProfileScope dnps;
1684 const char* kScript =
1685 "const AlwaysInline = 'AlwaysInline';\n"
1686 "const NeverInline = 'NeverInline';\n"
1687 "class A {\n"
1688 " var a;\n"
1689 " var b;\n"
1690 " @NeverInline A() { }\n"
1691 "}\n"
1692 "class B {\n"
1693 " @AlwaysInline\n"
1694 " static boo() {\n"
1695 " return new A();\n"
1696 " }\n"
1697 "}\n"
1698 "main() {\n"
1699 " B.boo();\n"
1700 "}\n";
1701
1702 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
1703 EXPECT_VALID(lib);
1704 Library& root_library = Library::Handle();
1705 root_library ^= Api::UnwrapHandle(lib);
1706
1707 const Class& class_a = Class::Handle(GetClass(root_library, "A"));
1708 EXPECT(!class_a.IsNull());
1709
1710 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
1711 EXPECT_VALID(result);
1712
1713 // Turn on allocation tracing for A.
1714 class_a.SetTraceAllocation(true);
1715
1716 // Allocate one time.
1717 result = Dart_Invoke(lib, NewString("main"), 0, NULL);
1718 EXPECT_VALID(result);
1719
1720 {
1721 Thread* thread = Thread::Current();
1722 Isolate* isolate = thread->isolate();
1723 StackZone zone(thread);
1724 HANDLESCOPE(thread);
1725 Profile profile(isolate);
1726 AllocationFilter filter(isolate, class_a.id());
1727 profile.Build(thread, &filter, Profile::kNoTags);
1728 // We should have one allocation samples.
1729 EXPECT_EQ(1, profile.sample_count());
1730 ProfileTrieWalker walker(&profile);
1731
1732 // Exclusive function: B.boo -> main.
1733 walker.Reset(Profile::kExclusiveFunction);
1734 // Move down from the root.
1735 EXPECT(walker.Down());
1736 EXPECT_STREQ("B.boo", walker.CurrentName());
1737 EXPECT_EQ(1, walker.CurrentNodeTickCount());
1738 EXPECT_EQ(1, walker.CurrentInclusiveTicks());
1739 EXPECT_EQ(1, walker.CurrentExclusiveTicks());
1740 EXPECT_STREQ("A", walker.CurrentToken());
1741 EXPECT(walker.Down());
1742 EXPECT_STREQ("main", walker.CurrentName());
1743 EXPECT_EQ(1, walker.CurrentNodeTickCount());
1744 EXPECT_EQ(1, walker.CurrentInclusiveTicks());
1745 EXPECT_EQ(0, walker.CurrentExclusiveTicks());
1746 EXPECT_STREQ("boo", walker.CurrentToken());
1747 EXPECT(!walker.Down());
1748 }
1749 }
1750
1751
1752 TEST_CASE(Profiler_BasicSourcePositionOptimized) {
1753 DisableNativeProfileScope dnps;
1754 // We use the AlwaysInline and NeverInline annotations in this test.
1755 SetFlagScope<bool> sfs(&FLAG_enable_inlining_annotations, true);
1756 // Optimize quickly.
1757 SetFlagScope<int> sfs2(&FLAG_optimization_counter_threshold, 5);
1758 const char* kScript =
1759 "const AlwaysInline = 'AlwaysInline';\n"
1760 "const NeverInline = 'NeverInline';\n"
1761 "class A {\n"
1762 " var a;\n"
1763 " var b;\n"
1764 " @NeverInline A() { }\n"
1765 "}\n"
1766 "class B {\n"
1767 " @AlwaysInline\n"
1768 " static boo() {\n"
1769 " return new A();\n"
1770 " }\n"
1771 "}\n"
1772 "main() {\n"
1773 " B.boo();\n"
1774 "}\n";
1775
1776 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
1777 EXPECT_VALID(lib);
1778 Library& root_library = Library::Handle();
1779 root_library ^= Api::UnwrapHandle(lib);
1780
1781 const Class& class_a = Class::Handle(GetClass(root_library, "A"));
1782 EXPECT(!class_a.IsNull());
1783
1784 const Function& main = Function::Handle(GetFunction(root_library, "main"));
1785 EXPECT(!main.IsNull());
1786
1787 // Warm up function.
1788 while (true) {
1789 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
1790 EXPECT_VALID(result);
1791 const Code& code = Code::Handle(main.CurrentCode());
1792 if (code.is_optimized()) {
1793 // Warmed up.
1794 break;
1795 }
1796 }
1797
1798 // Turn on allocation tracing for A.
1799 class_a.SetTraceAllocation(true);
1800
1801 // Allocate one time.
1802 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
1803 EXPECT_VALID(result);
1804
1805 // Still optimized.
1806 const Code& code = Code::Handle(main.CurrentCode());
1807 EXPECT(code.is_optimized());
1808
1809 {
1810 Thread* thread = Thread::Current();
1811 Isolate* isolate = thread->isolate();
1812 StackZone zone(thread);
1813 HANDLESCOPE(thread);
1814 Profile profile(isolate);
1815 AllocationFilter filter(isolate, class_a.id());
1816 profile.Build(thread, &filter, Profile::kNoTags);
1817 // We should have one allocation samples.
1818 EXPECT_EQ(1, profile.sample_count());
1819 ProfileTrieWalker walker(&profile);
1820
1821 // Exclusive function: B.boo -> main.
1822 walker.Reset(Profile::kExclusiveFunction);
1823 // Move down from the root.
1824 EXPECT(walker.Down());
1825 EXPECT_STREQ("B.boo", walker.CurrentName());
1826 EXPECT_EQ(1, walker.CurrentNodeTickCount());
1827 EXPECT_EQ(1, walker.CurrentInclusiveTicks());
1828 EXPECT_EQ(1, walker.CurrentExclusiveTicks());
1829 EXPECT_STREQ("A", walker.CurrentToken());
1830 EXPECT(walker.Down());
1831 EXPECT_STREQ("main", walker.CurrentName());
1832 EXPECT_EQ(1, walker.CurrentNodeTickCount());
1833 EXPECT_EQ(1, walker.CurrentInclusiveTicks());
1834 EXPECT_EQ(0, walker.CurrentExclusiveTicks());
1835 EXPECT_STREQ("boo", walker.CurrentToken());
1836 EXPECT(!walker.Down());
1837 }
1838 }
1839
1840
1841 TEST_CASE(Profiler_SourcePosition) {
1842 DisableNativeProfileScope dnps;
1843 const char* kScript =
1844 "const AlwaysInline = 'AlwaysInline';\n"
1845 "const NeverInline = 'NeverInline';\n"
1846 "class A {\n"
1847 " var a;\n"
1848 " var b;\n"
1849 " @NeverInline A() { }\n"
1850 "}\n"
1851 "class B {\n"
1852 " @NeverInline\n"
1853 " static oats() {\n"
1854 " return boo();\n"
1855 " }\n"
1856 " @AlwaysInline\n"
1857 " static boo() {\n"
1858 " return new A();\n"
1859 " }\n"
1860 "}\n"
1861 "class C {\n"
1862 " @NeverInline bacon() {\n"
1863 " return fox();\n"
1864 " }\n"
1865 " @AlwaysInline fox() {\n"
1866 " return B.oats();\n"
1867 " }\n"
1868 "}\n"
1869 "main() {\n"
1870 " new C()..bacon();\n"
1871 "}\n";
1872
1873 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
1874 EXPECT_VALID(lib);
1875 Library& root_library = Library::Handle();
1876 root_library ^= Api::UnwrapHandle(lib);
1877
1878 const Class& class_a = Class::Handle(GetClass(root_library, "A"));
1879 EXPECT(!class_a.IsNull());
1880
1881 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
1882 EXPECT_VALID(result);
1883
1884 // Turn on allocation tracing for A.
1885 class_a.SetTraceAllocation(true);
1886
1887 // Allocate one time.
1888 result = Dart_Invoke(lib, NewString("main"), 0, NULL);
1889 EXPECT_VALID(result);
1890
1891 {
1892 Thread* thread = Thread::Current();
1893 Isolate* isolate = thread->isolate();
1894 StackZone zone(thread);
1895 HANDLESCOPE(thread);
1896 Profile profile(isolate);
1897 AllocationFilter filter(isolate, class_a.id());
1898 profile.Build(thread, &filter, Profile::kNoTags);
1899 // We should have one allocation samples.
1900 EXPECT_EQ(1, profile.sample_count());
1901 ProfileTrieWalker walker(&profile);
1902
1903 // Exclusive function: B.boo -> main.
1904 walker.Reset(Profile::kExclusiveFunction);
1905 // Move down from the root.
1906 EXPECT(walker.Down());
1907 EXPECT_STREQ("B.boo", walker.CurrentName());
1908 EXPECT_EQ(1, walker.CurrentNodeTickCount());
1909 EXPECT_EQ(1, walker.CurrentInclusiveTicks());
1910 EXPECT_EQ(1, walker.CurrentExclusiveTicks());
1911 EXPECT_STREQ("A", walker.CurrentToken());
1912 EXPECT(walker.Down());
1913 EXPECT_STREQ("B.oats", walker.CurrentName());
1914 EXPECT_EQ(1, walker.CurrentNodeTickCount());
1915 EXPECT_EQ(1, walker.CurrentInclusiveTicks());
1916 EXPECT_EQ(0, walker.CurrentExclusiveTicks());
1917 EXPECT_STREQ("boo", walker.CurrentToken());
1918 EXPECT(walker.Down());
1919 EXPECT_STREQ("C.fox", walker.CurrentName());
1920 EXPECT_EQ(1, walker.CurrentNodeTickCount());
1921 EXPECT_EQ(1, walker.CurrentInclusiveTicks());
1922 EXPECT_EQ(0, walker.CurrentExclusiveTicks());
1923 EXPECT_STREQ("oats", walker.CurrentToken());
1924 EXPECT(walker.Down());
1925 EXPECT_STREQ("C.bacon", walker.CurrentName());
1926 EXPECT_EQ(1, walker.CurrentNodeTickCount());
1927 EXPECT_EQ(1, walker.CurrentInclusiveTicks());
1928 EXPECT_EQ(0, walker.CurrentExclusiveTicks());
1929 EXPECT_STREQ("fox", walker.CurrentToken());
1930 EXPECT(walker.Down());
1931 EXPECT_STREQ("main", walker.CurrentName());
1932 EXPECT_EQ(1, walker.CurrentNodeTickCount());
1933 EXPECT_EQ(1, walker.CurrentInclusiveTicks());
1934 EXPECT_EQ(0, walker.CurrentExclusiveTicks());
1935 EXPECT_STREQ("bacon", walker.CurrentToken());
1936 EXPECT(!walker.Down());
1937 }
1938 }
1939
1940
1941 TEST_CASE(Profiler_SourcePositionOptimized) {
srdjan 2016/03/02 19:02:56 Disable background compilation
Cutch 2016/03/02 19:14:08 Done here and elsewhere.
1942 DisableNativeProfileScope dnps;
1943 // We use the AlwaysInline and NeverInline annotations in this test.
1944 SetFlagScope<bool> sfs(&FLAG_enable_inlining_annotations, true);
1945 // Optimize quickly.
1946 SetFlagScope<int> sfs2(&FLAG_optimization_counter_threshold, 5);
1947
1948 const char* kScript =
1949 "const AlwaysInline = 'AlwaysInline';\n"
1950 "const NeverInline = 'NeverInline';\n"
1951 "class A {\n"
1952 " var a;\n"
1953 " var b;\n"
1954 " @NeverInline A() { }\n"
1955 "}\n"
1956 "class B {\n"
1957 " @NeverInline\n"
1958 " static oats() {\n"
1959 " return boo();\n"
1960 " }\n"
1961 " @AlwaysInline\n"
1962 " static boo() {\n"
1963 " return new A();\n"
1964 " }\n"
1965 "}\n"
1966 "class C {\n"
1967 " @NeverInline bacon() {\n"
1968 " return fox();\n"
1969 " }\n"
1970 " @AlwaysInline fox() {\n"
1971 " return B.oats();\n"
1972 " }\n"
1973 "}\n"
1974 "main() {\n"
1975 " new C()..bacon();\n"
1976 "}\n";
1977
1978 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
1979 EXPECT_VALID(lib);
1980 Library& root_library = Library::Handle();
1981 root_library ^= Api::UnwrapHandle(lib);
1982
1983 const Class& class_a = Class::Handle(GetClass(root_library, "A"));
1984 EXPECT(!class_a.IsNull());
1985
1986 const Function& main = Function::Handle(GetFunction(root_library, "main"));
1987 EXPECT(!main.IsNull());
1988
1989 // Warm up function.
1990 while (true) {
1991 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
1992 EXPECT_VALID(result);
1993 const Code& code = Code::Handle(main.CurrentCode());
1994 if (code.is_optimized()) {
1995 // Warmed up.
1996 break;
1997 }
1998 }
1999
2000 // Turn on allocation tracing for A.
2001 class_a.SetTraceAllocation(true);
2002
2003 // Allocate one time.
2004 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
2005 EXPECT_VALID(result);
2006
2007 // Still optimized.
2008 const Code& code = Code::Handle(main.CurrentCode());
2009 EXPECT(code.is_optimized());
2010
2011 {
2012 Thread* thread = Thread::Current();
2013 Isolate* isolate = thread->isolate();
2014 StackZone zone(thread);
2015 HANDLESCOPE(thread);
2016 Profile profile(isolate);
2017 AllocationFilter filter(isolate, class_a.id());
2018 profile.Build(thread, &filter, Profile::kNoTags);
2019 // We should have one allocation samples.
2020 EXPECT_EQ(1, profile.sample_count());
2021 ProfileTrieWalker walker(&profile);
2022
2023 // Exclusive function: B.boo -> main.
2024 walker.Reset(Profile::kExclusiveFunction);
2025 // Move down from the root.
2026 EXPECT(walker.Down());
2027 EXPECT_STREQ("B.boo", walker.CurrentName());
2028 EXPECT_EQ(1, walker.CurrentNodeTickCount());
2029 EXPECT_EQ(1, walker.CurrentInclusiveTicks());
2030 EXPECT_EQ(1, walker.CurrentExclusiveTicks());
2031 EXPECT_STREQ("A", walker.CurrentToken());
2032 EXPECT(walker.Down());
2033 EXPECT_STREQ("B.oats", walker.CurrentName());
2034 EXPECT_EQ(1, walker.CurrentNodeTickCount());
2035 EXPECT_EQ(1, walker.CurrentInclusiveTicks());
2036 EXPECT_EQ(0, walker.CurrentExclusiveTicks());
2037 EXPECT_STREQ("boo", walker.CurrentToken());
2038 EXPECT(walker.Down());
2039 EXPECT_STREQ("C.fox", walker.CurrentName());
2040 EXPECT_EQ(1, walker.CurrentNodeTickCount());
2041 EXPECT_EQ(1, walker.CurrentInclusiveTicks());
2042 EXPECT_EQ(0, walker.CurrentExclusiveTicks());
2043 EXPECT_STREQ("oats", walker.CurrentToken());
2044 EXPECT(walker.Down());
2045 EXPECT_STREQ("C.bacon", walker.CurrentName());
2046 EXPECT_EQ(1, walker.CurrentNodeTickCount());
2047 EXPECT_EQ(1, walker.CurrentInclusiveTicks());
2048 EXPECT_EQ(0, walker.CurrentExclusiveTicks());
2049 EXPECT_STREQ("fox", walker.CurrentToken());
2050 EXPECT(walker.Down());
2051 EXPECT_STREQ("main", walker.CurrentName());
2052 EXPECT_EQ(1, walker.CurrentNodeTickCount());
2053 EXPECT_EQ(1, walker.CurrentInclusiveTicks());
2054 EXPECT_EQ(0, walker.CurrentExclusiveTicks());
2055 EXPECT_STREQ("bacon", walker.CurrentToken());
2056 EXPECT(!walker.Down());
2057 }
2058 }
2059
2060
2061 TEST_CASE(Profiler_BinaryOperatorSourcePosition) {
2062 DisableNativeProfileScope dnps;
2063 const char* kScript =
2064 "const AlwaysInline = 'AlwaysInline';\n"
2065 "const NeverInline = 'NeverInline';\n"
2066 "class A {\n"
2067 " var a;\n"
2068 " var b;\n"
2069 " @NeverInline A() { }\n"
2070 "}\n"
2071 "class B {\n"
2072 " @NeverInline\n"
2073 " static oats() {\n"
2074 " return boo();\n"
2075 " }\n"
2076 " @AlwaysInline\n"
2077 " static boo() {\n"
2078 " return new A();\n"
2079 " }\n"
2080 "}\n"
2081 "class C {\n"
2082 " @NeverInline bacon() {\n"
2083 " return this + this;\n"
2084 " }\n"
2085 " @AlwaysInline operator+(C other) {\n"
2086 " return fox();\n"
2087 " }\n"
2088 " @AlwaysInline fox() {\n"
2089 " return B.oats();\n"
2090 " }\n"
2091 "}\n"
2092 "main() {\n"
2093 " new C()..bacon();\n"
2094 "}\n";
2095
2096 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
2097 EXPECT_VALID(lib);
2098 Library& root_library = Library::Handle();
2099 root_library ^= Api::UnwrapHandle(lib);
2100
2101 const Class& class_a = Class::Handle(GetClass(root_library, "A"));
2102 EXPECT(!class_a.IsNull());
2103
2104 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
2105 EXPECT_VALID(result);
2106
2107 // Turn on allocation tracing for A.
2108 class_a.SetTraceAllocation(true);
2109
2110 // Allocate one time.
2111 result = Dart_Invoke(lib, NewString("main"), 0, NULL);
2112 EXPECT_VALID(result);
2113
2114 {
2115 Thread* thread = Thread::Current();
2116 Isolate* isolate = thread->isolate();
2117 StackZone zone(thread);
2118 HANDLESCOPE(thread);
2119 Profile profile(isolate);
2120 AllocationFilter filter(isolate, class_a.id());
2121 profile.Build(thread, &filter, Profile::kNoTags);
2122 // We should have one allocation samples.
2123 EXPECT_EQ(1, profile.sample_count());
2124 ProfileTrieWalker walker(&profile);
2125
2126 // Exclusive function: B.boo -> main.
2127 walker.Reset(Profile::kExclusiveFunction);
2128 // Move down from the root.
2129 EXPECT(walker.Down());
2130 EXPECT_STREQ("B.boo", walker.CurrentName());
2131 EXPECT_EQ(1, walker.CurrentNodeTickCount());
2132 EXPECT_EQ(1, walker.CurrentInclusiveTicks());
2133 EXPECT_EQ(1, walker.CurrentExclusiveTicks());
2134 EXPECT_STREQ("A", walker.CurrentToken());
2135 EXPECT(walker.Down());
2136 EXPECT_STREQ("B.oats", walker.CurrentName());
2137 EXPECT_EQ(1, walker.CurrentNodeTickCount());
2138 EXPECT_EQ(1, walker.CurrentInclusiveTicks());
2139 EXPECT_EQ(0, walker.CurrentExclusiveTicks());
2140 EXPECT_STREQ("boo", walker.CurrentToken());
2141 EXPECT(walker.Down());
2142 EXPECT_STREQ("C.fox", walker.CurrentName());
2143 EXPECT_EQ(1, walker.CurrentNodeTickCount());
2144 EXPECT_EQ(1, walker.CurrentInclusiveTicks());
2145 EXPECT_EQ(0, walker.CurrentExclusiveTicks());
2146 EXPECT_STREQ("oats", walker.CurrentToken());
2147 EXPECT(walker.Down());
2148 EXPECT_STREQ("C.+", walker.CurrentName());
2149 EXPECT_EQ(1, walker.CurrentNodeTickCount());
2150 EXPECT_EQ(1, walker.CurrentInclusiveTicks());
2151 EXPECT_EQ(0, walker.CurrentExclusiveTicks());
2152 EXPECT_STREQ("fox", walker.CurrentToken());
2153 EXPECT(walker.Down());
2154 EXPECT_STREQ("C.bacon", walker.CurrentName());
2155 EXPECT_EQ(1, walker.CurrentNodeTickCount());
2156 EXPECT_EQ(1, walker.CurrentInclusiveTicks());
2157 EXPECT_EQ(0, walker.CurrentExclusiveTicks());
2158 EXPECT_STREQ("+", walker.CurrentToken());
2159 EXPECT(walker.Down());
2160 EXPECT_STREQ("main", walker.CurrentName());
2161 EXPECT_EQ(1, walker.CurrentNodeTickCount());
2162 EXPECT_EQ(1, walker.CurrentInclusiveTicks());
2163 EXPECT_EQ(0, walker.CurrentExclusiveTicks());
2164 EXPECT_STREQ("bacon", walker.CurrentToken());
2165 EXPECT(!walker.Down());
2166 }
2167 }
2168
2169
2170 TEST_CASE(Profiler_BinaryOperatorSourcePositionOptimized) {
srdjan 2016/03/02 19:02:56 Disable background compilation
2171 DisableNativeProfileScope dnps;
2172 // We use the AlwaysInline and NeverInline annotations in this test.
2173 SetFlagScope<bool> sfs(&FLAG_enable_inlining_annotations, true);
2174 // Optimize quickly.
2175 SetFlagScope<int> sfs2(&FLAG_optimization_counter_threshold, 5);
2176
2177 const char* kScript =
2178 "const AlwaysInline = 'AlwaysInline';\n"
2179 "const NeverInline = 'NeverInline';\n"
2180 "class A {\n"
2181 " var a;\n"
2182 " var b;\n"
2183 " @NeverInline A() { }\n"
2184 "}\n"
2185 "class B {\n"
2186 " @NeverInline\n"
2187 " static oats() {\n"
2188 " return boo();\n"
2189 " }\n"
2190 " @AlwaysInline\n"
2191 " static boo() {\n"
2192 " return new A();\n"
2193 " }\n"
2194 "}\n"
2195 "class C {\n"
2196 " @NeverInline bacon() {\n"
2197 " return this + this;\n"
2198 " }\n"
2199 " @AlwaysInline operator+(C other) {\n"
2200 " return fox();\n"
2201 " }\n"
2202 " @AlwaysInline fox() {\n"
2203 " return B.oats();\n"
2204 " }\n"
2205 "}\n"
2206 "main() {\n"
2207 " new C()..bacon();\n"
2208 "}\n";
2209
2210 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
2211 EXPECT_VALID(lib);
2212 Library& root_library = Library::Handle();
2213 root_library ^= Api::UnwrapHandle(lib);
2214
2215 const Class& class_a = Class::Handle(GetClass(root_library, "A"));
2216 EXPECT(!class_a.IsNull());
2217
2218 const Function& main = Function::Handle(GetFunction(root_library, "main"));
2219 EXPECT(!main.IsNull());
2220
2221 // Warm up function.
2222 while (true) {
2223 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
2224 EXPECT_VALID(result);
2225 const Code& code = Code::Handle(main.CurrentCode());
2226 if (code.is_optimized()) {
2227 // Warmed up.
2228 break;
2229 }
2230 }
2231
2232 // Turn on allocation tracing for A.
2233 class_a.SetTraceAllocation(true);
2234
2235 // Allocate one time.
2236 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
2237 EXPECT_VALID(result);
2238
2239 // Still optimized.
2240 const Code& code = Code::Handle(main.CurrentCode());
2241 EXPECT(code.is_optimized());
2242
2243 {
2244 Thread* thread = Thread::Current();
2245 Isolate* isolate = thread->isolate();
2246 StackZone zone(thread);
2247 HANDLESCOPE(thread);
2248 Profile profile(isolate);
2249 AllocationFilter filter(isolate, class_a.id());
2250 profile.Build(thread, &filter, Profile::kNoTags);
2251 // We should have one allocation samples.
2252 EXPECT_EQ(1, profile.sample_count());
2253 ProfileTrieWalker walker(&profile);
2254
2255 // Exclusive function: B.boo -> main.
2256 walker.Reset(Profile::kExclusiveFunction);
2257 // Move down from the root.
2258 EXPECT(walker.Down());
2259 EXPECT_STREQ("B.boo", walker.CurrentName());
2260 EXPECT_EQ(1, walker.CurrentNodeTickCount());
2261 EXPECT_EQ(1, walker.CurrentInclusiveTicks());
2262 EXPECT_EQ(1, walker.CurrentExclusiveTicks());
2263 EXPECT_STREQ("A", walker.CurrentToken());
2264 EXPECT(walker.Down());
2265 EXPECT_STREQ("B.oats", walker.CurrentName());
2266 EXPECT_EQ(1, walker.CurrentNodeTickCount());
2267 EXPECT_EQ(1, walker.CurrentInclusiveTicks());
2268 EXPECT_EQ(0, walker.CurrentExclusiveTicks());
2269 EXPECT_STREQ("boo", walker.CurrentToken());
2270 EXPECT(walker.Down());
2271 EXPECT_STREQ("C.fox", walker.CurrentName());
2272 EXPECT_EQ(1, walker.CurrentNodeTickCount());
2273 EXPECT_EQ(1, walker.CurrentInclusiveTicks());
2274 EXPECT_EQ(0, walker.CurrentExclusiveTicks());
2275 EXPECT_STREQ("oats", walker.CurrentToken());
2276 EXPECT(walker.Down());
2277 EXPECT_STREQ("C.+", walker.CurrentName());
2278 EXPECT_EQ(1, walker.CurrentNodeTickCount());
2279 EXPECT_EQ(1, walker.CurrentInclusiveTicks());
2280 EXPECT_EQ(0, walker.CurrentExclusiveTicks());
2281 EXPECT_STREQ("fox", walker.CurrentToken());
2282 EXPECT(walker.Down());
2283 EXPECT_STREQ("C.bacon", walker.CurrentName());
2284 EXPECT_EQ(1, walker.CurrentNodeTickCount());
2285 EXPECT_EQ(1, walker.CurrentInclusiveTicks());
2286 EXPECT_EQ(0, walker.CurrentExclusiveTicks());
2287 EXPECT_STREQ("+", walker.CurrentToken());
2288 EXPECT(walker.Down());
2289 EXPECT_STREQ("main", walker.CurrentName());
2290 EXPECT_EQ(1, walker.CurrentNodeTickCount());
2291 EXPECT_EQ(1, walker.CurrentInclusiveTicks());
2292 EXPECT_EQ(0, walker.CurrentExclusiveTicks());
2293 EXPECT_STREQ("bacon", walker.CurrentToken());
2294 EXPECT(!walker.Down());
2295 }
2296 }
2297
1661 #endif // !PRODUCT 2298 #endif // !PRODUCT
1662 2299
1663 } // namespace dart 2300 } // namespace dart
OLDNEW
« runtime/vm/profiler_service.h ('K') | « runtime/vm/profiler_service.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698