Index: src/sampler.cc |
diff --git a/src/sampler.cc b/src/sampler.cc |
index 25478a61ddad530d8a5ceb80b6087adb15746c61..efac288ee72c0870e5d1bee9b04290e94ac7ec1f 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<Address>(simulator_->get_pc()); |
+ sample->sp = reinterpret_cast<Address>(simulator_->get_register( |
+ Simulator::sp)); |
+#if V8_TARGET_ARCH_ARM |
+ sample->fp = reinterpret_cast<Address>(simulator_->get_register( |
+ Simulator::r11)); |
+#elif V8_TARGET_ARCH_MIPS |
+ sample->fp = reinterpret_cast<Address>(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<Address>(sim->get_pc()); |
- sample->sp = reinterpret_cast<Address>(sim->get_register(Simulator::sp)); |
-#if V8_TARGET_ARCH_ARM |
- sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::r11)); |
-#elif V8_TARGET_ARCH_MIPS |
- sample->fp = reinterpret_cast<Address>(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<ucontext_t*>(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<Address>(sim->get_pc()); |
- sample->sp = reinterpret_cast<Address>(sim->get_register(Simulator::sp)); |
-#if V8_TARGET_ARCH_ARM |
- sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::r11)); |
-#elif V8_TARGET_ARCH_MIPS |
- sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::fp)); |
-#endif |
+ helper.FillRegisters(sample); |
#else |
sample->pc = reinterpret_cast<Address>(state.REGISTER_FIELD(ip)); |
sample->sp = reinterpret_cast<Address>(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<DWORD>(-1); |
+ const DWORD kSuspendFailed = static_cast<DWORD>(-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<Address>(sim->get_pc()); |
- sample->sp = reinterpret_cast<Address>(sim->get_register(Simulator::sp)); |
-#if V8_TARGET_ARCH_ARM |
- sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::r11)); |
-#elif V8_TARGET_ARCH_MIPS |
- sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::fp)); |
-#endif |
+ helper.FillRegisters(sample); |
#else |
#if V8_HOST_ARCH_X64 |
sample->pc = reinterpret_cast<Address>(context.Rip); |