| // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| #ifndef VM_PROFILER_H_ |
| #define VM_PROFILER_H_ |
| |
| #include "vm/allocation.h" |
| #include "vm/code_observers.h" |
| #include "vm/globals.h" |
| #include "vm/thread.h" |
| #include "vm/thread_interrupter.h" |
| |
| namespace dart { |
| |
| // Forward declarations. |
| class JSONArray; |
| class JSONStream; |
| struct Sample; |
| |
| // Profiler |
| class Profiler : public AllStatic { |
| public: |
| static void InitOnce(); |
| static void Shutdown(); |
| |
| static void InitProfilingForIsolate(Isolate* isolate, |
| bool shared_buffer = false); |
| static void ShutdownProfilingForIsolate(Isolate* isolate); |
| |
| static void BeginExecution(Isolate* isolate); |
| static void EndExecution(Isolate* isolate); |
| |
| static void PrintToJSONStream(Isolate* isolate, JSONStream* stream); |
| |
| static void WriteTracing(Isolate* isolate); |
| |
| static SampleBuffer* sample_buffer() { |
| return sample_buffer_; |
| } |
| |
| private: |
| static bool initialized_; |
| static Monitor* monitor_; |
| |
| static void WriteTracingSample(Isolate* isolate, intptr_t pid, |
| Sample* sample, JSONArray& events); |
| |
| static void RecordTickInterruptCallback(const InterruptedThreadState& state, |
| void* data); |
| |
| static void RecordSampleInterruptCallback(const InterruptedThreadState& state, |
| void* data); |
| |
| static SampleBuffer* sample_buffer_; |
| }; |
| |
| |
| class IsolateProfilerData { |
| public: |
| IsolateProfilerData(SampleBuffer* sample_buffer, bool own_sample_buffer); |
| ~IsolateProfilerData(); |
| |
| SampleBuffer* sample_buffer() const { return sample_buffer_; } |
| |
| void set_sample_buffer(SampleBuffer* sample_buffer) { |
| sample_buffer_ = sample_buffer; |
| } |
| |
| private: |
| SampleBuffer* sample_buffer_; |
| bool own_sample_buffer_; |
| DISALLOW_COPY_AND_ASSIGN(IsolateProfilerData); |
| }; |
| |
| |
| // Profile sample. |
| struct Sample { |
| static const char* kLookupSymbol; |
| static const char* kNoSymbol; |
| static const char* kNoFrame; |
| static const intptr_t kNumStackFrames = 6; |
| enum SampleType { |
| kIsolateStart, |
| kIsolateStop, |
| kIsolateSample, |
| }; |
| int64_t timestamp; |
| ThreadId tid; |
| Isolate* isolate; |
| uintptr_t pcs[kNumStackFrames]; |
| SampleType type; |
| uint16_t vm_tags; |
| uint16_t runtime_tags; |
| |
| void Init(SampleType type, Isolate* isolate, int64_t timestamp, ThreadId tid); |
| }; |
| |
| |
| // Ring buffer of samples. |
| class SampleBuffer { |
| public: |
| static const intptr_t kDefaultBufferCapacity = 120000; // 2 minutes @ 1000hz. |
| |
| explicit SampleBuffer(intptr_t capacity = kDefaultBufferCapacity); |
| ~SampleBuffer(); |
| |
| intptr_t capacity() const { return capacity_; } |
| |
| Sample* ReserveSample(); |
| |
| Sample* GetSample(intptr_t i) const { |
| ASSERT(i >= 0); |
| ASSERT(i < capacity_); |
| return &samples_[i]; |
| } |
| |
| private: |
| Sample* samples_; |
| intptr_t capacity_; |
| uintptr_t cursor_; |
| |
| DISALLOW_COPY_AND_ASSIGN(SampleBuffer); |
| }; |
| |
| |
| class ProfilerSampleStackWalker : public ValueObject { |
| public: |
| ProfilerSampleStackWalker(Sample* sample, |
| uintptr_t stack_lower, |
| uintptr_t stack_upper, |
| uintptr_t pc, |
| uintptr_t fp, |
| uintptr_t sp); |
| |
| int walk(); |
| |
| private: |
| uword* CallerPC(uword* fp); |
| uword* CallerFP(uword* fp); |
| |
| bool ValidInstructionPointer(uword* pc); |
| |
| bool ValidFramePointer(uword* fp); |
| |
| Sample* sample_; |
| const uintptr_t stack_lower_; |
| const uintptr_t stack_upper_; |
| const uintptr_t original_pc_; |
| const uintptr_t original_fp_; |
| const uintptr_t original_sp_; |
| uintptr_t lower_bound_; |
| }; |
| |
| |
| } // namespace dart |
| |
| #endif // VM_PROFILER_H_ |