1e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org// Copyright 2013 the V8 project authors. All rights reserved.
23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be
33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file.
4e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
5e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org#ifndef V8_SAMPLER_H_
6e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org#define V8_SAMPLER_H_
7e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
81e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org#include "src/base/atomicops.h"
9196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/frames.h"
10196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/globals.h"
11e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
12e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgnamespace v8 {
13e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgnamespace internal {
14e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
15e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgclass Isolate;
16e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
17e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org// ----------------------------------------------------------------------------
18e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org// Sampler
19e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org//
20e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org// A sampler periodically samples the state of the VM and optionally
21e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org// (if used for profiling) the program counter and stack pointer for
22e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org// the thread that created it.
23e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
24c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.orgstruct RegisterState {
25c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org  RegisterState() : pc(NULL), sp(NULL), fp(NULL) {}
26c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org  Address pc;      // Instruction pointer.
27c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org  Address sp;      // Stack pointer.
28c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org  Address fp;      // Frame pointer.
29c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org};
30c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org
31e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org// TickSample captures the information collected for each sample.
32e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgstruct TickSample {
33e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  TickSample()
34e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      : state(OTHER),
35e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org        pc(NULL),
36e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org        external_callback(NULL),
3777ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org        frames_count(0),
38c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org        has_external_callback(false),
39c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org        top_frame_type(StackFrame::NONE) {}
40c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org  void Init(Isolate* isolate, const RegisterState& state);
41e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  StateTag state;  // The state of the VM.
42e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Address pc;      // Instruction pointer.
4377ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  union {
4477ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org    Address tos;   // Top stack value (*sp).
4577ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org    Address external_callback;
4677ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  };
4708e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  static const unsigned kMaxFramesCountLog2 = 8;
4808e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  static const unsigned kMaxFramesCount = (1 << kMaxFramesCountLog2) - 1;
49e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Address stack[kMaxFramesCount];  // Call stack.
505de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  base::TimeTicks timestamp;
5108e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  unsigned frames_count : kMaxFramesCountLog2;  // Number of captured frames.
5277ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  bool has_external_callback : 1;
53c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org  StackFrame::Type top_frame_type : 4;
54e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org};
55e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
56e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgclass Sampler {
57e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org public:
58e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Initializes the Sampler support. Called once at VM startup.
59e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  static void SetUp();
60e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  static void TearDown();
61e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
62e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Initialize sampler.
63e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Sampler(Isolate* isolate, int interval);
64e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  virtual ~Sampler();
65e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
66e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Isolate* isolate() const { return isolate_; }
67e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  int interval() const { return interval_; }
68e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
69e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Performs stack sampling.
70c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org  void SampleStack(const RegisterState& regs);
71e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
72e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Start and stop sampler.
73e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  void Start();
74e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  void Stop();
75e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
761e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // Whether the sampling thread should use this Sampler for CPU profiling?
771e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  bool IsProfiling() const {
781e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org    return base::NoBarrier_Load(&profiling_) > 0 &&
791e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org        !base::NoBarrier_Load(&has_processing_thread_);
801e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  }
81dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  void IncreaseProfilingDepth();
82dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  void DecreaseProfilingDepth();
83e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
84e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Whether the sampler is running (that is, consumes resources).
851e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org  bool IsActive() const { return base::NoBarrier_Load(&active_); }
86e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
87dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  void DoSample();
881e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // If true next sample must be initiated on the profiler event processor
891e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // thread right after latest sample is processed.
901e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  void SetHasProcessingThread(bool value) {
911e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org    base::NoBarrier_Store(&has_processing_thread_, value);
921e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  }
931e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
94e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Used in tests to make sure that stack sampling is performed.
95bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  unsigned js_and_external_sample_count() const {
96bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    return js_and_external_sample_count_;
97bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  }
98bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  void StartCountingSamples() {
99bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      is_counting_samples_ = true;
100bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      js_and_external_sample_count_ = 0;
101bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  }
102e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
103e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  class PlatformData;
104e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  PlatformData* platform_data() const { return data_; }
105e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
106c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org protected:
107c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org  // This method is called for each sampling period with the current
108c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org  // program counter.
109c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org  virtual void Tick(TickSample* sample) = 0;
110c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org
111e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org private:
1121e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org  void SetActive(bool value) { base::NoBarrier_Store(&active_, value); }
113e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
114e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Isolate* isolate_;
115e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  const int interval_;
1161e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org  base::Atomic32 profiling_;
1171e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org  base::Atomic32 has_processing_thread_;
1181e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org  base::Atomic32 active_;
119e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  PlatformData* data_;  // Platform specific data.
120bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  bool is_counting_samples_;
121bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // Counts stack samples taken in JS VM state.
122bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  unsigned js_and_external_sample_count_;
123e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler);
124e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org};
125e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
126e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
127e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org} }  // namespace v8::internal
128e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
129e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org#endif  // V8_SAMPLER_H_
130