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