1// Copyright 2013 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_SAMPLER_H_
29#define V8_SAMPLER_H_
30
31#include "atomicops.h"
32#include "frames.h"
33#include "v8globals.h"
34
35namespace v8 {
36namespace internal {
37
38class Isolate;
39
40// ----------------------------------------------------------------------------
41// Sampler
42//
43// A sampler periodically samples the state of the VM and optionally
44// (if used for profiling) the program counter and stack pointer for
45// the thread that created it.
46
47struct RegisterState {
48  RegisterState() : pc(NULL), sp(NULL), fp(NULL) {}
49  Address pc;      // Instruction pointer.
50  Address sp;      // Stack pointer.
51  Address fp;      // Frame pointer.
52};
53
54// TickSample captures the information collected for each sample.
55struct TickSample {
56  TickSample()
57      : state(OTHER),
58        pc(NULL),
59        external_callback(NULL),
60        frames_count(0),
61        has_external_callback(false),
62        top_frame_type(StackFrame::NONE) {}
63  void Init(Isolate* isolate, const RegisterState& state);
64  StateTag state;  // The state of the VM.
65  Address pc;      // Instruction pointer.
66  union {
67    Address tos;   // Top stack value (*sp).
68    Address external_callback;
69  };
70  static const int kMaxFramesCount = 64;
71  Address stack[kMaxFramesCount];  // Call stack.
72  int frames_count : 8;  // Number of captured frames.
73  bool has_external_callback : 1;
74  StackFrame::Type top_frame_type : 4;
75};
76
77class Sampler {
78 public:
79  // Initializes the Sampler support. Called once at VM startup.
80  static void SetUp();
81  static void TearDown();
82
83  // Initialize sampler.
84  Sampler(Isolate* isolate, int interval);
85  virtual ~Sampler();
86
87  Isolate* isolate() const { return isolate_; }
88  int interval() const { return interval_; }
89
90  // Performs stack sampling.
91  void SampleStack(const RegisterState& regs);
92
93  // Start and stop sampler.
94  void Start();
95  void Stop();
96
97  // Is the sampler used for profiling?
98  bool IsProfiling() const { return NoBarrier_Load(&profiling_) > 0; }
99  void IncreaseProfilingDepth() { NoBarrier_AtomicIncrement(&profiling_, 1); }
100  void DecreaseProfilingDepth() { NoBarrier_AtomicIncrement(&profiling_, -1); }
101
102  // Whether the sampler is running (that is, consumes resources).
103  bool IsActive() const { return NoBarrier_Load(&active_); }
104
105  // Used in tests to make sure that stack sampling is performed.
106  unsigned js_and_external_sample_count() const {
107    return js_and_external_sample_count_;
108  }
109  void StartCountingSamples() {
110      is_counting_samples_ = true;
111      js_and_external_sample_count_ = 0;
112  }
113
114  class PlatformData;
115  PlatformData* platform_data() const { return data_; }
116
117 protected:
118  // This method is called for each sampling period with the current
119  // program counter.
120  virtual void Tick(TickSample* sample) = 0;
121
122 private:
123  void SetActive(bool value) { NoBarrier_Store(&active_, value); }
124
125  Isolate* isolate_;
126  const int interval_;
127  Atomic32 profiling_;
128  Atomic32 active_;
129  PlatformData* data_;  // Platform specific data.
130  bool is_counting_samples_;
131  // Counts stack samples taken in JS VM state.
132  unsigned js_and_external_sample_count_;
133  DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler);
134};
135
136
137} }  // namespace v8::internal
138
139#endif  // V8_SAMPLER_H_
140