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 TickSampleTickSample34 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 isolate()72 Isolate* isolate() const { return isolate_; } interval()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? IsProfiling()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). IsActive()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. SetHasProcessingThread(bool value)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. js_and_external_sample_count()101 unsigned js_and_external_sample_count() const { 102 return js_and_external_sample_count_; 103 } StartCountingSamples()104 void StartCountingSamples() { 105 is_counting_samples_ = true; 106 js_and_external_sample_count_ = 0; 107 } 108 109 class PlatformData; platform_data()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: SetActive(bool value)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