Home | History | Annotate | Download | only in libsampler
      1 // Copyright 2016 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef V8_LIBSAMPLER_SAMPLER_H_
      6 #define V8_LIBSAMPLER_SAMPLER_H_
      7 
      8 #include "include/v8.h"
      9 
     10 #include "src/base/atomicops.h"
     11 #include "src/base/macros.h"
     12 
     13 namespace v8 {
     14 namespace sampler {
     15 
     16 // ----------------------------------------------------------------------------
     17 // Sampler
     18 //
     19 // A sampler periodically samples the state of the VM and optionally
     20 // (if used for profiling) the program counter and stack pointer for
     21 // the thread that created it.
     22 
     23 class Sampler {
     24  public:
     25   static const int kMaxFramesCountLog2 = 8;
     26   static const unsigned kMaxFramesCount = (1u << kMaxFramesCountLog2) - 1;
     27 
     28   // Initializes the Sampler support. Called once at VM startup.
     29   static void SetUp();
     30   static void TearDown();
     31 
     32   // Initialize sampler.
     33   explicit Sampler(Isolate* isolate);
     34   virtual ~Sampler();
     35 
     36   Isolate* isolate() const { return isolate_; }
     37 
     38   // Performs stack sampling.
     39   // Clients should override this method in order to do something on samples,
     40   // for example buffer samples in a queue.
     41   virtual void SampleStack(const v8::RegisterState& regs) = 0;
     42 
     43   // Start and stop sampler.
     44   void Start();
     45   void Stop();
     46 
     47   // Whether the sampling thread should use this Sampler for CPU profiling?
     48   bool IsProfiling() const {
     49     return base::NoBarrier_Load(&profiling_) > 0 &&
     50         !base::NoBarrier_Load(&has_processing_thread_);
     51   }
     52   void IncreaseProfilingDepth();
     53   void DecreaseProfilingDepth();
     54 
     55   // Whether the sampler is running (that is, consumes resources).
     56   bool IsActive() const { return base::NoBarrier_Load(&active_); }
     57 
     58   // CpuProfiler collects samples by calling DoSample directly
     59   // without calling Start. To keep it working, we register the sampler
     60   // with the CpuProfiler.
     61   bool IsRegistered() const { return base::NoBarrier_Load(&registered_); }
     62 
     63   void DoSample();
     64 
     65   void SetHasProcessingThread(bool value) {
     66     base::NoBarrier_Store(&has_processing_thread_, value);
     67   }
     68 
     69   // Used in tests to make sure that stack sampling is performed.
     70   unsigned js_sample_count() const { return js_sample_count_; }
     71   unsigned external_sample_count() const { return external_sample_count_; }
     72   void StartCountingSamples() {
     73     js_sample_count_ = 0;
     74     external_sample_count_ = 0;
     75     is_counting_samples_ = true;
     76   }
     77 
     78   class PlatformData;
     79   PlatformData* platform_data() const { return data_; }
     80 
     81  protected:
     82   // Counts stack samples taken in various VM states.
     83   bool is_counting_samples_;
     84   unsigned js_sample_count_;
     85   unsigned external_sample_count_;
     86 
     87  private:
     88   void SetActive(bool value) { base::NoBarrier_Store(&active_, value); }
     89   void SetRegistered(bool value) { base::NoBarrier_Store(&registered_, value); }
     90 
     91   Isolate* isolate_;
     92   base::Atomic32 profiling_;
     93   base::Atomic32 has_processing_thread_;
     94   base::Atomic32 active_;
     95   base::Atomic32 registered_;
     96   PlatformData* data_;  // Platform specific data.
     97   DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler);
     98 };
     99 
    100 }  // namespace sampler
    101 }  // namespace v8
    102 
    103 #endif  // V8_LIBSAMPLER_SAMPLER_H_
    104