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