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