| Index: src/sampler.cc
|
| diff --git a/src/sampler.cc b/src/sampler.cc
|
| index f0d2b10c7f7e0d5d150c1d5552426dbaa2f64032..ef525f96faf870a14422cadab343eb7ccbc03d00 100644
|
| --- a/src/sampler.cc
|
| +++ b/src/sampler.cc
|
| @@ -27,9 +27,7 @@
|
|
|
| #include "sampler.h"
|
|
|
| -#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) \
|
| - || defined(__NetBSD__) || defined(__sun) || defined(__ANDROID__) \
|
| - || defined(__native_client__) || defined(__MACH__)
|
| +#if V8_OS_POSIX && !V8_OS_CYGWIN
|
|
|
| #define USE_SIGNALS
|
|
|
| @@ -39,25 +37,25 @@
|
| #include <sys/time.h>
|
| #include <sys/syscall.h>
|
|
|
| -#if defined(__MACH__)
|
| +#if V8_OS_MACOSX
|
| #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.
|
| -#elif(!defined(__ANDROID__) || defined(__BIONIC_HAVE_UCONTEXT_T)) \
|
| - && !defined(__OpenBSD__)
|
| +#elif(!V8_OS_ANDROID || defined(__BIONIC_HAVE_UCONTEXT_T)) \
|
| + && !V8_OS_OPENBSD
|
| #include <ucontext.h>
|
| #endif
|
| #include <unistd.h>
|
|
|
| // GLibc on ARM defines mcontext_t has a typedef for 'struct sigcontext'.
|
| // Old versions of the C library <signal.h> didn't define the type.
|
| -#if defined(__ANDROID__) && !defined(__BIONIC_HAVE_UCONTEXT_T) && \
|
| +#if V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T) && \
|
| (defined(__arm__) || defined(__aarch64__)) && \
|
| !defined(__BIONIC_HAVE_STRUCT_SIGCONTEXT)
|
| #include <asm/sigcontext.h>
|
| #endif
|
|
|
| -#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
|
| +#elif V8_OS_WIN || V8_OS_CYGWIN
|
|
|
| #include "win32-headers.h"
|
|
|
| @@ -75,7 +73,7 @@
|
| #include "vm-state-inl.h"
|
|
|
|
|
| -#if defined(__ANDROID__) && !defined(__BIONIC_HAVE_UCONTEXT_T)
|
| +#if V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T)
|
|
|
| // Not all versions of Android's C library provide ucontext_t.
|
| // Detect this and provide custom but compatible definitions. Note that these
|
| @@ -159,7 +157,7 @@ typedef struct ucontext {
|
| enum { REG_EBP = 6, REG_ESP = 7, REG_EIP = 14 };
|
| #endif
|
|
|
| -#endif // __ANDROID__ && !defined(__BIONIC_HAVE_UCONTEXT_T)
|
| +#endif // V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T)
|
|
|
|
|
| namespace v8 {
|
| @@ -192,7 +190,7 @@ class Sampler::PlatformData : public PlatformDataCommon {
|
| pthread_t vm_tid_;
|
| };
|
|
|
| -#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
|
| +#elif V8_OS_WIN || V8_OS_CYGWIN
|
|
|
| // ----------------------------------------------------------------------------
|
| // Win32 profiler support. On Cygwin we use the same sampler implementation as
|
| @@ -277,8 +275,25 @@ class SimulatorHelper {
|
|
|
| class SignalHandler : public AllStatic {
|
| public:
|
| - static inline void EnsureInstalled() {
|
| - if (signal_handler_installed_) return;
|
| + static void SetUp() { if (!mutex_) mutex_ = new Mutex(); }
|
| + static void TearDown() { delete mutex_; }
|
| +
|
| + static void IncreaseSamplerCount() {
|
| + LockGuard<Mutex> lock_guard(mutex_);
|
| + if (++client_count_ == 1) Install();
|
| + }
|
| +
|
| + static void DecreaseSamplerCount() {
|
| + LockGuard<Mutex> lock_guard(mutex_);
|
| + if (--client_count_ == 0) Restore();
|
| + }
|
| +
|
| + static bool Installed() {
|
| + return signal_handler_installed_;
|
| + }
|
| +
|
| + private:
|
| + static void Install() {
|
| struct sigaction sa;
|
| sa.sa_sigaction = &HandleProfilerSignal;
|
| sigemptyset(&sa.sa_mask);
|
| @@ -287,30 +302,31 @@ class SignalHandler : public AllStatic {
|
| (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0);
|
| }
|
|
|
| - static inline void Restore() {
|
| + static void Restore() {
|
| if (signal_handler_installed_) {
|
| sigaction(SIGPROF, &old_signal_handler_, 0);
|
| signal_handler_installed_ = false;
|
| }
|
| }
|
|
|
| - static inline bool Installed() {
|
| - return signal_handler_installed_;
|
| - }
|
| -
|
| - private:
|
| static void HandleProfilerSignal(int signal, siginfo_t* info, void* context);
|
| + // Protects the process wide state below.
|
| + static Mutex* mutex_;
|
| + static int client_count_;
|
| static bool signal_handler_installed_;
|
| static struct sigaction old_signal_handler_;
|
| };
|
|
|
| +
|
| +Mutex* SignalHandler::mutex_ = NULL;
|
| +int SignalHandler::client_count_ = 0;
|
| struct sigaction SignalHandler::old_signal_handler_;
|
| bool SignalHandler::signal_handler_installed_ = false;
|
|
|
|
|
| void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info,
|
| void* context) {
|
| -#if defined(__native_client__)
|
| +#if V8_OS_NACL
|
| // As Native Client does not support signal handling, profiling
|
| // is disabled.
|
| return;
|
| @@ -328,7 +344,7 @@ void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info,
|
| }
|
|
|
| Sampler* sampler = isolate->logger()->sampler();
|
| - if (sampler == NULL || !sampler->IsActive()) return;
|
| + if (sampler == NULL) return;
|
|
|
| RegisterState state;
|
|
|
| @@ -344,10 +360,10 @@ void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info,
|
| #else
|
| // Extracting the sample from the context is extremely machine dependent.
|
| ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
|
| -#if !defined(__OpenBSD__)
|
| +#if !V8_OS_OPENBSD
|
| mcontext_t& mcontext = ucontext->uc_mcontext;
|
| #endif
|
| -#if defined(__linux__) || defined(__ANDROID__)
|
| +#if V8_OS_LINUX
|
| #if V8_HOST_ARCH_IA32
|
| state.pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]);
|
| state.sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]);
|
| @@ -380,7 +396,7 @@ 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__)
|
| +#elif V8_OS_MACOSX
|
| #if V8_HOST_ARCH_X64
|
| #if __DARWIN_UNIX03
|
| state.pc = reinterpret_cast<Address>(mcontext->__ss.__rip);
|
| @@ -402,7 +418,7 @@ void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info,
|
| state.fp = reinterpret_cast<Address>(mcontext->ss.ebp);
|
| #endif // __DARWIN_UNIX03
|
| #endif // V8_HOST_ARCH_IA32
|
| -#elif defined(__FreeBSD__)
|
| +#elif V8_OS_FREEBSD
|
| #if V8_HOST_ARCH_IA32
|
| state.pc = reinterpret_cast<Address>(mcontext.mc_eip);
|
| state.sp = reinterpret_cast<Address>(mcontext.mc_esp);
|
| @@ -416,7 +432,7 @@ void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info,
|
| state.sp = reinterpret_cast<Address>(mcontext.mc_r13);
|
| state.fp = reinterpret_cast<Address>(mcontext.mc_r11);
|
| #endif // V8_HOST_ARCH_*
|
| -#elif defined(__NetBSD__)
|
| +#elif V8_OS_NETBSD
|
| #if V8_HOST_ARCH_IA32
|
| state.pc = reinterpret_cast<Address>(mcontext.__gregs[_REG_EIP]);
|
| state.sp = reinterpret_cast<Address>(mcontext.__gregs[_REG_ESP]);
|
| @@ -426,7 +442,7 @@ void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info,
|
| state.sp = reinterpret_cast<Address>(mcontext.__gregs[_REG_RSP]);
|
| state.fp = reinterpret_cast<Address>(mcontext.__gregs[_REG_RBP]);
|
| #endif // V8_HOST_ARCH_*
|
| -#elif defined(__OpenBSD__)
|
| +#elif V8_OS_OPENBSD
|
| #if V8_HOST_ARCH_IA32
|
| state.pc = reinterpret_cast<Address>(ucontext->sc_eip);
|
| state.sp = reinterpret_cast<Address>(ucontext->sc_esp);
|
| @@ -436,14 +452,14 @@ void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info,
|
| state.sp = reinterpret_cast<Address>(ucontext->sc_rsp);
|
| state.fp = reinterpret_cast<Address>(ucontext->sc_rbp);
|
| #endif // V8_HOST_ARCH_*
|
| -#elif defined(__sun)
|
| +#elif V8_OS_SOLARIS
|
| state.pc = reinterpret_cast<Address>(mcontext.gregs[REG_PC]);
|
| state.sp = reinterpret_cast<Address>(mcontext.gregs[REG_SP]);
|
| state.fp = reinterpret_cast<Address>(mcontext.gregs[REG_FP]);
|
| -#endif // __sun
|
| +#endif // V8_OS_SOLARIS
|
| #endif // USE_SIMULATOR
|
| sampler->SampleStack(state);
|
| -#endif // __native_client__
|
| +#endif // V8_OS_NACL
|
| }
|
|
|
| #endif
|
| @@ -457,12 +473,12 @@ class SamplerThread : public Thread {
|
| : Thread(Thread::Options("SamplerThread", kSamplerThreadStackSize)),
|
| interval_(interval) {}
|
|
|
| - static void SetUp() { if (!mutex_) mutex_ = OS::CreateMutex(); }
|
| - static void TearDown() { delete mutex_; }
|
| + static void SetUp() { if (!mutex_) mutex_ = new Mutex(); }
|
| + static void TearDown() { delete mutex_; mutex_ = NULL; }
|
|
|
| static void AddActiveSampler(Sampler* sampler) {
|
| bool need_to_start = false;
|
| - ScopedLock lock(mutex_);
|
| + LockGuard<Mutex> lock_guard(mutex_);
|
| if (instance_ == NULL) {
|
| // Start a thread that will send SIGPROF signal to VM threads,
|
| // when CPU profiling will be enabled.
|
| @@ -475,16 +491,13 @@ class SamplerThread : public Thread {
|
| ASSERT(instance_->interval_ == sampler->interval());
|
| instance_->active_samplers_.Add(sampler);
|
|
|
| -#if defined(USE_SIGNALS)
|
| - SignalHandler::EnsureInstalled();
|
| -#endif
|
| if (need_to_start) instance_->StartSynchronously();
|
| }
|
|
|
| static void RemoveActiveSampler(Sampler* sampler) {
|
| SamplerThread* instance_to_remove = NULL;
|
| {
|
| - ScopedLock lock(mutex_);
|
| + LockGuard<Mutex> lock_guard(mutex_);
|
|
|
| ASSERT(sampler->IsActive());
|
| bool removed = instance_->active_samplers_.RemoveElement(sampler);
|
| @@ -496,9 +509,6 @@ class SamplerThread : public Thread {
|
| if (instance_->active_samplers_.is_empty()) {
|
| instance_to_remove = instance_;
|
| instance_ = NULL;
|
| -#if defined(USE_SIGNALS)
|
| - SignalHandler::Restore();
|
| -#endif
|
| }
|
| }
|
|
|
| @@ -511,7 +521,7 @@ class SamplerThread : public Thread {
|
| virtual void Run() {
|
| while (true) {
|
| {
|
| - ScopedLock lock(mutex_);
|
| + LockGuard<Mutex> lock_guard(mutex_);
|
| if (active_samplers_.is_empty()) break;
|
| // When CPU profiling is enabled both JavaScript and C++ code is
|
| // profiled. We must not suspend.
|
| @@ -587,12 +597,18 @@ DISABLE_ASAN void TickSample::Init(Isolate* isolate,
|
|
|
|
|
| void Sampler::SetUp() {
|
| +#if defined(USE_SIGNALS)
|
| + SignalHandler::SetUp();
|
| +#endif
|
| SamplerThread::SetUp();
|
| }
|
|
|
|
|
| void Sampler::TearDown() {
|
| SamplerThread::TearDown();
|
| +#if defined(USE_SIGNALS)
|
| + SignalHandler::TearDown();
|
| +#endif
|
| }
|
|
|
|
|
| @@ -628,6 +644,22 @@ void Sampler::Stop() {
|
| }
|
|
|
|
|
| +void Sampler::IncreaseProfilingDepth() {
|
| + NoBarrier_AtomicIncrement(&profiling_, 1);
|
| +#if defined(USE_SIGNALS)
|
| + SignalHandler::IncreaseSamplerCount();
|
| +#endif
|
| +}
|
| +
|
| +
|
| +void Sampler::DecreaseProfilingDepth() {
|
| +#if defined(USE_SIGNALS)
|
| + SignalHandler::DecreaseSamplerCount();
|
| +#endif
|
| + NoBarrier_AtomicIncrement(&profiling_, -1);
|
| +}
|
| +
|
| +
|
| void Sampler::SampleStack(const RegisterState& state) {
|
| TickSample* sample = isolate_->cpu_profiler()->StartTickSample();
|
| TickSample sample_obj;
|
| @@ -645,15 +677,6 @@ void Sampler::SampleStack(const RegisterState& state) {
|
| }
|
|
|
|
|
| -bool Sampler::CanSampleOnProfilerEventsProcessorThread() {
|
| -#if defined(USE_SIGNALS)
|
| - return true;
|
| -#else
|
| - return false;
|
| -#endif
|
| -}
|
| -
|
| -
|
| #if defined(USE_SIGNALS)
|
|
|
| void Sampler::DoSample() {
|
| @@ -661,7 +684,7 @@ void Sampler::DoSample() {
|
| pthread_kill(platform_data()->vm_tid(), SIGPROF);
|
| }
|
|
|
| -#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
|
| +#elif V8_OS_WIN || V8_OS_CYGWIN
|
|
|
| void Sampler::DoSample() {
|
| HANDLE profiled_thread = platform_data()->profiled_thread();
|
|
|