Home | History | Annotate | Download | only in src
      1 // Copyright 2013 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_SAMPLER_H_
      6 #define V8_SAMPLER_H_
      7 
      8 #include "src/base/atomicops.h"
      9 #include "src/frames.h"
     10 #include "src/globals.h"
     11 
     12 namespace v8 {
     13 namespace internal {
     14 
     15 class Isolate;
     16 
     17 // ----------------------------------------------------------------------------
     18 // Sampler
     19 //
     20 // A sampler periodically samples the state of the VM and optionally
     21 // (if used for profiling) the program counter and stack pointer for
     22 // the thread that created it.
     23 
     24 struct RegisterState {
     25   RegisterState() : pc(NULL), sp(NULL), fp(NULL) {}
     26   Address pc;      // Instruction pointer.
     27   Address sp;      // Stack pointer.
     28   Address fp;      // Frame pointer.
     29 };
     30 
     31 // TickSample captures the information collected for each sample.
     32 struct TickSample {
     33   TickSample()
     34       : state(OTHER),
     35         pc(NULL),
     36         external_callback(NULL),
     37         frames_count(0),
     38         has_external_callback(false),
     39         top_frame_type(StackFrame::NONE) {}
     40   void Init(Isolate* isolate, const RegisterState& state);
     41   StateTag state;  // The state of the VM.
     42   Address pc;      // Instruction pointer.
     43   union {
     44     Address tos;   // Top stack value (*sp).
     45     Address external_callback;
     46   };
     47   static const unsigned kMaxFramesCountLog2 = 8;
     48   static const unsigned kMaxFramesCount = (1 << kMaxFramesCountLog2) - 1;
     49   Address stack[kMaxFramesCount];  // Call stack.
     50   base::TimeTicks timestamp;
     51   unsigned frames_count : kMaxFramesCountLog2;  // Number of captured frames.
     52   bool has_external_callback : 1;
     53   StackFrame::Type top_frame_type : 4;
     54 };
     55 
     56 class Sampler {
     57  public:
     58   // Initializes the Sampler support. Called once at VM startup.
     59   static void SetUp();
     60   static void TearDown();
     61 
     62   // Initialize sampler.
     63   Sampler(Isolate* isolate, int interval);
     64   virtual ~Sampler();
     65 
     66   Isolate* isolate() const { return isolate_; }
     67   int interval() const { return interval_; }
     68 
     69   // Performs stack sampling.
     70   void SampleStack(const RegisterState& regs);
     71 
     72   // Start and stop sampler.
     73   void Start();
     74   void Stop();
     75 
     76   // Whether the sampling thread should use this Sampler for CPU profiling?
     77   bool IsProfiling() const {
     78     return base::NoBarrier_Load(&profiling_) > 0 &&
     79         !base::NoBarrier_Load(&has_processing_thread_);
     80   }
     81   void IncreaseProfilingDepth();
     82   void DecreaseProfilingDepth();
     83 
     84   // Whether the sampler is running (that is, consumes resources).
     85   bool IsActive() const { return base::NoBarrier_Load(&active_); }
     86 
     87   void DoSample();
     88   // If true next sample must be initiated on the profiler event processor
     89   // thread right after latest sample is processed.
     90   void SetHasProcessingThread(bool value) {
     91     base::NoBarrier_Store(&has_processing_thread_, value);
     92   }
     93 
     94   // Used in tests to make sure that stack sampling is performed.
     95   unsigned js_and_external_sample_count() const {
     96     return js_and_external_sample_count_;
     97   }
     98   void StartCountingSamples() {
     99       is_counting_samples_ = true;
    100       js_and_external_sample_count_ = 0;
    101   }
    102 
    103   class PlatformData;
    104   PlatformData* platform_data() const { return data_; }
    105 
    106  protected:
    107   // This method is called for each sampling period with the current
    108   // program counter.
    109   virtual void Tick(TickSample* sample) = 0;
    110 
    111  private:
    112   void SetActive(bool value) { base::NoBarrier_Store(&active_, value); }
    113 
    114   Isolate* isolate_;
    115   const int interval_;
    116   base::Atomic32 profiling_;
    117   base::Atomic32 has_processing_thread_;
    118   base::Atomic32 active_;
    119   PlatformData* data_;  // Platform specific data.
    120   bool is_counting_samples_;
    121   // Counts stack samples taken in JS VM state.
    122   unsigned js_and_external_sample_count_;
    123   DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler);
    124 };
    125 
    126 
    127 } }  // namespace v8::internal
    128 
    129 #endif  // V8_SAMPLER_H_
    130