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 int kMaxFramesCount = 64;
     48   Address stack[kMaxFramesCount];  // Call stack.
     49   TimeTicks timestamp;
     50   int frames_count : 8;  // Number of captured frames.
     51   bool has_external_callback : 1;
     52   StackFrame::Type top_frame_type : 4;
     53 };
     54 
     55 class Sampler {
     56  public:
     57   // Initializes the Sampler support. Called once at VM startup.
     58   static void SetUp();
     59   static void TearDown();
     60 
     61   // Initialize sampler.
     62   Sampler(Isolate* isolate, int interval);
     63   virtual ~Sampler();
     64 
     65   Isolate* isolate() const { return isolate_; }
     66   int interval() const { return interval_; }
     67 
     68   // Performs stack sampling.
     69   void SampleStack(const RegisterState& regs);
     70 
     71   // Start and stop sampler.
     72   void Start();
     73   void Stop();
     74 
     75   // Whether the sampling thread should use this Sampler for CPU profiling?
     76   bool IsProfiling() const {
     77     return base::NoBarrier_Load(&profiling_) > 0 &&
     78         !base::NoBarrier_Load(&has_processing_thread_);
     79   }
     80   void IncreaseProfilingDepth();
     81   void DecreaseProfilingDepth();
     82 
     83   // Whether the sampler is running (that is, consumes resources).
     84   bool IsActive() const { return base::NoBarrier_Load(&active_); }
     85 
     86   void DoSample();
     87   // If true next sample must be initiated on the profiler event processor
     88   // thread right after latest sample is processed.
     89   void SetHasProcessingThread(bool value) {
     90     base::NoBarrier_Store(&has_processing_thread_, value);
     91   }
     92 
     93   // Used in tests to make sure that stack sampling is performed.
     94   unsigned js_and_external_sample_count() const {
     95     return js_and_external_sample_count_;
     96   }
     97   void StartCountingSamples() {
     98       is_counting_samples_ = true;
     99       js_and_external_sample_count_ = 0;
    100   }
    101 
    102   class PlatformData;
    103   PlatformData* platform_data() const { return data_; }
    104 
    105  protected:
    106   // This method is called for each sampling period with the current
    107   // program counter.
    108   virtual void Tick(TickSample* sample) = 0;
    109 
    110  private:
    111   void SetActive(bool value) { base::NoBarrier_Store(&active_, value); }
    112 
    113   Isolate* isolate_;
    114   const int interval_;
    115   base::Atomic32 profiling_;
    116   base::Atomic32 has_processing_thread_;
    117   base::Atomic32 active_;
    118   PlatformData* data_;  // Platform specific data.
    119   bool is_counting_samples_;
    120   // Counts stack samples taken in JS VM state.
    121   unsigned js_and_external_sample_count_;
    122   DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler);
    123 };
    124 
    125 
    126 } }  // namespace v8::internal
    127 
    128 #endif  // V8_SAMPLER_H_
    129