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
12namespace v8 {
13namespace internal {
14
15class 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
24struct 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.
32struct 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
56class 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