Revision: 14297
Author:   [email protected]
Date:     Wed Apr 17 00:20:24 2013
Log:      Nuke SamplerRegistry

The registry is a simple list of active Samplers but uses additional Mutex. Useful parts were merged into SamplerThread, others removed completely.

BUG=None

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

Modified:
 /branches/bleeding_edge/src/log.cc
 /branches/bleeding_edge/src/log.h
 /branches/bleeding_edge/src/sampler.cc
 /branches/bleeding_edge/src/v8.cc

=======================================
--- /branches/bleeding_edge/src/log.cc  Tue Apr 16 05:30:51 2013
+++ /branches/bleeding_edge/src/log.cc  Wed Apr 17 00:20:24 2013
@@ -1928,66 +1928,5 @@

   return log_->Close();
 }
-
-
-// Protects the state below.
-static Mutex* active_samplers_mutex = NULL;
-
-List<Sampler*>* SamplerRegistry::active_samplers_ = NULL;
-
-
-void SamplerRegistry::SetUp() {
-  if (!active_samplers_mutex) {
-    active_samplers_mutex = OS::CreateMutex();
-  }
-}
-
-
-bool SamplerRegistry::IterateActiveSamplers(VisitSampler func, void* param) {
-  ScopedLock lock(active_samplers_mutex);
-  for (int i = 0;
-       ActiveSamplersExist() && i < active_samplers_->length();
-       ++i) {
-    func(active_samplers_->at(i), param);
-  }
-  return ActiveSamplersExist();
-}
-
-
-static void ComputeCpuProfiling(Sampler* sampler, void* flag_ptr) {
-  bool* flag = reinterpret_cast<bool*>(flag_ptr);
-  *flag |= sampler->IsProfiling();
-}
-
-
-SamplerRegistry::State SamplerRegistry::GetState() {
-  bool flag = false;
-  if (!IterateActiveSamplers(&ComputeCpuProfiling, &flag)) {
-    return HAS_NO_SAMPLERS;
-  }
-  return flag ? HAS_CPU_PROFILING_SAMPLERS : HAS_SAMPLERS;
-}
-
-
-void SamplerRegistry::AddActiveSampler(Sampler* sampler) {
-  ASSERT(sampler->IsActive());
-  ScopedLock lock(active_samplers_mutex);
-  if (active_samplers_ == NULL) {
-    active_samplers_ = new List<Sampler*>;
-  } else {
-    ASSERT(!active_samplers_->Contains(sampler));
-  }
-  active_samplers_->Add(sampler);
-}
-
-
-void SamplerRegistry::RemoveActiveSampler(Sampler* sampler) {
-  ASSERT(sampler->IsActive());
-  ScopedLock lock(active_samplers_mutex);
-  ASSERT(active_samplers_ != NULL);
-  bool removed = active_samplers_->RemoveElement(sampler);
-  ASSERT(removed);
-  USE(removed);
-}

 } }  // namespace v8::internal
=======================================
--- /branches/bleeding_edge/src/log.h   Tue Apr 16 05:06:43 2013
+++ /branches/bleeding_edge/src/log.h   Wed Apr 17 00:20:24 2013
@@ -505,40 +505,6 @@
 };


