| Index: src/sampler.cc
|
| diff --git a/src/sampler.cc b/src/sampler.cc
|
| index 52b03853d35c2df1ba6462d07aa56ba3d91c1b52..fa8c2e80ecd98b42d59642055f4bcbd63a44a57e 100644
|
| --- a/src/sampler.cc
|
| +++ b/src/sampler.cc
|
| @@ -29,7 +29,7 @@
|
|
|
| #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) \
|
| || defined(__NetBSD__) || defined(__sun) || defined(__ANDROID__) \
|
| - || defined(__native_client__)
|
| + || defined(__native_client__) || defined(__MACH__)
|
|
|
| #define USE_SIGNALS
|
|
|
| @@ -38,9 +38,12 @@
|
| #include <signal.h>
|
| #include <sys/time.h>
|
| #include <sys/syscall.h>
|
| +
|
| +#if defined(__MACH__)
|
| +#include <mach/mach.h>
|
| // OpenBSD doesn't have <ucontext.h>. ucontext_t lives in <signal.h>
|
| // and is a typedef for struct sigcontext. There is no uc_mcontext.
|
| -#if (!defined(__ANDROID__) || defined(__BIONIC_HAVE_UCONTEXT_T)) \
|
| +#elif(!defined(__ANDROID__) || defined(__BIONIC_HAVE_UCONTEXT_T)) \
|
| && !defined(__OpenBSD__)
|
| #include <ucontext.h>
|
| #endif
|
| @@ -53,10 +56,6 @@
|
| #include <asm/sigcontext.h>
|
| #endif
|
|
|
| -#elif defined(__MACH__)
|
| -
|
| -#include <mach/mach.h>
|
| -
|
| #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
|
|
|
| #include "win32-headers.h"
|
| @@ -174,33 +173,12 @@ class PlatformDataCommon : public Malloced {
|
| class Sampler::PlatformData : public PlatformDataCommon {
|
| public:
|
| PlatformData() : vm_tid_(pthread_self()) {}
|
| -
|
| - void SendProfilingSignal() const;
|
| + pthread_t vm_tid() const { return vm_tid_; }
|
|
|
| private:
|
| pthread_t vm_tid_;
|
| };
|
|
|
| -#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__)
|
|
|
| // ----------------------------------------------------------------------------
|
| @@ -365,6 +343,28 @@ void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info,
|
| state.sp = reinterpret_cast<Address>(mcontext.gregs[29]);
|
| state.fp = reinterpret_cast<Address>(mcontext.gregs[30]);
|
| #endif // V8_HOST_ARCH_*
|
| +#elif defined(__MACH__)
|
| +#if V8_HOST_ARCH_X64
|
| +#if __DARWIN_UNIX03
|
| + state.pc = reinterpret_cast<Address>(mcontext->__ss.__rip);
|
| + state.sp = reinterpret_cast<Address>(mcontext->__ss.__rsp);
|
| + state.fp = reinterpret_cast<Address>(mcontext->__ss.__rbp);
|
| +#else // !__DARWIN_UNIX03
|
| + state.pc = reinterpret_cast<Address>(mcontext->ss.rip);
|
| + state.sp = reinterpret_cast<Address>(mcontext->ss.rsp);
|
| + state.fp = reinterpret_cast<Address>(mcontext->ss.rbp);
|
| +#endif // __DARWIN_UNIX03
|
| +#elif V8_HOST_ARCH_IA32
|
| +#if __DARWIN_UNIX03
|
| + state.pc = reinterpret_cast<Address>(mcontext->__ss.__eip);
|
| + state.sp = reinterpret_cast<Address>(mcontext->__ss.__esp);
|
| + state.fp = reinterpret_cast<Address>(mcontext->__ss.__ebp);
|
| +#else // !__DARWIN_UNIX03
|
| + state.pc = reinterpret_cast<Address>(mcontext->ss.eip);
|
| + state.sp = reinterpret_cast<Address>(mcontext->ss.esp);
|
| + state.fp = reinterpret_cast<Address>(mcontext->ss.ebp);
|
| +#endif // __DARWIN_UNIX03
|
| +#endif // V8_HOST_ARCH_IA32
|
| #elif defined(__FreeBSD__)
|
| #if V8_HOST_ARCH_IA32
|
| state.pc = reinterpret_cast<Address>(mcontext.mc_eip);
|
| @@ -482,7 +482,7 @@ class SamplerThread : public Thread {
|
| Sampler* sampler = active_samplers_.at(i);
|
| if (!sampler->isolate()->IsInitialized()) continue;
|
| if (!sampler->IsProfiling()) continue;
|
| - SampleContext(sampler);
|
| + sampler->DoSample();
|
| }
|
| }
|
| OS::Sleep(interval_);
|
| @@ -490,107 +490,6 @@ class SamplerThread : public Thread {
|
| }
|
|
|
| private:
|
| -#if defined(USE_SIGNALS)
|
| -
|
| - void SampleContext(Sampler* sampler) {
|
| - sampler->platform_data()->SendProfilingSignal();
|
| - }
|
| -
|
| -#elif defined(__MACH__)
|
| -
|
| - void SampleContext(Sampler* sampler) {
|
| - thread_act_t profiled_thread = sampler->platform_data()->profiled_thread();
|
| -
|
| -#if defined(USE_SIMULATOR)
|
| - SimulatorHelper helper;
|
| - Isolate* isolate = sampler->isolate();
|
| - if (!helper.Init(sampler, isolate)) return;
|
| -#endif
|
| -
|
| - if (KERN_SUCCESS != thread_suspend(profiled_thread)) return;
|
| -
|
| -#if V8_HOST_ARCH_X64
|
| - thread_state_flavor_t flavor = x86_THREAD_STATE64;
|
| - x86_thread_state64_t thread_state;
|
| - mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT;
|
| -#if __DARWIN_UNIX03
|
| -#define REGISTER_FIELD(name) __r ## name
|
| -#else
|
| -#define REGISTER_FIELD(name) r ## name
|
| -#endif // __DARWIN_UNIX03
|
| -#elif V8_HOST_ARCH_IA32
|
| - thread_state_flavor_t flavor = i386_THREAD_STATE;
|
| - i386_thread_state_t thread_state;
|
| - mach_msg_type_number_t count = i386_THREAD_STATE_COUNT;
|
| -#if __DARWIN_UNIX03
|
| -#define REGISTER_FIELD(name) __e ## name
|
| -#else
|
| -#define REGISTER_FIELD(name) e ## name
|
| -#endif // __DARWIN_UNIX03
|
| -#else
|
| -#error Unsupported Mac OS X host architecture.
|
| -#endif // V8_HOST_ARCH
|
| -
|
| - if (thread_get_state(profiled_thread,
|
| - flavor,
|
| - reinterpret_cast<natural_t*>(&thread_state),
|
| - &count) == KERN_SUCCESS) {
|
| - RegisterState state;
|
| -#if defined(USE_SIMULATOR)
|
| - helper.FillRegisters(&state);
|
| -#else
|
| - state.pc = reinterpret_cast<Address>(thread_state.REGISTER_FIELD(ip));
|
| - state.sp = reinterpret_cast<Address>(thread_state.REGISTER_FIELD(sp));
|
| - state.fp = reinterpret_cast<Address>(thread_state.REGISTER_FIELD(bp));
|
| -#endif // USE_SIMULATOR
|
| -#undef REGISTER_FIELD
|
| - sampler->SampleStack(state);
|
| - }
|
| - thread_resume(profiled_thread);
|
| - }
|
| -
|
| -#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
|
| -
|
| - void SampleContext(Sampler* sampler) {
|
| - HANDLE profiled_thread = sampler->platform_data()->profiled_thread();
|
| - if (profiled_thread == NULL) return;
|
| -
|
| - Isolate* isolate = sampler->isolate();
|
| -#if defined(USE_SIMULATOR)
|
| - SimulatorHelper helper;
|
| - if (!helper.Init(sampler, isolate)) return;
|
| -#endif
|
| -
|
| - const DWORD kSuspendFailed = static_cast<DWORD>(-1);
|
| - if (SuspendThread(profiled_thread) == kSuspendFailed) return;
|
| -
|
| - // 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) {
|
| - RegisterState state;
|
| -#if defined(USE_SIMULATOR)
|
| - helper.FillRegisters(&state);
|
| -#else
|
| -#if V8_HOST_ARCH_X64
|
| - state.pc = reinterpret_cast<Address>(context.Rip);
|
| - state.sp = reinterpret_cast<Address>(context.Rsp);
|
| - state.fp = reinterpret_cast<Address>(context.Rbp);
|
| -#else
|
| - state.pc = reinterpret_cast<Address>(context.Eip);
|
| - state.sp = reinterpret_cast<Address>(context.Esp);
|
| - state.fp = reinterpret_cast<Address>(context.Ebp);
|
| -#endif
|
| -#endif // USE_SIMULATOR
|
| - sampler->SampleStack(state);
|
| - }
|
| - ResumeThread(profiled_thread);
|
| - }
|
| -
|
| -#endif // USE_SIGNALS
|
| -
|
| -
|
| // Protects the process wide state below.
|
| static Mutex* mutex_;
|
| static SamplerThread* instance_;
|
| @@ -606,14 +505,6 @@ Mutex* SamplerThread::mutex_ = NULL;
|
| SamplerThread* SamplerThread::instance_ = NULL;
|
|
|
|
|
| -#if defined(USE_SIGNALS)
|
| -void Sampler::PlatformData::SendProfilingSignal() const {
|
| - if (!SignalHandler::Installed()) return;
|
| - pthread_kill(vm_tid_, SIGPROF);
|
| -}
|
| -#endif
|
| -
|
| -
|
| //
|
| // StackTracer implementation
|
| //
|
| @@ -726,10 +617,52 @@ bool Sampler::CanSampleOnProfilerEventsProcessorThread() {
|
| }
|
|
|
|
|
| -void Sampler::DoSample() {
|
| #if defined(USE_SIGNALS)
|
| - platform_data()->SendProfilingSignal();
|
| +
|
| +void Sampler::DoSample() {
|
| + if (!SignalHandler::Installed()) return;
|
| + pthread_kill(platform_data()->vm_tid(), SIGPROF);
|
| +}
|
| +
|
| +#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
|
| +
|
| +void Sampler::DoSample() {
|
| + HANDLE profiled_thread = platform_data()->profiled_thread();
|
| + if (profiled_thread == NULL) return;
|
| +
|
| +#if defined(USE_SIMULATOR)
|
| + SimulatorHelper helper;
|
| + if (!helper.Init(this, isolate())) return;
|
| #endif
|
| +
|
| + const DWORD kSuspendFailed = static_cast<DWORD>(-1);
|
| + if (SuspendThread(profiled_thread) == kSuspendFailed) return;
|
| +
|
| + // 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) {
|
| + RegisterState state;
|
| +#if defined(USE_SIMULATOR)
|
| + helper.FillRegisters(&state);
|
| +#else
|
| +#if V8_HOST_ARCH_X64
|
| + state.pc = reinterpret_cast<Address>(context.Rip);
|
| + state.sp = reinterpret_cast<Address>(context.Rsp);
|
| + state.fp = reinterpret_cast<Address>(context.Rbp);
|
| +#else
|
| + state.pc = reinterpret_cast<Address>(context.Eip);
|
| + state.sp = reinterpret_cast<Address>(context.Esp);
|
| + state.fp = reinterpret_cast<Address>(context.Ebp);
|
| +#endif
|
| +#endif // USE_SIMULATOR
|
| + SampleStack(state);
|
| + }
|
| + ResumeThread(profiled_thread);
|
| }
|
|
|
| +#endif // USE_SIGNALS
|
| +
|
| +
|
| } } // namespace v8::internal
|
|
|