| 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 |