OLD | NEW |
---|---|
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
49 using i::SmartPointer; | 49 using i::SmartPointer; |
50 using i::Vector; | 50 using i::Vector; |
51 | 51 |
52 | 52 |
53 // Helper methods | 53 // Helper methods |
54 static v8::Local<v8::Function> GetFunction(v8::Context* env, const char* name) { | 54 static v8::Local<v8::Function> GetFunction(v8::Context* env, const char* name) { |
55 return v8::Local<v8::Function>::Cast(env->Global()->Get(v8_str(name))); | 55 return v8::Local<v8::Function>::Cast(env->Global()->Get(v8_str(name))); |
56 } | 56 } |
57 | 57 |
58 | 58 |
59 static int offset(const char* src, const char* substring) { | |
60 return static_cast<int>(strstr(src, substring) - src); | |
61 } | |
62 | |
63 | |
59 static const char* reason(const i::Deoptimizer::DeoptReason reason) { | 64 static const char* reason(const i::Deoptimizer::DeoptReason reason) { |
60 return i::Deoptimizer::GetDeoptReason(reason); | 65 return i::Deoptimizer::GetDeoptReason(reason); |
61 } | 66 } |
62 | 67 |
63 | 68 |
64 TEST(StartStop) { | 69 TEST(StartStop) { |
65 i::Isolate* isolate = CcTest::i_isolate(); | 70 i::Isolate* isolate = CcTest::i_isolate(); |
66 CpuProfilesCollection profiles(isolate->heap()); | 71 CpuProfilesCollection profiles(isolate->heap()); |
67 ProfileGenerator generator(&profiles); | 72 ProfileGenerator generator(&profiles); |
68 SmartPointer<ProfilerEventsProcessor> processor(new ProfilerEventsProcessor( | 73 SmartPointer<ProfilerEventsProcessor> processor(new ProfilerEventsProcessor( |
(...skipping 1638 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1707 outer_profile = NULL; | 1712 outer_profile = NULL; |
1708 CHECK_EQ(0, iprofiler->GetProfilesCount()); | 1713 CHECK_EQ(0, iprofiler->GetProfilesCount()); |
1709 } | 1714 } |
1710 | 1715 |
1711 | 1716 |
1712 const char* GetBranchDeoptReason(i::CpuProfile* iprofile, const char* branch[], | 1717 const char* GetBranchDeoptReason(i::CpuProfile* iprofile, const char* branch[], |
1713 int length) { | 1718 int length) { |
1714 v8::CpuProfile* profile = reinterpret_cast<v8::CpuProfile*>(iprofile); | 1719 v8::CpuProfile* profile = reinterpret_cast<v8::CpuProfile*>(iprofile); |
1715 const ProfileNode* iopt_function = NULL; | 1720 const ProfileNode* iopt_function = NULL; |
1716 iopt_function = GetSimpleBranch(profile, branch, length); | 1721 iopt_function = GetSimpleBranch(profile, branch, length); |
1717 CHECK_EQ(1, iopt_function->deopt_infos().length()); | 1722 CHECK_EQ(1, iopt_function->deopt_infos().size()); |
1718 return iopt_function->deopt_infos()[0].deopt_reason; | 1723 return iopt_function->deopt_infos()[0]->deopt_reason; |
1719 } | 1724 } |
1720 | 1725 |
1721 | 1726 |
1722 // deopt at top function | 1727 // deopt at top function |
1723 TEST(CollectDeoptEvents) { | 1728 TEST(CollectDeoptEvents) { |
1724 if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return; | 1729 if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return; |
1725 i::FLAG_allow_natives_syntax = true; | 1730 i::FLAG_allow_natives_syntax = true; |
1726 v8::HandleScope scope(CcTest::isolate()); | 1731 v8::HandleScope scope(CcTest::isolate()); |
1727 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); | 1732 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); |
1728 v8::Context::Scope context_scope(env); | 1733 v8::Context::Scope context_scope(env); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1770 "opt_function2(1, 1);\n" | 1775 "opt_function2(1, 1);\n" |
1771 "\n" | 1776 "\n" |
1772 "opt_function2(0, 1);\n" | 1777 "opt_function2(0, 1);\n" |
1773 "\n" | 1778 "\n" |
1774 "stopProfiling();\n" | 1779 "stopProfiling();\n" |
1775 "\n"; | 1780 "\n"; |
1776 | 1781 |
1777 v8::Script::Compile(v8_str(source))->Run(); | 1782 v8::Script::Compile(v8_str(source))->Run(); |
1778 i::CpuProfile* iprofile = iprofiler->GetProfile(0); | 1783 i::CpuProfile* iprofile = iprofiler->GetProfile(0); |
1779 iprofile->Print(); | 1784 iprofile->Print(); |
1785 /* The expected profile | |
1786 [Top down]: | |
1787 0 (root) 0 #1 | |
1788 23 32 #2 | |
1789 1 opt_function2 31 #7 | |
1790 1 opt_function2 31 #8 | |
1791 ;;; deopted at script_id: 31 position: 106 with reason | |
1792 'division by zero'. | |
1793 2 opt_function0 29 #3 | |
1794 4 opt_function0 29 #4 | |
1795 ;;; deopted at script_id: 29 position: 108 with reason 'not a | |
1796 heap number'. | |
1797 0 opt_function1 30 #5 | |
1798 1 opt_function1 30 #6 | |
1799 ;;; deopted at script_id: 30 position: 108 with reason 'lost | |
1800 precision or NaN'. | |
1801 */ | |
1802 | |
1780 { | 1803 { |
1781 const char* branch[] = {"", "opt_function0", "opt_function0"}; | 1804 const char* branch[] = {"", "opt_function0", "opt_function0"}; |
1782 CHECK_EQ(reason(i::Deoptimizer::kNotAHeapNumber), | 1805 CHECK_EQ(reason(i::Deoptimizer::kNotAHeapNumber), |
1783 GetBranchDeoptReason(iprofile, branch, arraysize(branch))); | 1806 GetBranchDeoptReason(iprofile, branch, arraysize(branch))); |
1784 } | 1807 } |
1785 { | 1808 { |
1786 const char* branch[] = {"", "opt_function1", "opt_function1"}; | 1809 const char* branch[] = {"", "opt_function1", "opt_function1"}; |
1787 const char* deopt_reason = | 1810 const char* deopt_reason = |
1788 GetBranchDeoptReason(iprofile, branch, arraysize(branch)); | 1811 GetBranchDeoptReason(iprofile, branch, arraysize(branch)); |
1789 if (deopt_reason != reason(i::Deoptimizer::kNaN) && | 1812 if (deopt_reason != reason(i::Deoptimizer::kNaN) && |
(...skipping 17 matching lines...) Expand all Loading... | |
1807 v8::HandleScope scope(CcTest::isolate()); | 1830 v8::HandleScope scope(CcTest::isolate()); |
1808 | 1831 |
1809 const char* source = | 1832 const char* source = |
1810 "function CompareStatementWithThis() {\n" | 1833 "function CompareStatementWithThis() {\n" |
1811 " if (this === 1) {}\n" | 1834 " if (this === 1) {}\n" |
1812 "}\n" | 1835 "}\n" |
1813 "CompareStatementWithThis();\n"; | 1836 "CompareStatementWithThis();\n"; |
1814 | 1837 |
1815 v8::Script::Compile(v8_str(source))->Run(); | 1838 v8::Script::Compile(v8_str(source))->Run(); |
1816 } | 1839 } |
1840 | |
1841 | |
1842 static const char* inlined_source = | |
1843 "function opt_function(left, right) { var k = left / 10; var r = 10 / " | |
1844 "right; return k + r; }\n"; | |
1845 // 0.........1.........2.........3.........4....*....5.........6......*..7 | |
1846 | |
1847 | |
1848 // deopt at the first level inlined function | |
1849 TEST(DeoptAtFirstLevelInlinedSource) { | |
1850 if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return; | |
1851 i::FLAG_allow_natives_syntax = true; | |
1852 v8::HandleScope scope(CcTest::isolate()); | |
1853 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); | |
1854 v8::Context::Scope context_scope(env); | |
1855 v8::Isolate* isolate = env->GetIsolate(); | |
1856 v8::CpuProfiler* profiler = isolate->GetCpuProfiler(); | |
1857 i::CpuProfiler* iprofiler = reinterpret_cast<i::CpuProfiler*>(profiler); | |
1858 | |
1859 // 0.........1.........2.........3.........4.........5.........6.........7 | |
alph
2015/03/20 08:28:43
nit: shifted a bit
loislo
2015/03/20 08:53:12
done
| |
1860 const char* source = | |
1861 "function test(left, right) { return opt_function(left, right); }\n" | |
1862 "\n" | |
1863 "startProfiling();\n" | |
1864 "\n" | |
1865 "test(10, 10);\n" | |
1866 "\n" | |
1867 "%OptimizeFunctionOnNextCall(test)\n" | |
1868 "\n" | |
1869 "test(10, 10);\n" | |
1870 "\n" | |
1871 "test(undefined, 10);\n" | |
1872 "\n" | |
1873 "stopProfiling();\n" | |
1874 "\n"; | |
1875 | |
1876 v8::Handle<v8::Script> inlined_script = v8_compile(inlined_source); | |
1877 inlined_script->Run(); | |
1878 int inlined_script_id = inlined_script->GetUnboundScript()->GetId(); | |
1879 | |
1880 v8::Handle<v8::Script> script = v8_compile(source); | |
1881 script->Run(); | |
1882 int script_id = script->GetUnboundScript()->GetId(); | |
1883 | |
1884 i::CpuProfile* iprofile = iprofiler->GetProfile(0); | |
1885 iprofile->Print(); | |
1886 /* The expected profile output | |
1887 [Top down]: | |
1888 0 (root) 0 #1 | |
1889 10 30 #2 | |
1890 1 test 30 #3 | |
1891 ;;; deopted at script_id: 29 position: 45 with reason 'not a | |
1892 heap number'. | |
1893 ;;; Inline point: script_id 30 position: 36. | |
1894 4 opt_function 29 #4 | |
1895 */ | |
1896 v8::CpuProfile* profile = reinterpret_cast<v8::CpuProfile*>(iprofile); | |
1897 | |
1898 const char* branch[] = {"", "test"}; | |
1899 const ProfileNode* itest_node = | |
1900 GetSimpleBranch(profile, branch, arraysize(branch)); | |
1901 const std::vector<i::DeoptInfo*>& deopt_infos = itest_node->deopt_infos(); | |
1902 CHECK_EQ(1, deopt_infos.size()); | |
1903 | |
1904 const i::DeoptInfo* info0 = deopt_infos[0]; | |
1905 CHECK_EQ(reason(i::Deoptimizer::kNotAHeapNumber), info0->deopt_reason); | |
1906 CHECK_EQ(2, info0->stack.size()); | |
1907 CHECK_EQ(inlined_script_id, info0->stack[0].script_id); | |
1908 CHECK_EQ(offset(inlined_source, "left /"), info0->stack[0].position); | |
1909 CHECK_EQ(script_id, info0->stack[1].script_id); | |
1910 CHECK_EQ(offset(source, "opt_function(left,"), info0->stack[1].position); | |
1911 | |
1912 iprofiler->DeleteProfile(iprofile); | |
1913 } | |
1914 | |
1915 | |
1916 // deopt at the second level inlined function | |
1917 TEST(DeoptAtSecondLevelInlinedSource) { | |
1918 if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return; | |
1919 i::FLAG_allow_natives_syntax = true; | |
1920 v8::HandleScope scope(CcTest::isolate()); | |
1921 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); | |
1922 v8::Context::Scope context_scope(env); | |
1923 v8::Isolate* isolate = env->GetIsolate(); | |
1924 v8::CpuProfiler* profiler = isolate->GetCpuProfiler(); | |
1925 i::CpuProfiler* iprofiler = reinterpret_cast<i::CpuProfiler*>(profiler); | |
1926 | |
1927 // 0.........1.........2.........3.........4.........5.........6.........7 | |
alph
2015/03/20 08:28:43
ditto
loislo
2015/03/20 08:53:12
done
| |
1928 const char* source = | |
1929 "function test2(left, right) { return opt_function(left, right); }\n" | |
1930 "function test1(left, right) { return test2(left, right); }\n" | |
1931 "\n" | |
1932 "startProfiling();\n" | |
1933 "\n" | |
1934 "test1(10, 10);\n" | |
1935 "\n" | |
1936 "%OptimizeFunctionOnNextCall(test1)\n" | |
1937 "\n" | |
1938 "test1(10, 10);\n" | |
1939 "\n" | |
1940 "test1(undefined, 10);\n" | |
1941 "\n" | |
1942 "stopProfiling();\n" | |
1943 "\n"; | |
1944 | |
1945 v8::Handle<v8::Script> inlined_script = v8_compile(inlined_source); | |
1946 inlined_script->Run(); | |
1947 int inlined_script_id = inlined_script->GetUnboundScript()->GetId(); | |
1948 | |
1949 v8::Handle<v8::Script> script = v8_compile(source); | |
1950 script->Run(); | |
1951 int script_id = script->GetUnboundScript()->GetId(); | |
1952 | |
1953 i::CpuProfile* iprofile = iprofiler->GetProfile(0); | |
1954 iprofile->Print(); | |
1955 /* The expected profile output | |
1956 [Top down]: | |
1957 0 (root) 0 #1 | |
1958 11 30 #2 | |
1959 1 test1 30 #3 | |
1960 ;;; deopted at script_id: 29 position: 45 with reason 'not a | |
1961 heap number'. | |
1962 ;;; Inline point: script_id 30 position: 37. | |
1963 ;;; Inline point: script_id 30 position: 103. | |
1964 1 test2 30 #4 | |
1965 3 opt_function 29 #5 | |
1966 */ | |
1967 | |
1968 v8::CpuProfile* profile = reinterpret_cast<v8::CpuProfile*>(iprofile); | |
1969 | |
1970 const char* branch[] = {"", "test1"}; | |
1971 const ProfileNode* itest_node = | |
1972 GetSimpleBranch(profile, branch, arraysize(branch)); | |
1973 const std::vector<i::DeoptInfo*>& deopt_infos = itest_node->deopt_infos(); | |
1974 CHECK_EQ(1, deopt_infos.size()); | |
1975 | |
1976 const i::DeoptInfo* info0 = deopt_infos[0]; | |
1977 CHECK_EQ(reason(i::Deoptimizer::kNotAHeapNumber), info0->deopt_reason); | |
1978 CHECK_EQ(3, info0->stack.size()); | |
1979 CHECK_EQ(inlined_script_id, info0->stack[0].script_id); | |
1980 CHECK_EQ(offset(inlined_source, "left /"), info0->stack[0].position); | |
1981 CHECK_EQ(script_id, info0->stack[1].script_id); | |
1982 CHECK_EQ(offset(source, "opt_function(left,"), info0->stack[1].position); | |
1983 CHECK_EQ(offset(source, "test2(left, right);"), info0->stack[2].position); | |
1984 | |
1985 iprofiler->DeleteProfile(iprofile); | |
1986 } | |
1987 | |
1988 | |
1989 // deopt in untracked function | |
1990 TEST(DeoptUntrackedFunction) { | |
1991 if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return; | |
1992 i::FLAG_allow_natives_syntax = true; | |
1993 v8::HandleScope scope(CcTest::isolate()); | |
1994 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); | |
1995 v8::Context::Scope context_scope(env); | |
1996 v8::Isolate* isolate = env->GetIsolate(); | |
1997 v8::CpuProfiler* profiler = isolate->GetCpuProfiler(); | |
1998 i::CpuProfiler* iprofiler = reinterpret_cast<i::CpuProfiler*>(profiler); | |
1999 | |
2000 // 0.........1.........2.........3.........4.........5.........6.........7 | |
2001 const char* source = | |
2002 "function test(left, right) { return opt_function(left, right); }\n" | |
2003 "\n" | |
2004 "test(10, 10);\n" | |
2005 "\n" | |
2006 "%OptimizeFunctionOnNextCall(test)\n" | |
2007 "\n" | |
2008 "test(10, 10);\n" | |
2009 "\n" | |
2010 "startProfiling();\n" // profiler started after compilation. | |
2011 "\n" | |
2012 "test(undefined, 10);\n" | |
2013 "\n" | |
2014 "stopProfiling();\n" | |
2015 "\n"; | |
2016 | |
2017 v8::Handle<v8::Script> inlined_script = v8_compile(inlined_source); | |
2018 inlined_script->Run(); | |
2019 | |
2020 v8::Handle<v8::Script> script = v8_compile(source); | |
2021 script->Run(); | |
2022 | |
2023 i::CpuProfile* iprofile = iprofiler->GetProfile(0); | |
2024 iprofile->Print(); | |
2025 v8::CpuProfile* profile = reinterpret_cast<v8::CpuProfile*>(iprofile); | |
2026 | |
2027 const char* branch[] = {"", "test"}; | |
2028 const ProfileNode* itest_node = | |
2029 GetSimpleBranch(profile, branch, arraysize(branch)); | |
2030 CHECK_EQ(0, itest_node->deopt_infos().size()); | |
2031 | |
2032 iprofiler->DeleteProfile(iprofile); | |
2033 } | |
OLD | NEW |