Chromium Code Reviews| Index: runtime/vm/profiler.h |
| diff --git a/runtime/vm/profiler.h b/runtime/vm/profiler.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..21b4c18e64402d7f1d7ba47f64845e37c168d044 |
| --- /dev/null |
| +++ b/runtime/vm/profiler.h |
| @@ -0,0 +1,196 @@ |
| +// 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 "platform/hashmap.h" |
| +#include "platform/thread.h" |
| +#include "vm/allocation.h" |
| +#include "vm/code_observers.h" |
| +#include "vm/globals.h" |
| + |
| +namespace dart { |
| + |
| +class JSONStream; |
|
siva
2013/11/11 03:51:54
Add comment:
// Forward declarations.
Cutch
2013/11/18 20:48:54
Done.
|
| + |
| +// Profiler manager. |
| +class ProfilerManager : public AllStatic { |
| + public: |
| + static void InitOnce(); |
| + static void Shutdown(); |
| + |
| + static void SetupIsolateForProfiling(Isolate* isolate); |
| + static void ShutdownIsolateForProfiling(Isolate* isolate); |
| + static void ScheduleIsolate(Isolate* isolate); |
| + static void DescheduleIsolate(Isolate* isolate); |
| + |
| + static void PrintToJSONStream(Isolate* isolate, JSONStream* stream); |
| + |
| + static void WriteTracing(Isolate* isolate, const char* name, Dart_Port port); |
| + |
| + private: |
| + static bool initialized_; |
| + static bool shutdown_; |
| + static Monitor* monitor_; |
| + |
| + static Isolate** isolates_; |
| + static intptr_t isolates_capacity_; |
| + static intptr_t isolates_size_; |
| + |
| + static void ResizeIsolates(intptr_t new_capacity); |
| + static void AddIsolate(Isolate* isolate); |
| + static intptr_t FindIsolate(Isolate* isolate); |
| + static void RemoveIsolate(intptr_t i); |
| + |
| + // Returns the microseconds until the next live timer fires. |
| + static int64_t SampleAndRescheduleIsolates(int64_t current_time); |
| + static void FreeIsolateProfilingData(Isolate* isolate); |
| + static void ThreadMain(uword parameters); |
| +}; |
| + |
| + |
| +class IsolateProfilerData { |
| + public: |
| + static const int64_t kDescheduledCpuUsage = -1; |
| + static const int64_t kNoExpirationTime = -2; |
| + |
| + IsolateProfilerData(Isolate* isolate, SampleBuffer* sample_buffer); |
| + ~IsolateProfilerData(); |
| + |
| + int64_t sample_interval() const { return sample_interval_micros_; } |
|
siva
2013/11/11 03:51:54
normally we have been naming the setters and acces
Cutch
2013/11/18 20:48:54
Done.
|
| + |
| + void set_sample_interval(int64_t sample_interval) { |
| + sample_interval_micros_ = sample_interval; |
| + } |
| + |
| + bool CanExpire() { |
|
siva
2013/11/11 03:51:54
const?
Cutch
2013/11/18 20:48:54
Done.
|
| + return timer_expiration_micros_ != kNoExpirationTime; |
| + } |
| + |
| + bool ShouldSample(int64_t current_time) { |
|
siva
2013/11/11 03:51:54
const
Cutch
2013/11/18 20:48:54
Done.
|
| + return CanExpire() && TimeUntilExpiration(current_time) <= 0; |
| + } |
| + |
| + int64_t TimeUntilExpiration(int64_t current_time_micros) { |
|
siva
2013/11/11 03:51:54
const, maybe there are others too in these new cla
Cutch
2013/11/18 20:48:54
Done.
|
| + ASSERT(CanExpire()); |
| + return timer_expiration_micros_ - current_time_micros; |
| + } |
| + |
| + void set_cpu_usage(int64_t cpu_usage) { |
| + cpu_usage_ = cpu_usage; |
| + } |
| + |
| + void SampledAt(int64_t current_time); |
| + |
| + void Scheduled(int64_t current_time, ThreadId thread); |
| + |
| + void Descheduled(); |
| + |
| + int64_t cpu_usage() const { return cpu_usage_; } |
| + |
| + int64_t set_and_delta_cpu_usage(int64_t cpu_usage) { |
|
siva
2013/11/11 03:51:54
ComputeDeltaAndSetCpuUsage(int64_t cpu_usage) ?
Cutch
2013/11/18 20:48:54
Done.
|
| + int64_t delta = 0; |
| + if (cpu_usage_ != kDescheduledCpuUsage) { |
| + // Only compute the real delta if we are being sampled regularly. |
| + delta = cpu_usage - cpu_usage_; |
| + } |
| + set_cpu_usage(cpu_usage); |
| + return delta; |
| + } |
| + |
| + ThreadId thread_id() const { return thread_id_; } |
| + |
| + Isolate* isolate() const { return isolate_; } |
| + |
| + SampleBuffer* sample_buffer() const { return sample_buffer_; } |
| + |
| + private: |
| + int64_t last_sampled_micros_; |
| + int64_t timer_expiration_micros_; |
| + int64_t sample_interval_micros_; |
| + int64_t cpu_usage_; |
| + ThreadId thread_id_; |
| + Isolate* isolate_; |
| + SampleBuffer* sample_buffer_; |
| + DISALLOW_COPY_AND_ASSIGN(IsolateProfilerData); |
| +}; |
| + |
| + |
| +// Profile sample. |
| +struct Sample { |
| + static const char* kLookupSymbol; |
| + static const char* kNoSymbol; |
| + static const intptr_t kNumStackFrames = 4; |
| + enum SampleState { |
| + kIdle = 0, |
| + kExecuting = 1, |
| + kNumSampleStates |
| + }; |
| + int64_t timestamp; |
| + int64_t cpu_usage; |
| + uintptr_t pcs[kNumStackFrames]; |
| + uint16_t vm_tags; |
| + uint16_t runtime_tags; |
| + Sample(); |
| +}; |
| + |
| + |
| +// Ring buffer of samples. One per isolate. |
| +class SampleBuffer { |
| + public: |
| + static const intptr_t kDefaultBufferCapacity = 1000000; |
| + |
| + explicit SampleBuffer(intptr_t capacity = kDefaultBufferCapacity); |
| + ~SampleBuffer(); |
| + |
| + intptr_t capacity() const { return capacity_; } |
| + |
| + Sample* ReserveSample(); |
| + |
| + Sample* FirstSample() const; |
| + Sample* NextSample(Sample* sample) const; |
| + Sample* LastSample() const; |
| + private: |
| + Sample* samples_; |
| + intptr_t capacity_; |
| + intptr_t start_; |
| + intptr_t end_; |
| + |
| + intptr_t WrapIncrement(intptr_t i) const; |
| + 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_; |
| +}; |
| + |
| + |
| +} // namespace dart |
| + |
| +#endif // VM_PROFILER_H_ |