Chromium Code Reviews| Index: runtime/vm/heap_profiler.h |
| diff --git a/runtime/vm/heap_profiler.h b/runtime/vm/heap_profiler.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..660d9f9328f604d07c9ea93d5b1c6d6dce9f5d07 |
| --- /dev/null |
| +++ b/runtime/vm/heap_profiler.h |
| @@ -0,0 +1,299 @@ |
| +// Copyright (c) 2012, 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_HEAP_PROFILER_H_ |
| +#define VM_HEAP_PROFILER_H_ |
| + |
| +#include <set> |
| + |
| +#include "include/dart_api.h" |
| +#include "vm/globals.h" |
| +#include "vm/handles.h" |
| +#include "vm/object.h" |
| +#include "vm/visitor.h" |
| + |
| +namespace dart { |
| + |
|
turnidge
2012/05/29 17:50:01
Maybe add a top-level comment describing what the
cshapiro
2012/06/01 04:27:02
A great idea. Done.
|
| +class HeapProfiler { |
| + public: |
| + HeapProfiler(Dart_HeapProfileWriteCallback callback, void* stream); |
| + ~HeapProfiler(); |
| + |
| + // Writes a root to the heap dump. |
| + void WriteRoot(const RawObject* raw_obj); |
| + |
| + // Writes a object to the heap dump. |
| + void WriteObject(const RawObject* raw_obj); |
| + |
| + private: |
| + // Record tags describe top-level records. |
| + enum Tag { |
| + kStringInUtf8 = 0x01, |
| + kLoadClass = 0x02, |
| + kUnloadClass = 0x03, |
| + kStackFrame = 0x04, |
| + kStackTrace = 0x05, |
| + kAllocSites = 0x06, |
| + kHeapSummary = 0x07, |
| + kStartThread = 0x0A, |
| + kEndThread = 0x0B, |
| + kHeapDump = 0x0C, |
| + kCpuSamples = 0x0D, |
| + kControlSettings = 0x0E, |
| + kHeapDumpSummary = 0x1C, |
| + kHeapDumpEnd = 0x2C |
| + }; |
| + |
| + // Sub-record tags describe sub-records within a heap dump. |
| + enum Subtag { |
| + kRootJniGlobal = 0x01, |
| + kRootJniLocal = 0x01, |
| + kRootJavaFrame = 0x03, |
| + kRootNativeStack = 0x04, |
| + kRootStickyClass = 0x05, |
| + kRootThreadBlock = 0x06, |
| + kRootMonitorUsed = 0x07, |
| + kRootThreadObject = 0x08, |
| + kClassDump = 0x20, |
| + kInstanceDump = 0x21, |
| + kObjectArrayDump = 0x22, |
| + kPrimitiveArrayDump = 0x23, |
| + kRootUnknown = 0xFF |
| + }; |
| + |
| + // Tags for describing element and field types. |
| + enum BasicType { |
| + kObject = 2, |
| + kBoolean = 4, |
| + kChar = 5, |
| + kFloat = 6, |
| + kDouble = 7, |
| + kByte = 8, |
| + kShort = 9, |
| + kInt = 10, |
| + kLong = 11 |
| + }; |
| + |
| + // A growable array of bytes used to build a record body. |
| + class Buffer { |
| + public: |
| + Buffer() : data_(0), size_(0), capacity_(0) { |
| + } |
| + ~Buffer(); |
| + |
| + // Writes an array of bytes to the buffer, increasing the capacity |
| + // as needed. |
| + void Write(const uint8_t* data, intptr_t length); |
| + |
| + // Returns the underlying element storage. |
| + const uint8_t* Data() const { |
| + return data_; |
| + } |
| + |
| + // Returns the number of elements written to the buffer. |
| + intptr_t Size() const { |
| + return size_; |
| + } |
| + |
| + private: |
| + // Resizes the element storage, if needed. |
| + void EnsureCapacity(intptr_t size); |
| + |
| + uint8_t* data_; |
| + |
| + intptr_t size_; |
| + |
| + // Size of the element storage. |
| + intptr_t capacity_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(Buffer); |
| + }; |
| + |
| + // A top-level data record. |
| + class Record { |
| + public: |
| + Record(uint8_t tag, HeapProfiler* profiler) |
| + : tag_(tag), profiler_(profiler) { |
| + } |
| + ~Record() { |
| + profiler_->WriteRecord(*this); |
| + } |
| + |
| + // Returns the tag describing the record format. |
| + uint8_t Tag() const { |
| + return tag_; |
| + } |
| + |
| + // Returns a millisecond time delta, always 0. |
| + uint8_t Time() const { |
| + return 0; |
| + } |
| + |
| + // Returns the record length in bytes. |
| + uint32_t Length() const { |
| + return body_.Size(); |
| + } |
| + |
| + // Returns the record body. |
| + const uint8_t* Body() const { |
| + return body_.Data(); |
| + } |
| + |
| + // Appends an array of 8-bit values to the record body. |
| + void Write(const uint8_t* value, intptr_t size); |
| + |
| + // Appends an 8-, 16-, 32- or 64-bit value to the body in |
| + // big-endian format. |
| + void Write8(uint8_t value); |
| + void Write16(uint16_t value); |
| + void Write32(uint32_t value); |
| + void Write64(uint64_t value); |
| + |
| + // Appends an ID to the body. |
| + void WritePointer(const void* value); |
| + |
| + private: |
| + // A tag value that describes the record format. |
| + uint8_t tag_; |
| + |
| + // The payload of the record as described by the tag. |
| + Buffer body_; |
| + |
| + // Parent object. |
| + HeapProfiler* profiler_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(Record); |
| + }; |
| + |
| + // A sub-record within a heap dump record. Write calls are |
| + // forwarded to the profilers heap dump record instance. |
| + class SubRecord { |
| + public: |
| + // Starts a new sub-record within the heap dump record. |
| + SubRecord(uint8_t sub_tag, HeapProfiler* profiler); |
| + ~SubRecord(); |
| + |
| + // Appends an array of 8-bit values to the heap dump record. |
| + void Write(const uint8_t* value, intptr_t size); |
| + |
| + // Appends an 8-, 16-, 32- or 64-bit value to the heap dump |
| + // record. |
| + void Write8(uint8_t value); |
| + void Write16(uint16_t value); |
| + void Write32(uint32_t value); |
| + void Write64(uint64_t value); |
| + |
| + // Appends an ID to the current heap dump record. |
| + void WritePointer(const void* value); |
| + |
| + private: |
| + // The record instance that receives forwarded write calls. |
| + Record* record_; |
| + }; |
| + |
| + // Id canonizers. |
| + const RawClass* ClassId(const RawClass* raw_class); |
| + const RawObject* ObjectId(const RawObject* raw_obj); |
| + const char* StringId(const char* c_string); |
| + const RawString* StringId(const RawString* raw_string); |
| + |
| + // Invokes the write callback. |
| + void Write(const void* data, intptr_t size); |
| + |
| + // Writes the binary hprof header to the output stream. |
| + void WriteHeader(); |
| + |
| + // Writes a record to the output stream. |
| + void WriteRecord(const Record& record); |
| + |
| + |
| + // Writes a string in utf-8 record to the output stream. |
| + void WriteStringInUtf8(const char* c_string); |
| + void WriteStringInUtf8(const RawString* raw_string); |
| + |
| + |
| + // Writes a load class record to the output stream. |
| + void WriteLoadClass(const RawClass* raw_class); |
| + |
| + // Writes an empty stack trace to the output stream. |
| + void WriteStackTrace(); |
| + |
| + // Writes a heap summary record to the output stream. |
| + void WriteHeapSummary(uint32_t total_live_bytes, |
| + uint32_t total_live_instances, |
| + uint64_t total_bytes_allocated, |
| + uint64_t total_instances_allocated); |
| + |
| + // Writes a heap dump record to the output stream. |
| + void WriteHeapDump(); |
| + |
| + // Writes a sub-record to the heap dump record. |
| + void WriteClassDump(const RawClass* raw_class); |
| + void WriteInstanceDump(const RawObject* raw_obj); |
| + void WriteObjectArrayDump(const RawArray* raw_array); |
| + void WritePrimitiveArrayDump(const RawByteArray* raw_byte_array, |
| + uint8_t tag, |
| + const void* data); |
| + |
| + Dart_HeapProfileWriteCallback write_callback_; |
| + |
| + void* output_stream_; |
| + |
| + Record* heap_dump_record_; |
| + |
| + std::set<const RawSmi*> smi_table_; |
| + std::set<const RawClass*> class_table_; |
| + std::set<const RawString*> string_table_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(HeapProfiler); |
| +}; |
| + |
| + |
| +// Writes a root sub-record to the heap dump for every strong handle. |
| +class HeapProfilerRootVisitor : public ObjectPointerVisitor { |
| + public: |
| + explicit HeapProfilerRootVisitor(HeapProfiler* profiler) |
| + : profiler_(profiler) { |
| + } |
| + |
| + virtual void VisitPointers(RawObject** first, RawObject** last); |
| + |
| + private: |
| + HeapProfiler* profiler_; |
| + DISALLOW_COPY_AND_ASSIGN(HeapProfilerRootVisitor); |
| +}; |
| + |
| + |
| +// Writes a root sub-record to the heap dump for every weak handle. |
| +class HeapProfilerWeakRootVisitor : public HandleVisitor { |
| + public: |
| + explicit HeapProfilerWeakRootVisitor(HeapProfilerRootVisitor* visitor) |
| + : visitor_(visitor) { |
| + } |
| + |
| + virtual void VisitHandle(uword addr); |
| + |
| + private: |
| + HeapProfilerRootVisitor* visitor_; |
| + DISALLOW_COPY_AND_ASSIGN(HeapProfilerWeakRootVisitor); |
| +}; |
| + |
| + |
| +// Writes a sub-record to the heap dump for every object in the heap. |
| +class HeapProfilerObjectVisitor : public ObjectVisitor { |
| + public: |
| + explicit HeapProfilerObjectVisitor(HeapProfiler* profiler) |
| + : profiler_(profiler) { |
| + } |
| + |
| + virtual void VisitObject(RawObject* obj); |
| + |
| + private: |
| + HeapProfiler* profiler_; |
| + DISALLOW_COPY_AND_ASSIGN(HeapProfilerObjectVisitor); |
| +}; |
| + |
| +} // namespace dart |
| + |
| +#endif // VM_HEAP_PROFILER_H_ |