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/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 Loading... | |
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 |
OLD | NEW |