From f6499289f634a8be42a5bb30bd8d230c7202b339 Mon Sep 17 00:00:00 2001 From: "yurys@chromium.org" Date: Mon, 3 Jun 2013 07:52:08 +0000 Subject: [PATCH] Simulator specific code that is the same on all platforms as well as TickSample instance retrieval extracted into SampleHelper class. Drive-by: extracted platform-independent pieces of Sampler::PlatformData into PlatformDataCommon. BUG=None R=loislo@chromium.org, svenpanne@chromium.org Review URL: https://codereview.chromium.org/15957005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14910 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/sampler.cc | 266 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 131 insertions(+), 135 deletions(-) diff --git a/src/sampler.cc b/src/sampler.cc index 25478a6..efac288 100644 --- a/src/sampler.cc +++ b/src/sampler.cc @@ -145,23 +145,130 @@ enum { REG_EBP = 6, REG_ESP = 7, REG_EIP = 14 }; namespace v8 { namespace internal { -#if defined(USE_SIGNALS) +namespace { -class Sampler::PlatformData : public Malloced { +class PlatformDataCommon : public Malloced { public: - PlatformData() - : vm_tid_(pthread_self()), - profiled_thread_id_(ThreadId::Current()) {} + PlatformDataCommon() : profiled_thread_id_(ThreadId::Current()) {} + ThreadId profiled_thread_id() { return profiled_thread_id_; } + + protected: + ~PlatformDataCommon() {} + + private: + ThreadId profiled_thread_id_; +}; + +} // namespace +#if defined(USE_SIGNALS) + +class Sampler::PlatformData : public PlatformDataCommon { + public: + PlatformData() : vm_tid_(pthread_self()) {} pthread_t vm_tid() const { return vm_tid_; } - ThreadId profiled_thread_id() { return profiled_thread_id_; } private: pthread_t vm_tid_; - ThreadId profiled_thread_id_; +}; + +#elif defined(__MACH__) + +class Sampler::PlatformData : public PlatformDataCommon { + public: + PlatformData() : profiled_thread_(mach_thread_self()) {} + + ~PlatformData() { + // Deallocate Mach port for thread. + mach_port_deallocate(mach_task_self(), profiled_thread_); + } + + thread_act_t profiled_thread() { return profiled_thread_; } + + private: + // Note: for profiled_thread_ Mach primitives are used instead of PThread's + // because the latter doesn't provide thread manipulation primitives required. + // For details, consult "Mac OS X Internals" book, Section 7.3. + thread_act_t profiled_thread_; +}; + +#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__) + +// ---------------------------------------------------------------------------- +// Win32 profiler support. On Cygwin we use the same sampler implementation as +// on Win32. + +class Sampler::PlatformData : public PlatformDataCommon { + public: + // Get a handle to the calling thread. This is the thread that we are + // going to profile. We need to make a copy of the handle because we are + // going to use it in the sampler thread. Using GetThreadHandle() will + // not work in this case. We're using OpenThread because DuplicateHandle + // for some reason doesn't work in Chrome's sandbox. + PlatformData() + : profiled_thread_(OpenThread(THREAD_GET_CONTEXT | + THREAD_SUSPEND_RESUME | + THREAD_QUERY_INFORMATION, + false, + GetCurrentThreadId())) {} + + ~PlatformData() { + if (profiled_thread_ != NULL) { + CloseHandle(profiled_thread_); + profiled_thread_ = NULL; + } + } + + HANDLE profiled_thread() { return profiled_thread_; } + + private: + HANDLE profiled_thread_; +}; +#endif + + +class SampleHelper { + public: + inline TickSample* Init(Sampler* sampler, Isolate* isolate) { +#if defined(USE_SIMULATOR) + ThreadId thread_id = sampler->platform_data()->profiled_thread_id(); + Isolate::PerIsolateThreadData* per_thread_data = isolate-> + FindPerThreadDataForThread(thread_id); + if (!per_thread_data) return NULL; + simulator_ = per_thread_data->simulator(); + // Check if there is active simulator before allocating TickSample. + if (!simulator_) return NULL; +#endif // USE_SIMULATOR + TickSample* sample = isolate->cpu_profiler()->TickSampleEvent(); + if (sample == NULL) sample = &sample_obj; + return sample; + } + +#if defined(USE_SIMULATOR) + inline void FillRegisters(TickSample* sample) { + sample->pc = reinterpret_cast
(simulator_->get_pc()); + sample->sp = reinterpret_cast
(simulator_->get_register( + Simulator::sp)); +#if V8_TARGET_ARCH_ARM + sample->fp = reinterpret_cast
(simulator_->get_register( + Simulator::r11)); +#elif V8_TARGET_ARCH_MIPS + sample->fp = reinterpret_cast
(simulator_->get_register( + Simulator::fp)); +#endif + } +#endif // USE_SIMULATOR + + private: +#if defined(USE_SIMULATOR) + Simulator* simulator_; +#endif + TickSample sample_obj; }; +#if defined(USE_SIGNALS) + class SignalHandler : public AllStatic { public: static inline void EnsureInstalled() { @@ -217,30 +324,12 @@ void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info, Sampler* sampler = isolate->logger()->sampler(); if (sampler == NULL || !sampler->IsActive()) return; -#if defined(USE_SIMULATOR) -#if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS - ThreadId thread_id = sampler->platform_data()->profiled_thread_id(); - Isolate::PerIsolateThreadData* per_thread_data = isolate-> - FindPerThreadDataForThread(thread_id); - if (!per_thread_data) return; - Simulator* sim = per_thread_data->simulator(); - // Check if there is active simulator before allocating TickSample. - if (!sim) return; -#endif -#endif // USE_SIMULATOR - - TickSample sample_obj; - TickSample* sample = isolate->cpu_profiler()->TickSampleEvent(); - if (sample == NULL) sample = &sample_obj; + SampleHelper helper; + TickSample* sample = helper.Init(sampler, isolate); + if (sample == NULL) return; #if defined(USE_SIMULATOR) - sample->pc = reinterpret_cast
(sim->get_pc()); - sample->sp = reinterpret_cast
(sim->get_register(Simulator::sp)); -#if V8_TARGET_ARCH_ARM - sample->fp = reinterpret_cast
(sim->get_register(Simulator::r11)); -#elif V8_TARGET_ARCH_MIPS - sample->fp = reinterpret_cast
(sim->get_register(Simulator::fp)); -#endif // V8_TARGET_ARCH_* + helper.FillRegisters(sample); #else // Extracting the sample from the context is extremely machine dependent. ucontext_t* ucontext = reinterpret_cast(context); @@ -321,65 +410,6 @@ void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info, #endif // __native_client__ } -#elif defined(__MACH__) -class Sampler::PlatformData : public Malloced { - public: - PlatformData() - : profiled_thread_(mach_thread_self()), - profiled_thread_id_(ThreadId::Current()) {} - - ~PlatformData() { - // Deallocate Mach port for thread. - mach_port_deallocate(mach_task_self(), profiled_thread_); - } - - thread_act_t profiled_thread() { return profiled_thread_; } - ThreadId profiled_thread_id() { return profiled_thread_id_; } - - private: - // Note: for profiled_thread_ Mach primitives are used instead of PThread's - // because the latter doesn't provide thread manipulation primitives required. - // For details, consult "Mac OS X Internals" book, Section 7.3. - thread_act_t profiled_thread_; - ThreadId profiled_thread_id_; -}; - -#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__) - -// ---------------------------------------------------------------------------- -// Win32 profiler support. On Cygwin we use the same sampler implementation as -// on Win32. - -class Sampler::PlatformData : public Malloced { - public: - // Get a handle to the calling thread. This is the thread that we are - // going to profile. We need to make a copy of the handle because we are - // going to use it in the sampler thread. Using GetThreadHandle() will - // not work in this case. We're using OpenThread because DuplicateHandle - // for some reason doesn't work in Chrome's sandbox. - PlatformData() - : profiled_thread_(OpenThread(THREAD_GET_CONTEXT | - THREAD_SUSPEND_RESUME | - THREAD_QUERY_INFORMATION, - false, - GetCurrentThreadId())), - profiled_thread_id_(ThreadId::Current()) {} - - ~PlatformData() { - if (profiled_thread_ != NULL) { - CloseHandle(profiled_thread_); - profiled_thread_ = NULL; - } - } - - HANDLE profiled_thread() { return profiled_thread_; } - ThreadId profiled_thread_id() { return profiled_thread_id_; } - - private: - HANDLE profiled_thread_; - ThreadId profiled_thread_id_; -}; - #endif @@ -476,20 +506,10 @@ class SamplerThread : public Thread { void SampleContext(Sampler* sampler) { thread_act_t profiled_thread = sampler->platform_data()->profiled_thread(); Isolate* isolate = sampler->isolate(); -#if defined(USE_SIMULATOR) -#if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS - ThreadId thread_id = sampler->platform_data()->profiled_thread_id(); - Isolate::PerIsolateThreadData* per_thread_data = isolate-> - FindPerThreadDataForThread(thread_id); - if (!per_thread_data) return; - Simulator* sim = per_thread_data->simulator(); - // Check if there is active simulator before allocating TickSample. - if (!sim) return; -#endif -#endif // USE_SIMULATOR - TickSample sample_obj; - TickSample* sample = isolate->cpu_profiler()->TickSampleEvent(); - if (sample == NULL) sample = &sample_obj; + + SampleHelper helper; + TickSample* sample = helper.Init(sampler, isolate); + if (sample == NULL) return; if (KERN_SUCCESS != thread_suspend(profiled_thread)) return; @@ -521,13 +541,7 @@ class SamplerThread : public Thread { &count) == KERN_SUCCESS) { sample->state = isolate->current_vm_state(); #if defined(USE_SIMULATOR) - sample->pc = reinterpret_cast
(sim->get_pc()); - sample->sp = reinterpret_cast
(sim->get_register(Simulator::sp)); -#if V8_TARGET_ARCH_ARM - sample->fp = reinterpret_cast
(sim->get_register(Simulator::r11)); -#elif V8_TARGET_ARCH_MIPS - sample->fp = reinterpret_cast
(sim->get_register(Simulator::fp)); -#endif + helper.FillRegisters(sample); #else sample->pc = reinterpret_cast
(state.REGISTER_FIELD(ip)); sample->sp = reinterpret_cast
(state.REGISTER_FIELD(sp)); @@ -546,40 +560,22 @@ class SamplerThread : public Thread { HANDLE profiled_thread = sampler->platform_data()->profiled_thread(); if (profiled_thread == NULL) return; - // Context used for sampling the register state of the profiled thread. - CONTEXT context; - memset(&context, 0, sizeof(context)); - Isolate* isolate = sampler->isolate(); -#if defined(USE_SIMULATOR) -#if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS - ThreadId thread_id = sampler->platform_data()->profiled_thread_id(); - Isolate::PerIsolateThreadData* per_thread_data = isolate-> - FindPerThreadDataForThread(thread_id); - if (!per_thread_data) return; - Simulator* sim = per_thread_data->simulator(); - // Check if there is active simulator before allocating TickSample. - if (!sim) return; -#endif -#endif // USE_SIMULATOR - TickSample sample_obj; - TickSample* sample = isolate->cpu_profiler()->TickSampleEvent(); - if (sample == NULL) sample = &sample_obj; + SampleHelper helper; + TickSample* sample = helper.Init(sampler, isolate); + if (sample == NULL) return; - static const DWORD kSuspendFailed = static_cast(-1); + const DWORD kSuspendFailed = static_cast(-1); if (SuspendThread(profiled_thread) == kSuspendFailed) return; sample->state = isolate->current_vm_state(); + // Context used for sampling the register state of the profiled thread. + CONTEXT context; + memset(&context, 0, sizeof(context)); context.ContextFlags = CONTEXT_FULL; if (GetThreadContext(profiled_thread, &context) != 0) { #if defined(USE_SIMULATOR) - sample->pc = reinterpret_cast
(sim->get_pc()); - sample->sp = reinterpret_cast
(sim->get_register(Simulator::sp)); -#if V8_TARGET_ARCH_ARM - sample->fp = reinterpret_cast
(sim->get_register(Simulator::r11)); -#elif V8_TARGET_ARCH_MIPS - sample->fp = reinterpret_cast
(sim->get_register(Simulator::fp)); -#endif + helper.FillRegisters(sample); #else #if V8_HOST_ARCH_X64 sample->pc = reinterpret_cast
(context.Rip); -- 2.7.4