Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 #ifndef VM_HEAP_PROFILER_H_ | |
| 6 #define VM_HEAP_PROFILER_H_ | |
| 7 | |
| 8 #include <set> | |
| 9 | |
| 10 #include "include/dart_api.h" | |
| 11 #include "vm/globals.h" | |
| 12 #include "vm/handles.h" | |
| 13 #include "vm/object.h" | |
| 14 #include "vm/visitor.h" | |
| 15 | |
| 16 namespace dart { | |
| 17 | |
|
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.
| |
| 18 class HeapProfiler { | |
| 19 public: | |
| 20 HeapProfiler(Dart_HeapProfileWriteCallback callback, void* stream); | |
| 21 ~HeapProfiler(); | |
| 22 | |
| 23 // Writes a root to the heap dump. | |
| 24 void WriteRoot(const RawObject* raw_obj); | |
| 25 | |
| 26 // Writes a object to the heap dump. | |
| 27 void WriteObject(const RawObject* raw_obj); | |
| 28 | |
| 29 private: | |
| 30 // Record tags describe top-level records. | |
| 31 enum Tag { | |
| 32 kStringInUtf8 = 0x01, | |
| 33 kLoadClass = 0x02, | |
| 34 kUnloadClass = 0x03, | |
| 35 kStackFrame = 0x04, | |
| 36 kStackTrace = 0x05, | |
| 37 kAllocSites = 0x06, | |
| 38 kHeapSummary = 0x07, | |
| 39 kStartThread = 0x0A, | |
| 40 kEndThread = 0x0B, | |
| 41 kHeapDump = 0x0C, | |
| 42 kCpuSamples = 0x0D, | |
| 43 kControlSettings = 0x0E, | |
| 44 kHeapDumpSummary = 0x1C, | |
| 45 kHeapDumpEnd = 0x2C | |
| 46 }; | |
| 47 | |
| 48 // Sub-record tags describe sub-records within a heap dump. | |
| 49 enum Subtag { | |
| 50 kRootJniGlobal = 0x01, | |
| 51 kRootJniLocal = 0x01, | |
| 52 kRootJavaFrame = 0x03, | |
| 53 kRootNativeStack = 0x04, | |
| 54 kRootStickyClass = 0x05, | |
| 55 kRootThreadBlock = 0x06, | |
| 56 kRootMonitorUsed = 0x07, | |
| 57 kRootThreadObject = 0x08, | |
| 58 kClassDump = 0x20, | |
| 59 kInstanceDump = 0x21, | |
| 60 kObjectArrayDump = 0x22, | |
| 61 kPrimitiveArrayDump = 0x23, | |
| 62 kRootUnknown = 0xFF | |
| 63 }; | |
| 64 | |
| 65 // Tags for describing element and field types. | |
| 66 enum BasicType { | |
| 67 kObject = 2, | |
| 68 kBoolean = 4, | |
| 69 kChar = 5, | |
| 70 kFloat = 6, | |
| 71 kDouble = 7, | |
| 72 kByte = 8, | |
| 73 kShort = 9, | |
| 74 kInt = 10, | |
| 75 kLong = 11 | |
| 76 }; | |
| 77 | |
| 78 // A growable array of bytes used to build a record body. | |
| 79 class Buffer { | |
| 80 public: | |
| 81 Buffer() : data_(0), size_(0), capacity_(0) { | |
| 82 } | |
| 83 ~Buffer(); | |
| 84 | |
| 85 // Writes an array of bytes to the buffer, increasing the capacity | |
| 86 // as needed. | |
| 87 void Write(const uint8_t* data, intptr_t length); | |
| 88 | |
| 89 // Returns the underlying element storage. | |
| 90 const uint8_t* Data() const { | |
| 91 return data_; | |
| 92 } | |
| 93 | |
| 94 // Returns the number of elements written to the buffer. | |
| 95 intptr_t Size() const { | |
| 96 return size_; | |
| 97 } | |
| 98 | |
| 99 private: | |
| 100 // Resizes the element storage, if needed. | |
| 101 void EnsureCapacity(intptr_t size); | |
| 102 | |
| 103 uint8_t* data_; | |
| 104 | |
| 105 intptr_t size_; | |
| 106 | |
| 107 // Size of the element storage. | |
| 108 intptr_t capacity_; | |
| 109 | |
| 110 DISALLOW_COPY_AND_ASSIGN(Buffer); | |
| 111 }; | |
| 112 | |
| 113 // A top-level data record. | |
| 114 class Record { | |
| 115 public: | |
| 116 Record(uint8_t tag, HeapProfiler* profiler) | |
| 117 : tag_(tag), profiler_(profiler) { | |
| 118 } | |
| 119 ~Record() { | |
| 120 profiler_->WriteRecord(*this); | |
| 121 } | |
| 122 | |
| 123 // Returns the tag describing the record format. | |
| 124 uint8_t Tag() const { | |
| 125 return tag_; | |
| 126 } | |
| 127 | |
| 128 // Returns a millisecond time delta, always 0. | |
| 129 uint8_t Time() const { | |
| 130 return 0; | |
| 131 } | |
| 132 | |
| 133 // Returns the record length in bytes. | |
| 134 uint32_t Length() const { | |
| 135 return body_.Size(); | |
| 136 } | |
| 137 | |
| 138 // Returns the record body. | |
| 139 const uint8_t* Body() const { | |
| 140 return body_.Data(); | |
| 141 } | |
| 142 | |
| 143 // Appends an array of 8-bit values to the record body. | |
| 144 void Write(const uint8_t* value, intptr_t size); | |
| 145 | |
| 146 // Appends an 8-, 16-, 32- or 64-bit value to the body in | |
| 147 // big-endian format. | |
| 148 void Write8(uint8_t value); | |
| 149 void Write16(uint16_t value); | |
| 150 void Write32(uint32_t value); | |
| 151 void Write64(uint64_t value); | |
| 152 | |
| 153 // Appends an ID to the body. | |
| 154 void WritePointer(const void* value); | |
| 155 | |
| 156 private: | |
| 157 // A tag value that describes the record format. | |
| 158 uint8_t tag_; | |
| 159 | |
| 160 // The payload of the record as described by the tag. | |
| 161 Buffer body_; | |
| 162 | |
| 163 // Parent object. | |
| 164 HeapProfiler* profiler_; | |
| 165 | |
| 166 DISALLOW_COPY_AND_ASSIGN(Record); | |
| 167 }; | |
| 168 | |
| 169 // A sub-record within a heap dump record. Write calls are | |
| 170 // forwarded to the profilers heap dump record instance. | |
| 171 class SubRecord { | |
| 172 public: | |
| 173 // Starts a new sub-record within the heap dump record. | |
| 174 SubRecord(uint8_t sub_tag, HeapProfiler* profiler); | |
| 175 ~SubRecord(); | |
| 176 | |
| 177 // Appends an array of 8-bit values to the heap dump record. | |
| 178 void Write(const uint8_t* value, intptr_t size); | |
| 179 | |
| 180 // Appends an 8-, 16-, 32- or 64-bit value to the heap dump | |
| 181 // record. | |
| 182 void Write8(uint8_t value); | |
| 183 void Write16(uint16_t value); | |
| 184 void Write32(uint32_t value); | |
| 185 void Write64(uint64_t value); | |
| 186 | |
| 187 // Appends an ID to the current heap dump record. | |
| 188 void WritePointer(const void* value); | |
| 189 | |
| 190 private: | |
| 191 // The record instance that receives forwarded write calls. | |
| 192 Record* record_; | |
| 193 }; | |
| 194 | |
| 195 // Id canonizers. | |
| 196 const RawClass* ClassId(const RawClass* raw_class); | |
| 197 const RawObject* ObjectId(const RawObject* raw_obj); | |
| 198 const char* StringId(const char* c_string); | |
| 199 const RawString* StringId(const RawString* raw_string); | |
| 200 | |
| 201 // Invokes the write callback. | |
| 202 void Write(const void* data, intptr_t size); | |
| 203 | |
| 204 // Writes the binary hprof header to the output stream. | |
| 205 void WriteHeader(); | |
| 206 | |
| 207 // Writes a record to the output stream. | |
| 208 void WriteRecord(const Record& record); | |
| 209 | |
| 210 | |
| 211 // Writes a string in utf-8 record to the output stream. | |
| 212 void WriteStringInUtf8(const char* c_string); | |
| 213 void WriteStringInUtf8(const RawString* raw_string); | |
| 214 | |
| 215 | |
| 216 // Writes a load class record to the output stream. | |
| 217 void WriteLoadClass(const RawClass* raw_class); | |
| 218 | |
| 219 // Writes an empty stack trace to the output stream. | |
| 220 void WriteStackTrace(); | |
| 221 | |
| 222 // Writes a heap summary record to the output stream. | |
| 223 void WriteHeapSummary(uint32_t total_live_bytes, | |
| 224 uint32_t total_live_instances, | |
| 225 uint64_t total_bytes_allocated, | |
| 226 uint64_t total_instances_allocated); | |
| 227 | |
| 228 // Writes a heap dump record to the output stream. | |
| 229 void WriteHeapDump(); | |
| 230 | |
| 231 // Writes a sub-record to the heap dump record. | |
| 232 void WriteClassDump(const RawClass* raw_class); | |
| 233 void WriteInstanceDump(const RawObject* raw_obj); | |
| 234 void WriteObjectArrayDump(const RawArray* raw_array); | |
| 235 void WritePrimitiveArrayDump(const RawByteArray* raw_byte_array, | |
| 236 uint8_t tag, | |
| 237 const void* data); | |
| 238 | |
| 239 Dart_HeapProfileWriteCallback write_callback_; | |
| 240 | |
| 241 void* output_stream_; | |
| 242 | |
| 243 Record* heap_dump_record_; | |
| 244 | |
| 245 std::set<const RawSmi*> smi_table_; | |
| 246 std::set<const RawClass*> class_table_; | |
| 247 std::set<const RawString*> string_table_; | |
| 248 | |
| 249 DISALLOW_COPY_AND_ASSIGN(HeapProfiler); | |
| 250 }; | |
| 251 | |
| 252 | |
| 253 // Writes a root sub-record to the heap dump for every strong handle. | |
| 254 class HeapProfilerRootVisitor : public ObjectPointerVisitor { | |
| 255 public: | |
| 256 explicit HeapProfilerRootVisitor(HeapProfiler* profiler) | |
| 257 : profiler_(profiler) { | |
| 258 } | |
| 259 | |
| 260 virtual void VisitPointers(RawObject** first, RawObject** last); | |
| 261 | |
| 262 private: | |
| 263 HeapProfiler* profiler_; | |
| 264 DISALLOW_COPY_AND_ASSIGN(HeapProfilerRootVisitor); | |
| 265 }; | |
| 266 | |
| 267 | |
| 268 // Writes a root sub-record to the heap dump for every weak handle. | |
| 269 class HeapProfilerWeakRootVisitor : public HandleVisitor { | |
| 270 public: | |
| 271 explicit HeapProfilerWeakRootVisitor(HeapProfilerRootVisitor* visitor) | |
| 272 : visitor_(visitor) { | |
| 273 } | |
| 274 | |
| 275 virtual void VisitHandle(uword addr); | |
| 276 | |
| 277 private: | |
| 278 HeapProfilerRootVisitor* visitor_; | |
| 279 DISALLOW_COPY_AND_ASSIGN(HeapProfilerWeakRootVisitor); | |
| 280 }; | |
| 281 | |
| 282 | |
| 283 // Writes a sub-record to the heap dump for every object in the heap. | |
| 284 class HeapProfilerObjectVisitor : public ObjectVisitor { | |
| 285 public: | |
| 286 explicit HeapProfilerObjectVisitor(HeapProfiler* profiler) | |
| 287 : profiler_(profiler) { | |
| 288 } | |
| 289 | |
| 290 virtual void VisitObject(RawObject* obj); | |
| 291 | |
| 292 private: | |
| 293 HeapProfiler* profiler_; | |
| 294 DISALLOW_COPY_AND_ASSIGN(HeapProfilerObjectVisitor); | |
| 295 }; | |
| 296 | |
| 297 } // namespace dart | |
| 298 | |
| 299 #endif // VM_HEAP_PROFILER_H_ | |
| OLD | NEW |