OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 1950 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1961 uint32_t Socket::NToH(uint32_t value) { | 1961 uint32_t Socket::NToH(uint32_t value) { |
1962 return ntohl(value); | 1962 return ntohl(value); |
1963 } | 1963 } |
1964 | 1964 |
1965 | 1965 |
1966 Socket* OS::CreateSocket() { | 1966 Socket* OS::CreateSocket() { |
1967 return new Win32Socket(); | 1967 return new Win32Socket(); |
1968 } | 1968 } |
1969 | 1969 |
1970 | 1970 |
1971 // ---------------------------------------------------------------------------- | |
1972 // Win32 profiler support. | |
1973 | |
1974 class Sampler::PlatformData : public Malloced { | |
1975 public: | |
1976 // Get a handle to the calling thread. This is the thread that we are | |
1977 // going to profile. We need to make a copy of the handle because we are | |
1978 // going to use it in the sampler thread. Using GetThreadHandle() will | |
1979 // not work in this case. We're using OpenThread because DuplicateHandle | |
1980 // for some reason doesn't work in Chrome's sandbox. | |
1981 PlatformData() | |
1982 : profiled_thread_(OpenThread(THREAD_GET_CONTEXT | | |
1983 THREAD_SUSPEND_RESUME | | |
1984 THREAD_QUERY_INFORMATION, | |
1985 false, | |
1986 GetCurrentThreadId())), | |
1987 profiled_thread_id_(ThreadId::Current()) {} | |
1988 | |
1989 ~PlatformData() { | |
1990 if (profiled_thread_ != NULL) { | |
1991 CloseHandle(profiled_thread_); | |
1992 profiled_thread_ = NULL; | |
1993 } | |
1994 } | |
1995 | |
1996 HANDLE profiled_thread() { return profiled_thread_; } | |
1997 ThreadId profiled_thread_id() { return profiled_thread_id_; } | |
1998 | |
1999 private: | |
2000 HANDLE profiled_thread_; | |
2001 ThreadId profiled_thread_id_; | |
2002 }; | |
2003 | |
2004 | |
2005 class SamplerThread : public Thread { | |
2006 public: | |
2007 static const int kSamplerThreadStackSize = 64 * KB; | |
2008 | |
2009 explicit SamplerThread(int interval) | |
2010 : Thread(Thread::Options("SamplerThread", kSamplerThreadStackSize)), | |
2011 interval_(interval) {} | |
2012 | |
2013 static void SetUp() { if (!mutex_) mutex_ = OS::CreateMutex(); } | |
2014 static void TearDown() { delete mutex_; } | |
2015 | |
2016 static void AddActiveSampler(Sampler* sampler) { | |
2017 ScopedLock lock(mutex_); | |
2018 SamplerRegistry::AddActiveSampler(sampler); | |
2019 if (instance_ == NULL) { | |
2020 instance_ = new SamplerThread(sampler->interval()); | |
2021 instance_->StartSynchronously(); | |
2022 } else { | |
2023 ASSERT(instance_->interval_ == sampler->interval()); | |
2024 } | |
2025 } | |
2026 | |
2027 static void RemoveActiveSampler(Sampler* sampler) { | |
2028 ScopedLock lock(mutex_); | |
2029 SamplerRegistry::RemoveActiveSampler(sampler); | |
2030 if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) { | |
2031 instance_->Join(); | |
2032 delete instance_; | |
2033 instance_ = NULL; | |
2034 } | |
2035 } | |
2036 | |
2037 // Implement Thread::Run(). | |
2038 virtual void Run() { | |
2039 SamplerRegistry::State state; | |
2040 while ((state = SamplerRegistry::GetState()) != | |
2041 SamplerRegistry::HAS_NO_SAMPLERS) { | |
2042 // When CPU profiling is enabled both JavaScript and C++ code is | |
2043 // profiled. We must not suspend. | |
2044 if (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS) { | |
2045 SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this); | |
2046 } | |
2047 OS::Sleep(interval_); | |
2048 } | |
2049 } | |
2050 | |
2051 static void DoCpuProfile(Sampler* sampler, void* raw_sampler_thread) { | |
2052 if (!sampler->isolate()->IsInitialized()) return; | |
2053 if (!sampler->IsProfiling()) return; | |
2054 SamplerThread* sampler_thread = | |
2055 reinterpret_cast<SamplerThread*>(raw_sampler_thread); | |
2056 sampler_thread->SampleContext(sampler); | |
2057 } | |
2058 | |
2059 void SampleContext(Sampler* sampler) { | |
2060 HANDLE profiled_thread = sampler->platform_data()->profiled_thread(); | |
2061 if (profiled_thread == NULL) return; | |
2062 | |
2063 // Context used for sampling the register state of the profiled thread. | |
2064 CONTEXT context; | |
2065 memset(&context, 0, sizeof(context)); | |
2066 | |
2067 Isolate* isolate = sampler->isolate(); | |
2068 #if defined(USE_SIMULATOR) | |
2069 #if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS | |
2070 ThreadId thread_id = sampler->platform_data()->profiled_thread_id(); | |
2071 Isolate::PerIsolateThreadData* per_thread_data = isolate-> | |
2072 FindPerThreadDataForThread(thread_id); | |
2073 if (!per_thread_data) return; | |
2074 Simulator* sim = per_thread_data->simulator(); | |
2075 // Check if there is active simulator before allocating TickSample. | |
2076 if (!sim) return; | |
2077 #endif | |
2078 #endif // USE_SIMULATOR | |
2079 TickSample sample_obj; | |
2080 TickSample* sample = isolate->cpu_profiler()->TickSampleEvent(); | |
2081 if (sample == NULL) sample = &sample_obj; | |
2082 | |
2083 static const DWORD kSuspendFailed = static_cast<DWORD>(-1); | |
2084 if (SuspendThread(profiled_thread) == kSuspendFailed) return; | |
2085 sample->state = isolate->current_vm_state(); | |
2086 | |
2087 context.ContextFlags = CONTEXT_FULL; | |
2088 if (GetThreadContext(profiled_thread, &context) != 0) { | |
2089 #if defined(USE_SIMULATOR) | |
2090 #if V8_TARGET_ARCH_ARM | |
2091 sample->pc = reinterpret_cast<Address>(sim->get_register(Simulator::pc)); | |
2092 sample->sp = reinterpret_cast<Address>(sim->get_register(Simulator::sp)); | |
2093 sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::r11)); | |
2094 #elif V8_TARGET_ARCH_MIPS | |
2095 sample->pc = reinterpret_cast<Address>(sim->get_register(Simulator::pc)); | |
2096 sample->sp = reinterpret_cast<Address>(sim->get_register(Simulator::sp)); | |
2097 sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::fp)); | |
2098 #endif | |
2099 #else | |
2100 #if V8_HOST_ARCH_X64 | |
2101 sample->pc = reinterpret_cast<Address>(context.Rip); | |
2102 sample->sp = reinterpret_cast<Address>(context.Rsp); | |
2103 sample->fp = reinterpret_cast<Address>(context.Rbp); | |
2104 #else | |
2105 sample->pc = reinterpret_cast<Address>(context.Eip); | |
2106 sample->sp = reinterpret_cast<Address>(context.Esp); | |
2107 sample->fp = reinterpret_cast<Address>(context.Ebp); | |
2108 #endif | |
2109 #endif // USE_SIMULATOR | |
2110 sampler->SampleStack(sample); | |
2111 sampler->Tick(sample); | |
2112 } | |
2113 ResumeThread(profiled_thread); | |
2114 } | |
2115 | |
2116 const int interval_; | |
2117 | |
2118 // Protects the process wide state below. | |
2119 static Mutex* mutex_; | |
2120 static SamplerThread* instance_; | |
2121 | |
2122 private: | |
2123 DISALLOW_COPY_AND_ASSIGN(SamplerThread); | |
2124 }; | |
2125 | |
2126 | |
2127 Mutex* SamplerThread::mutex_ = NULL; | |
2128 SamplerThread* SamplerThread::instance_ = NULL; | |
2129 | |
2130 | |
2131 void OS::SetUp() { | 1971 void OS::SetUp() { |
2132 // Seed the random number generator. | 1972 // Seed the random number generator. |
2133 // Convert the current time to a 64-bit integer first, before converting it | 1973 // Convert the current time to a 64-bit integer first, before converting it |
2134 // to an unsigned. Going directly can cause an overflow and the seed to be | 1974 // to an unsigned. Going directly can cause an overflow and the seed to be |
2135 // set to all ones. The seed will be identical for different instances that | 1975 // set to all ones. The seed will be identical for different instances that |
2136 // call this setup code within the same millisecond. | 1976 // call this setup code within the same millisecond. |
2137 uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis()); | 1977 uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis()); |
2138 srand(static_cast<unsigned int>(seed)); | 1978 srand(static_cast<unsigned int>(seed)); |
2139 limit_mutex = CreateMutex(); | 1979 limit_mutex = CreateMutex(); |
2140 SamplerThread::SetUp(); | |
2141 } | 1980 } |
2142 | 1981 |
2143 | 1982 |
2144 void OS::TearDown() { | 1983 void OS::TearDown() { |
2145 SamplerThread::TearDown(); | |
2146 delete limit_mutex; | 1984 delete limit_mutex; |
2147 } | 1985 } |
2148 | 1986 |
2149 | 1987 |
2150 Sampler::Sampler(Isolate* isolate, int interval) | |
2151 : isolate_(isolate), | |
2152 interval_(interval), | |
2153 profiling_(false), | |
2154 active_(false), | |
2155 samples_taken_(0) { | |
2156 data_ = new PlatformData; | |
2157 } | |
2158 | |
2159 | |
2160 Sampler::~Sampler() { | |
2161 ASSERT(!IsActive()); | |
2162 delete data_; | |
2163 } | |
2164 | |
2165 | |
2166 void Sampler::Start() { | |
2167 ASSERT(!IsActive()); | |
2168 SetActive(true); | |
2169 SamplerThread::AddActiveSampler(this); | |
2170 } | |
2171 | |
2172 | |
2173 void Sampler::Stop() { | |
2174 ASSERT(IsActive()); | |
2175 SamplerThread::RemoveActiveSampler(this); | |
2176 SetActive(false); | |
2177 } | |
2178 | |
2179 | |
2180 } } // namespace v8::internal | 1988 } } // namespace v8::internal |
OLD | NEW |