OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 1820 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1831 | 1831 |
1832 Sampler* sampler_; | 1832 Sampler* sampler_; |
1833 HANDLE sampler_thread_; | 1833 HANDLE sampler_thread_; |
1834 HANDLE profiled_thread_; | 1834 HANDLE profiled_thread_; |
1835 | 1835 |
1836 // Sampler thread handler. | 1836 // Sampler thread handler. |
1837 void Runner() { | 1837 void Runner() { |
1838 // Context used for sampling the register state of the profiled thread. | 1838 // Context used for sampling the register state of the profiled thread. |
1839 CONTEXT context; | 1839 CONTEXT context; |
1840 memset(&context, 0, sizeof(context)); | 1840 memset(&context, 0, sizeof(context)); |
1841 // Loop until the sampler is disengaged, keeping the specified samling freq. | 1841 // Loop until the sampler is disengaged, keeping the specified |
| 1842 // sampling frequency. |
1842 for ( ; sampler_->IsActive(); Sleep(sampler_->interval_)) { | 1843 for ( ; sampler_->IsActive(); Sleep(sampler_->interval_)) { |
1843 TickSample sample_obj; | 1844 TickSample sample_obj; |
1844 TickSample* sample = CpuProfiler::TickSampleEvent(); | 1845 TickSample* sample = CpuProfiler::TickSampleEvent(); |
1845 if (sample == NULL) sample = &sample_obj; | 1846 if (sample == NULL) sample = &sample_obj; |
1846 | 1847 |
| 1848 // If the sampler runs in sync with the JS thread, we try to |
| 1849 // suspend it. If we fail, we skip the current sample. |
| 1850 if (sampler_->IsSynchronous()) { |
| 1851 static const DWORD kSuspendFailed = static_cast<DWORD>(-1); |
| 1852 if (SuspendThread(profiled_thread_) == kSuspendFailed) continue; |
| 1853 } |
| 1854 |
1847 // We always sample the VM state. | 1855 // We always sample the VM state. |
1848 sample->state = VMState::current_state(); | 1856 sample->state = VMState::current_state(); |
| 1857 |
1849 // If profiling, we record the pc and sp of the profiled thread. | 1858 // If profiling, we record the pc and sp of the profiled thread. |
1850 if (sampler_->IsProfiling() | 1859 if (sampler_->IsProfiling()) { |
1851 && SuspendThread(profiled_thread_) != (DWORD)-1) { | |
1852 context.ContextFlags = CONTEXT_FULL; | 1860 context.ContextFlags = CONTEXT_FULL; |
1853 if (GetThreadContext(profiled_thread_, &context) != 0) { | 1861 if (GetThreadContext(profiled_thread_, &context) != 0) { |
1854 #if V8_HOST_ARCH_X64 | 1862 #if V8_HOST_ARCH_X64 |
1855 sample->pc = reinterpret_cast<Address>(context.Rip); | 1863 sample->pc = reinterpret_cast<Address>(context.Rip); |
1856 sample->sp = reinterpret_cast<Address>(context.Rsp); | 1864 sample->sp = reinterpret_cast<Address>(context.Rsp); |
1857 sample->fp = reinterpret_cast<Address>(context.Rbp); | 1865 sample->fp = reinterpret_cast<Address>(context.Rbp); |
1858 #else | 1866 #else |
1859 sample->pc = reinterpret_cast<Address>(context.Eip); | 1867 sample->pc = reinterpret_cast<Address>(context.Eip); |
1860 sample->sp = reinterpret_cast<Address>(context.Esp); | 1868 sample->sp = reinterpret_cast<Address>(context.Esp); |
1861 sample->fp = reinterpret_cast<Address>(context.Ebp); | 1869 sample->fp = reinterpret_cast<Address>(context.Ebp); |
1862 #endif | 1870 #endif |
1863 sampler_->SampleStack(sample); | 1871 sampler_->SampleStack(sample); |
1864 } | 1872 } |
1865 ResumeThread(profiled_thread_); | |
1866 } | 1873 } |
1867 | 1874 |
1868 // Invoke tick handler with program counter and stack pointer. | 1875 // Invoke tick handler with program counter and stack pointer. |
1869 sampler_->Tick(sample); | 1876 sampler_->Tick(sample); |
| 1877 |
| 1878 // If the sampler runs in sync with the JS thread, we have to |
| 1879 // remember to resume it. |
| 1880 if (sampler_->IsSynchronous()) ResumeThread(profiled_thread_); |
1870 } | 1881 } |
1871 } | 1882 } |
1872 }; | 1883 }; |
1873 | 1884 |
1874 | 1885 |
1875 // Entry point for sampler thread. | 1886 // Entry point for sampler thread. |
1876 static unsigned int __stdcall SamplerEntry(void* arg) { | 1887 static unsigned int __stdcall SamplerEntry(void* arg) { |
1877 Sampler::PlatformData* data = | 1888 Sampler::PlatformData* data = |
1878 reinterpret_cast<Sampler::PlatformData*>(arg); | 1889 reinterpret_cast<Sampler::PlatformData*>(arg); |
1879 data->Runner(); | 1890 data->Runner(); |
1880 return 0; | 1891 return 0; |
1881 } | 1892 } |
1882 | 1893 |
1883 | 1894 |
1884 // Initialize a profile sampler. | 1895 // Initialize a profile sampler. |
1885 Sampler::Sampler(int interval, bool profiling) | 1896 Sampler::Sampler(int interval, bool profiling) |
1886 : interval_(interval), profiling_(profiling), active_(false) { | 1897 : interval_(interval), |
| 1898 profiling_(profiling), |
| 1899 synchronous_(profiling), |
| 1900 active_(false) { |
1887 data_ = new PlatformData(this); | 1901 data_ = new PlatformData(this); |
1888 } | 1902 } |
1889 | 1903 |
1890 | 1904 |
1891 Sampler::~Sampler() { | 1905 Sampler::~Sampler() { |
1892 delete data_; | 1906 delete data_; |
1893 } | 1907 } |
1894 | 1908 |
1895 | 1909 |
1896 // Start profiling. | 1910 // Start profiling. |
1897 void Sampler::Start() { | 1911 void Sampler::Start() { |
1898 // If we are profiling, we need to be able to access the calling | 1912 // If we are starting a synchronous sampler, we need to be able to |
1899 // thread. | 1913 // access the calling thread. |
1900 if (IsProfiling()) { | 1914 if (IsSynchronous()) { |
1901 // Get a handle to the calling thread. This is the thread that we are | 1915 // Get a handle to the calling thread. This is the thread that we are |
1902 // going to profile. We need to make a copy of the handle because we are | 1916 // going to profile. We need to make a copy of the handle because we are |
1903 // going to use it in the sampler thread. Using GetThreadHandle() will | 1917 // going to use it in the sampler thread. Using GetThreadHandle() will |
1904 // not work in this case. We're using OpenThread because DuplicateHandle | 1918 // not work in this case. We're using OpenThread because DuplicateHandle |
1905 // for some reason doesn't work in Chrome's sandbox. | 1919 // for some reason doesn't work in Chrome's sandbox. |
1906 data_->profiled_thread_ = OpenThread(THREAD_GET_CONTEXT | | 1920 data_->profiled_thread_ = OpenThread(THREAD_GET_CONTEXT | |
1907 THREAD_SUSPEND_RESUME | | 1921 THREAD_SUSPEND_RESUME | |
1908 THREAD_QUERY_INFORMATION, | 1922 THREAD_QUERY_INFORMATION, |
1909 FALSE, | 1923 FALSE, |
1910 GetCurrentThreadId()); | 1924 GetCurrentThreadId()); |
(...skipping 22 matching lines...) Expand all Loading... |
1933 | 1947 |
1934 // Release the thread handles | 1948 // Release the thread handles |
1935 CloseHandle(data_->sampler_thread_); | 1949 CloseHandle(data_->sampler_thread_); |
1936 CloseHandle(data_->profiled_thread_); | 1950 CloseHandle(data_->profiled_thread_); |
1937 } | 1951 } |
1938 | 1952 |
1939 | 1953 |
1940 #endif // ENABLE_LOGGING_AND_PROFILING | 1954 #endif // ENABLE_LOGGING_AND_PROFILING |
1941 | 1955 |
1942 } } // namespace v8::internal | 1956 } } // namespace v8::internal |
OLD | NEW |