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