-// Process wide registry of samplers.
-class SamplerRegistry : public AllStatic {
- public:
-  enum State {
-    HAS_NO_SAMPLERS,
-    HAS_SAMPLERS,
-    HAS_CPU_PROFILING_SAMPLERS
-  };
-
-  static void SetUp();
-
-  typedef void (*VisitSampler)(Sampler*, void*);
-
-  static State GetState();
-
-  // Iterates over all active samplers keeping the internal lock held.
-  // Returns whether there are any active samplers.
-  static bool IterateActiveSamplers(VisitSampler func, void* param);
-
-  // Adds/Removes an active sampler.
-  static void AddActiveSampler(Sampler* sampler);
-  static void RemoveActiveSampler(Sampler* sampler);
-
- private:
-  static bool ActiveSamplersExist() {
-    return active_samplers_ != NULL && !active_samplers_->is_empty();
-  }
-
-  static List<Sampler*>* active_samplers_;
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(SamplerRegistry);
-};
-
-
 // Class that extracts stack trace, used for profiling.
 class StackTracer : public AllStatic {
  public:
=======================================
--- /branches/bleeding_edge/src/sampler.cc      Tue Apr 16 05:06:43 2013
+++ /branches/bleeding_edge/src/sampler.cc      Wed Apr 17 00:20:24 2013
@@ -65,12 +65,6 @@
 #include "v8threads.h"


-namespace v8 {
-namespace internal {
-
-
-#if defined(USE_SIGNALS)
-
 #if defined(__ANDROID__) && !defined(__BIONIC_HAVE_UCONTEXT_T)

 // Not all versions of Android's C library provide ucontext_t.
@@ -146,6 +140,11 @@
 #endif  // __ANDROID__ && !defined(__BIONIC_HAVE_UCONTEXT_T)


+namespace v8 {
+namespace internal {
+
+#if defined(USE_SIGNALS)
+
 class Sampler::PlatformData : public Malloced {
  public:
   PlatformData()
@@ -161,7 +160,41 @@
 };


-static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
+class SignalHandler : public AllStatic {
+ public:
+  static inline void EnsureInstalled() {
+    if (signal_handler_installed_) return;
+    struct sigaction sa;
+    sa.sa_sigaction = &HandleProfilerSignal;
+    sigemptyset(&sa.sa_mask);
+    sa.sa_flags = SA_RESTART | SA_SIGINFO;
+    signal_handler_installed_ =
+        (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0);
+  }
+
+  static inline 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);
+  static bool signal_handler_installed_;
+  static struct sigaction old_signal_handler_;
+};
+
+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__)
   // As Native Client does not support signal handling, profiling
   // is disabled.
@@ -360,83 +393,78 @@

   static void SetUp() { if (!mutex_) mutex_ = OS::CreateMutex(); }
   static void TearDown() { delete mutex_; }
-
-#if defined(USE_SIGNALS)
-  static void InstallSignalHandler() {
-    struct sigaction sa;
-    sa.sa_sigaction = ProfilerSignalHandler;
-    sigemptyset(&sa.sa_mask);
-    sa.sa_flags = SA_RESTART | SA_SIGINFO;
-    signal_handler_installed_ =
-        (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0);
-  }
-
-  static void RestoreSignalHandler() {
-    if (signal_handler_installed_) {
-      sigaction(SIGPROF, &old_signal_handler_, 0);
-      signal_handler_installed_ = false;
-    }
-  }
-#endif

   static void AddActiveSampler(Sampler* sampler) {
+    bool need_to_start = false;
     ScopedLock lock(mutex_);
-    SamplerRegistry::AddActiveSampler(sampler);
     if (instance_ == NULL) {
       // Start a thread that will send SIGPROF signal to VM threads,
       // when CPU profiling will be enabled.
       instance_ = new SamplerThread(sampler->interval());
-      instance_->StartSynchronously();
-    } else {
-      ASSERT(instance_->interval_ == sampler->interval());
+      need_to_start = true;
     }
+
+    ASSERT(sampler->IsActive());
+    ASSERT(!instance_->active_samplers_.Contains(sampler));
+    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) {
-    ScopedLock lock(mutex_);
-    SamplerRegistry::RemoveActiveSampler(sampler);
-    if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
-      instance_->Join();
-      delete instance_;
-      instance_ = NULL;
+    SamplerThread* instance_to_remove = NULL;
+    {
+      ScopedLock lock(mutex_);
+
+      ASSERT(sampler->IsActive());
+      bool removed = instance_->active_samplers_.RemoveElement(sampler);
+      ASSERT(removed);
+      USE(removed);
+
+      // We cannot delete the instance immediately as we need to Join() the
+ // thread but we are holding mutex_ and the thread may try to acquire it.
+      if (instance_->active_samplers_.is_empty()) {
+        instance_to_remove = instance_;
+        instance_ = NULL;
 #if defined(USE_SIGNALS)
-      RestoreSignalHandler();
+        SignalHandler::Restore();
 #endif
+      }
     }
+
+    if (!instance_to_remove) return;
+    instance_to_remove->Join();
+    delete instance_to_remove;
   }

   // Implement Thread::Run().
   virtual void Run() {
-    SamplerRegistry::State state;
-    while ((state = SamplerRegistry::GetState()) !=
-           SamplerRegistry::HAS_NO_SAMPLERS) {
-      // When CPU profiling is enabled both JavaScript and C++ code is
-      // profiled. We must not suspend.
-      if (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS) {
-#if defined(USE_SIGNALS)
-        if (!signal_handler_installed_) InstallSignalHandler();
-#endif
-        SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this);
-      } else {
-#if defined(USE_SIGNALS)
-        if (signal_handler_installed_) RestoreSignalHandler();
-#endif
+    while (true) {
+      {
+        ScopedLock lock(mutex_);
+        if (active_samplers_.is_empty()) break;
+        // When CPU profiling is enabled both JavaScript and C++ code is
+        // profiled. We must not suspend.
+        for (int i = 0; i < active_samplers_.length(); ++i) {
+          Sampler* sampler = active_samplers_.at(i);
+          if (!sampler->isolate()->IsInitialized()) continue;
+          if (!sampler->IsProfiling()) continue;
+          SampleContext(sampler);
+        }
       }
       OS::Sleep(interval_);
     }
   }

-  static void DoCpuProfile(Sampler* sampler, void* raw_sender) {
-    if (!sampler->isolate()->IsInitialized()) return;
-    if (!sampler->IsProfiling()) return;
-    SamplerThread* sender = reinterpret_cast<SamplerThread*>(raw_sender);
-    sender->SampleContext(sampler);
-  }
-
+ private:
 #if defined(USE_SIGNALS)

   void SampleContext(Sampler* sampler) {
-    if (!signal_handler_installed_) return;
+    if (!SignalHandler::Installed()) return;
     pthread_t tid = sampler->platform_data()->vm_tid();
     int result = pthread_kill(tid, SIGPROF);
     USE(result);
@@ -575,27 +603,20 @@

 #endif  // USE_SIGNALS

-  const int interval_;

   // Protects the process wide state below.
   static Mutex* mutex_;
   static SamplerThread* instance_;
-#if defined(USE_SIGNALS)
-  static bool signal_handler_installed_;
-  static struct sigaction old_signal_handler_;
-#endif
+
+  const int interval_;
+  List<Sampler*> active_samplers_;

- private:
   DISALLOW_COPY_AND_ASSIGN(SamplerThread);
 };


 Mutex* SamplerThread::mutex_ = NULL;
 SamplerThread* SamplerThread::instance_ = NULL;
-#if defined(USE_SIGNALS)
-struct sigaction SamplerThread::old_signal_handler_;
-bool SamplerThread::signal_handler_installed_ = false;
-#endif


 void Sampler::SetUp() {
=======================================
--- /branches/bleeding_edge/src/v8.cc   Mon Apr 15 06:57:41 2013
+++ /branches/bleeding_edge/src/v8.cc   Wed Apr 17 00:20:24 2013
@@ -37,7 +37,6 @@
 #include "heap-profiler.h"
 #include "hydrogen.h"
 #include "lithium-allocator.h"
-#include "log.h"
 #include "objects.h"
 #include "once.h"
 #include "platform.h"
@@ -281,7 +280,6 @@
   ElementsAccessor::InitializeOncePerProcess();
   LOperand::SetUpCaches();
   SetUpJSCallerSavedCodeData();
-  SamplerRegistry::SetUp();
   ExternalReference::SetUp();
 }

--
--
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