Revision: 16320
Author:   [email protected]
Date:     Mon Aug 26 11:53:29 2013 UTC
Log:      Use signals for cpu profiling on Mac OS X

A while ago in r2315 Mac OS X cpu profiler implementation was changed to pause sampled thread instead of sending SIGPROF signal. That was done because at that point profiler send the signal to the whole process and it was handled on a random thread. Now that signal-based implementation uses pthread_kill it may well be used on Mac OS X too.

BUG=v8:2814
[email protected], [email protected]

Review URL: https://codereview.chromium.org/23115005
http://code.google.com/p/v8/source/detail?r=16320

Modified:
 /branches/bleeding_edge/src/cpu-profiler.cc
 /branches/bleeding_edge/src/sampler.cc

=======================================
--- /branches/bleeding_edge/src/cpu-profiler.cc Mon Aug 26 07:17:12 2013 UTC
+++ /branches/bleeding_edge/src/cpu-profiler.cc Mon Aug 26 11:53:29 2013 UTC
@@ -436,7 +436,6 @@
     processor_ = new ProfilerEventsProcessor(
         generator_, sampler, FLAG_cpu_profiler_sampling_interval);
     is_profiling_ = true;
-    processor_->StartSynchronously();
     // Enumerate stuff we already have in the heap.
     ASSERT(isolate_->heap()->HasBeenSetUp());
     if (!FLAG_prof_browser_mode) {
@@ -454,6 +453,7 @@
       sampler->Start();
       need_to_stop_sampler_ = true;
     }
+    processor_->StartSynchronously();
   }
 }

=======================================
--- /branches/bleeding_edge/src/sampler.cc      Mon Aug 26 07:17:12 2013 UTC
+++ /branches/bleeding_edge/src/sampler.cc      Mon Aug 26 11:53:29 2013 UTC
@@ -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 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 @@
   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 @@
           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 @@
   }

  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 @@
 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
 //
@@ -725,11 +616,53 @@
 #endif
 }

+
+#if defined(USE_SIGNALS)
+
+void Sampler::DoSample() {
+  if (!SignalHandler::Installed()) return;
+  pthread_kill(platform_data()->vm_tid(), SIGPROF);
+}
+
+#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)

 void Sampler::DoSample() {
-#if defined(USE_SIGNALS)
-  platform_data()->SendProfilingSignal();
+  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

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to