| OLD | NEW |
| (Empty) |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #ifndef V8_HEAP_SNAPSHOT_GENERATOR_H_ | |
| 6 #define V8_HEAP_SNAPSHOT_GENERATOR_H_ | |
| 7 | |
| 8 #include "include/v8-profiler.h" | |
| 9 #include "src/base/platform/time.h" | |
| 10 #include "src/objects.h" | |
| 11 #include "src/strings-storage.h" | |
| 12 | |
| 13 namespace v8 { | |
| 14 namespace internal { | |
| 15 | |
| 16 class AllocationTracker; | |
| 17 class AllocationTraceNode; | |
| 18 class HeapEntry; | |
| 19 class HeapIterator; | |
| 20 class HeapProfiler; | |
| 21 class HeapSnapshot; | |
| 22 class SnapshotFiller; | |
| 23 | |
| 24 class HeapGraphEdge BASE_EMBEDDED { | |
| 25 public: | |
| 26 enum Type { | |
| 27 kContextVariable = v8::HeapGraphEdge::kContextVariable, | |
| 28 kElement = v8::HeapGraphEdge::kElement, | |
| 29 kProperty = v8::HeapGraphEdge::kProperty, | |
| 30 kInternal = v8::HeapGraphEdge::kInternal, | |
| 31 kHidden = v8::HeapGraphEdge::kHidden, | |
| 32 kShortcut = v8::HeapGraphEdge::kShortcut, | |
| 33 kWeak = v8::HeapGraphEdge::kWeak | |
| 34 }; | |
| 35 | |
| 36 HeapGraphEdge(Type type, const char* name, int from, int to); | |
| 37 HeapGraphEdge(Type type, int index, int from, int to); | |
| 38 void ReplaceToIndexWithEntry(HeapSnapshot* snapshot); | |
| 39 | |
| 40 Type type() const { return TypeField::decode(bit_field_); } | |
| 41 int index() const { | |
| 42 DCHECK(type() == kElement || type() == kHidden); | |
| 43 return index_; | |
| 44 } | |
| 45 const char* name() const { | |
| 46 DCHECK(type() == kContextVariable || type() == kProperty || | |
| 47 type() == kInternal || type() == kShortcut || type() == kWeak); | |
| 48 return name_; | |
| 49 } | |
| 50 INLINE(HeapEntry* from() const); | |
| 51 HeapEntry* to() const { return to_entry_; } | |
| 52 | |
| 53 private: | |
| 54 INLINE(HeapSnapshot* snapshot() const); | |
| 55 int from_index() const { return FromIndexField::decode(bit_field_); } | |
| 56 | |
| 57 class TypeField : public BitField<Type, 0, 3> {}; | |
| 58 class FromIndexField : public BitField<int, 3, 29> {}; | |
| 59 uint32_t bit_field_; | |
| 60 union { | |
| 61 // During entries population |to_index_| is used for storing the index, | |
| 62 // afterwards it is replaced with a pointer to the entry. | |
| 63 int to_index_; | |
| 64 HeapEntry* to_entry_; | |
| 65 }; | |
| 66 union { | |
| 67 int index_; | |
| 68 const char* name_; | |
| 69 }; | |
| 70 }; | |
| 71 | |
| 72 | |
| 73 // HeapEntry instances represent an entity from the heap (or a special | |
| 74 // virtual node, e.g. root). | |
| 75 class HeapEntry BASE_EMBEDDED { | |
| 76 public: | |
| 77 enum Type { | |
| 78 kHidden = v8::HeapGraphNode::kHidden, | |
| 79 kArray = v8::HeapGraphNode::kArray, | |
| 80 kString = v8::HeapGraphNode::kString, | |
| 81 kObject = v8::HeapGraphNode::kObject, | |
| 82 kCode = v8::HeapGraphNode::kCode, | |
| 83 kClosure = v8::HeapGraphNode::kClosure, | |
| 84 kRegExp = v8::HeapGraphNode::kRegExp, | |
| 85 kHeapNumber = v8::HeapGraphNode::kHeapNumber, | |
| 86 kNative = v8::HeapGraphNode::kNative, | |
| 87 kSynthetic = v8::HeapGraphNode::kSynthetic, | |
| 88 kConsString = v8::HeapGraphNode::kConsString, | |
| 89 kSlicedString = v8::HeapGraphNode::kSlicedString, | |
| 90 kSymbol = v8::HeapGraphNode::kSymbol, | |
| 91 kSimdValue = v8::HeapGraphNode::kSimdValue | |
| 92 }; | |
| 93 static const int kNoEntry; | |
| 94 | |
| 95 HeapEntry() { } | |
| 96 HeapEntry(HeapSnapshot* snapshot, | |
| 97 Type type, | |
| 98 const char* name, | |
| 99 SnapshotObjectId id, | |
| 100 size_t self_size, | |
| 101 unsigned trace_node_id); | |
| 102 | |
| 103 HeapSnapshot* snapshot() { return snapshot_; } | |
| 104 Type type() { return static_cast<Type>(type_); } | |
| 105 const char* name() { return name_; } | |
| 106 void set_name(const char* name) { name_ = name; } | |
| 107 SnapshotObjectId id() { return id_; } | |
| 108 size_t self_size() { return self_size_; } | |
| 109 unsigned trace_node_id() const { return trace_node_id_; } | |
| 110 INLINE(int index() const); | |
| 111 int children_count() const { return children_count_; } | |
| 112 INLINE(int set_children_index(int index)); | |
| 113 void add_child(HeapGraphEdge* edge) { | |
| 114 children_arr()[children_count_++] = edge; | |
| 115 } | |
| 116 Vector<HeapGraphEdge*> children() { | |
| 117 return Vector<HeapGraphEdge*>(children_arr(), children_count_); } | |
| 118 | |
| 119 void SetIndexedReference( | |
| 120 HeapGraphEdge::Type type, int index, HeapEntry* entry); | |
| 121 void SetNamedReference( | |
| 122 HeapGraphEdge::Type type, const char* name, HeapEntry* entry); | |
| 123 | |
| 124 void Print( | |
| 125 const char* prefix, const char* edge_name, int max_depth, int indent); | |
| 126 | |
| 127 private: | |
| 128 INLINE(HeapGraphEdge** children_arr()); | |
| 129 const char* TypeAsString(); | |
| 130 | |
| 131 unsigned type_: 4; | |
| 132 int children_count_: 28; | |
| 133 int children_index_; | |
| 134 size_t self_size_; | |
| 135 HeapSnapshot* snapshot_; | |
| 136 const char* name_; | |
| 137 SnapshotObjectId id_; | |
| 138 // id of allocation stack trace top node | |
| 139 unsigned trace_node_id_; | |
| 140 }; | |
| 141 | |
| 142 | |
| 143 // HeapSnapshot represents a single heap snapshot. It is stored in | |
| 144 // HeapProfiler, which is also a factory for | |
| 145 // HeapSnapshots. All HeapSnapshots share strings copied from JS heap | |
| 146 // to be able to return them even if they were collected. | |
| 147 // HeapSnapshotGenerator fills in a HeapSnapshot. | |
| 148 class HeapSnapshot { | |
| 149 public: | |
| 150 explicit HeapSnapshot(HeapProfiler* profiler); | |
| 151 void Delete(); | |
| 152 | |
| 153 HeapProfiler* profiler() { return profiler_; } | |
| 154 size_t RawSnapshotSize() const; | |
| 155 HeapEntry* root() { return &entries_[root_index_]; } | |
| 156 HeapEntry* gc_roots() { return &entries_[gc_roots_index_]; } | |
| 157 HeapEntry* gc_subroot(int index) { | |
| 158 return &entries_[gc_subroot_indexes_[index]]; | |
| 159 } | |
| 160 List<HeapEntry>& entries() { return entries_; } | |
| 161 List<HeapGraphEdge>& edges() { return edges_; } | |
| 162 List<HeapGraphEdge*>& children() { return children_; } | |
| 163 void RememberLastJSObjectId(); | |
| 164 SnapshotObjectId max_snapshot_js_object_id() const { | |
| 165 return max_snapshot_js_object_id_; | |
| 166 } | |
| 167 | |
| 168 HeapEntry* AddEntry(HeapEntry::Type type, | |
| 169 const char* name, | |
| 170 SnapshotObjectId id, | |
| 171 size_t size, | |
| 172 unsigned trace_node_id); | |
| 173 void AddSyntheticRootEntries(); | |
| 174 HeapEntry* GetEntryById(SnapshotObjectId id); | |
| 175 List<HeapEntry*>* GetSortedEntriesList(); | |
| 176 void FillChildren(); | |
| 177 | |
| 178 void Print(int max_depth); | |
| 179 | |
| 180 private: | |
| 181 HeapEntry* AddRootEntry(); | |
| 182 HeapEntry* AddGcRootsEntry(); | |
| 183 HeapEntry* AddGcSubrootEntry(int tag, SnapshotObjectId id); | |
| 184 | |
| 185 HeapProfiler* profiler_; | |
| 186 int root_index_; | |
| 187 int gc_roots_index_; | |
| 188 int gc_subroot_indexes_[VisitorSynchronization::kNumberOfSyncTags]; | |
| 189 List<HeapEntry> entries_; | |
| 190 List<HeapGraphEdge> edges_; | |
| 191 List<HeapGraphEdge*> children_; | |
| 192 List<HeapEntry*> sorted_entries_; | |
| 193 SnapshotObjectId max_snapshot_js_object_id_; | |
| 194 | |
| 195 friend class HeapSnapshotTester; | |
| 196 | |
| 197 DISALLOW_COPY_AND_ASSIGN(HeapSnapshot); | |
| 198 }; | |
| 199 | |
| 200 | |
| 201 class HeapObjectsMap { | |
| 202 public: | |
| 203 struct TimeInterval { | |
| 204 explicit TimeInterval(SnapshotObjectId id) | |
| 205 : id(id), size(0), count(0), timestamp(base::TimeTicks::Now()) {} | |
| 206 SnapshotObjectId last_assigned_id() const { return id - kObjectIdStep; } | |
| 207 SnapshotObjectId id; | |
| 208 uint32_t size; | |
| 209 uint32_t count; | |
| 210 base::TimeTicks timestamp; | |
| 211 }; | |
| 212 | |
| 213 explicit HeapObjectsMap(Heap* heap); | |
| 214 | |
| 215 Heap* heap() const { return heap_; } | |
| 216 | |
| 217 SnapshotObjectId FindEntry(Address addr); | |
| 218 SnapshotObjectId FindOrAddEntry(Address addr, | |
| 219 unsigned int size, | |
| 220 bool accessed = true); | |
| 221 bool MoveObject(Address from, Address to, int size); | |
| 222 void UpdateObjectSize(Address addr, int size); | |
| 223 SnapshotObjectId last_assigned_id() const { | |
| 224 return next_id_ - kObjectIdStep; | |
| 225 } | |
| 226 | |
| 227 void StopHeapObjectsTracking(); | |
| 228 SnapshotObjectId PushHeapObjectsStats(OutputStream* stream, | |
| 229 int64_t* timestamp_us); | |
| 230 const List<TimeInterval>& samples() const { return time_intervals_; } | |
| 231 size_t GetUsedMemorySize() const; | |
| 232 | |
| 233 SnapshotObjectId GenerateId(v8::RetainedObjectInfo* info); | |
| 234 | |
| 235 static const int kObjectIdStep = 2; | |
| 236 static const SnapshotObjectId kInternalRootObjectId; | |
| 237 static const SnapshotObjectId kGcRootsObjectId; | |
| 238 static const SnapshotObjectId kGcRootsFirstSubrootId; | |
| 239 static const SnapshotObjectId kFirstAvailableObjectId; | |
| 240 | |
| 241 int FindUntrackedObjects(); | |
| 242 | |
| 243 void UpdateHeapObjectsMap(); | |
| 244 void RemoveDeadEntries(); | |
| 245 | |
| 246 private: | |
| 247 struct EntryInfo { | |
| 248 EntryInfo(SnapshotObjectId id, Address addr, unsigned int size) | |
| 249 : id(id), addr(addr), size(size), accessed(true) { } | |
| 250 EntryInfo(SnapshotObjectId id, Address addr, unsigned int size, bool accessed) | |
| 251 : id(id), addr(addr), size(size), accessed(accessed) { } | |
| 252 SnapshotObjectId id; | |
| 253 Address addr; | |
| 254 unsigned int size; | |
| 255 bool accessed; | |
| 256 }; | |
| 257 | |
| 258 SnapshotObjectId next_id_; | |
| 259 HashMap entries_map_; | |
| 260 List<EntryInfo> entries_; | |
| 261 List<TimeInterval> time_intervals_; | |
| 262 Heap* heap_; | |
| 263 | |
| 264 DISALLOW_COPY_AND_ASSIGN(HeapObjectsMap); | |
| 265 }; | |
| 266 | |
| 267 | |
| 268 // A typedef for referencing anything that can be snapshotted living | |
| 269 // in any kind of heap memory. | |
| 270 typedef void* HeapThing; | |
| 271 | |
| 272 | |
| 273 // An interface that creates HeapEntries by HeapThings. | |
| 274 class HeapEntriesAllocator { | |
| 275 public: | |
| 276 virtual ~HeapEntriesAllocator() { } | |
| 277 virtual HeapEntry* AllocateEntry(HeapThing ptr) = 0; | |
| 278 }; | |
| 279 | |
| 280 | |
| 281 // The HeapEntriesMap instance is used to track a mapping between | |
| 282 // real heap objects and their representations in heap snapshots. | |
| 283 class HeapEntriesMap { | |
| 284 public: | |
| 285 HeapEntriesMap(); | |
| 286 | |
| 287 int Map(HeapThing thing); | |
| 288 void Pair(HeapThing thing, int entry); | |
| 289 | |
| 290 private: | |
| 291 static uint32_t Hash(HeapThing thing) { | |
| 292 return ComputeIntegerHash( | |
| 293 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(thing)), | |
| 294 v8::internal::kZeroHashSeed); | |
| 295 } | |
| 296 | |
| 297 HashMap entries_; | |
| 298 | |
| 299 friend class HeapObjectsSet; | |
| 300 | |
| 301 DISALLOW_COPY_AND_ASSIGN(HeapEntriesMap); | |
| 302 }; | |
| 303 | |
| 304 | |
| 305 class HeapObjectsSet { | |
| 306 public: | |
| 307 HeapObjectsSet(); | |
| 308 void Clear(); | |
| 309 bool Contains(Object* object); | |
| 310 void Insert(Object* obj); | |
| 311 const char* GetTag(Object* obj); | |
| 312 void SetTag(Object* obj, const char* tag); | |
| 313 bool is_empty() const { return entries_.occupancy() == 0; } | |
| 314 | |
| 315 private: | |
| 316 HashMap entries_; | |
| 317 | |
| 318 DISALLOW_COPY_AND_ASSIGN(HeapObjectsSet); | |
| 319 }; | |
| 320 | |
| 321 | |
| 322 class SnapshottingProgressReportingInterface { | |
| 323 public: | |
| 324 virtual ~SnapshottingProgressReportingInterface() { } | |
| 325 virtual void ProgressStep() = 0; | |
| 326 virtual bool ProgressReport(bool force) = 0; | |
| 327 }; | |
| 328 | |
| 329 | |
| 330 // An implementation of V8 heap graph extractor. | |
| 331 class V8HeapExplorer : public HeapEntriesAllocator { | |
| 332 public: | |
| 333 V8HeapExplorer(HeapSnapshot* snapshot, | |
| 334 SnapshottingProgressReportingInterface* progress, | |
| 335 v8::HeapProfiler::ObjectNameResolver* resolver); | |
| 336 virtual ~V8HeapExplorer(); | |
| 337 virtual HeapEntry* AllocateEntry(HeapThing ptr); | |
| 338 int EstimateObjectsCount(HeapIterator* iterator); | |
| 339 bool IterateAndExtractReferences(SnapshotFiller* filler); | |
| 340 void TagGlobalObjects(); | |
| 341 void TagCodeObject(Code* code); | |
| 342 void TagBuiltinCodeObject(Code* code, const char* name); | |
| 343 HeapEntry* AddEntry(Address address, | |
| 344 HeapEntry::Type type, | |
| 345 const char* name, | |
| 346 size_t size); | |
| 347 | |
| 348 static String* GetConstructorName(JSObject* object); | |
| 349 | |
| 350 private: | |
| 351 typedef bool (V8HeapExplorer::*ExtractReferencesMethod)(int entry, | |
| 352 HeapObject* object); | |
| 353 | |
| 354 HeapEntry* AddEntry(HeapObject* object); | |
| 355 HeapEntry* AddEntry(HeapObject* object, | |
| 356 HeapEntry::Type type, | |
| 357 const char* name); | |
| 358 | |
| 359 const char* GetSystemEntryName(HeapObject* object); | |
| 360 | |
| 361 template<V8HeapExplorer::ExtractReferencesMethod extractor> | |
| 362 bool IterateAndExtractSinglePass(); | |
| 363 | |
| 364 bool ExtractReferencesPass1(int entry, HeapObject* obj); | |
| 365 bool ExtractReferencesPass2(int entry, HeapObject* obj); | |
| 366 void ExtractJSGlobalProxyReferences(int entry, JSGlobalProxy* proxy); | |
| 367 void ExtractJSObjectReferences(int entry, JSObject* js_obj); | |
| 368 void ExtractStringReferences(int entry, String* obj); | |
| 369 void ExtractSymbolReferences(int entry, Symbol* symbol); | |
| 370 void ExtractJSCollectionReferences(int entry, JSCollection* collection); | |
| 371 void ExtractJSWeakCollectionReferences(int entry, | |
| 372 JSWeakCollection* collection); | |
| 373 void ExtractContextReferences(int entry, Context* context); | |
| 374 void ExtractMapReferences(int entry, Map* map); | |
| 375 void ExtractSharedFunctionInfoReferences(int entry, | |
| 376 SharedFunctionInfo* shared); | |
| 377 void ExtractScriptReferences(int entry, Script* script); | |
| 378 void ExtractAccessorInfoReferences(int entry, AccessorInfo* accessor_info); | |
| 379 void ExtractAccessorPairReferences(int entry, AccessorPair* accessors); | |
| 380 void ExtractCodeCacheReferences(int entry, CodeCache* code_cache); | |
| 381 void ExtractCodeReferences(int entry, Code* code); | |
| 382 void ExtractBoxReferences(int entry, Box* box); | |
| 383 void ExtractCellReferences(int entry, Cell* cell); | |
| 384 void ExtractPropertyCellReferences(int entry, PropertyCell* cell); | |
| 385 void ExtractAllocationSiteReferences(int entry, AllocationSite* site); | |
| 386 void ExtractJSArrayBufferReferences(int entry, JSArrayBuffer* buffer); | |
| 387 void ExtractFixedArrayReferences(int entry, FixedArray* array); | |
| 388 void ExtractClosureReferences(JSObject* js_obj, int entry); | |
| 389 void ExtractPropertyReferences(JSObject* js_obj, int entry); | |
| 390 void ExtractAccessorPairProperty(JSObject* js_obj, int entry, Name* key, | |
| 391 Object* callback_obj, int field_offset = -1); | |
| 392 void ExtractElementReferences(JSObject* js_obj, int entry); | |
| 393 void ExtractInternalReferences(JSObject* js_obj, int entry); | |
| 394 | |
| 395 bool IsEssentialObject(Object* object); | |
| 396 void SetContextReference(HeapObject* parent_obj, | |
| 397 int parent, | |
| 398 String* reference_name, | |
| 399 Object* child, | |
| 400 int field_offset); | |
| 401 void SetNativeBindReference(HeapObject* parent_obj, | |
| 402 int parent, | |
| 403 const char* reference_name, | |
| 404 Object* child); | |
| 405 void SetElementReference(HeapObject* parent_obj, | |
| 406 int parent, | |
| 407 int index, | |
| 408 Object* child); | |
| 409 void SetInternalReference(HeapObject* parent_obj, | |
| 410 int parent, | |
| 411 const char* reference_name, | |
| 412 Object* child, | |
| 413 int field_offset = -1); | |
| 414 void SetInternalReference(HeapObject* parent_obj, | |
| 415 int parent, | |
| 416 int index, | |
| 417 Object* child, | |
| 418 int field_offset = -1); | |
| 419 void SetHiddenReference(HeapObject* parent_obj, | |
| 420 int parent, | |
| 421 int index, | |
| 422 Object* child); | |
| 423 void SetWeakReference(HeapObject* parent_obj, | |
| 424 int parent, | |
| 425 const char* reference_name, | |
| 426 Object* child_obj, | |
| 427 int field_offset); | |
| 428 void SetWeakReference(HeapObject* parent_obj, | |
| 429 int parent, | |
| 430 int index, | |
| 431 Object* child_obj, | |
| 432 int field_offset); | |
| 433 void SetPropertyReference(HeapObject* parent_obj, | |
| 434 int parent, | |
| 435 Name* reference_name, | |
| 436 Object* child, | |
| 437 const char* name_format_string = NULL, | |
| 438 int field_offset = -1); | |
| 439 void SetDataOrAccessorPropertyReference(PropertyKind kind, | |
| 440 JSObject* parent_obj, int parent, | |
| 441 Name* reference_name, Object* child, | |
| 442 const char* name_format_string = NULL, | |
| 443 int field_offset = -1); | |
| 444 | |
| 445 void SetUserGlobalReference(Object* user_global); | |
| 446 void SetRootGcRootsReference(); | |
| 447 void SetGcRootsReference(VisitorSynchronization::SyncTag tag); | |
| 448 void SetGcSubrootReference( | |
| 449 VisitorSynchronization::SyncTag tag, bool is_weak, Object* child); | |
| 450 const char* GetStrongGcSubrootName(Object* object); | |
| 451 void TagObject(Object* obj, const char* tag); | |
| 452 void MarkAsWeakContainer(Object* object); | |
| 453 | |
| 454 HeapEntry* GetEntry(Object* obj); | |
| 455 | |
| 456 Heap* heap_; | |
| 457 HeapSnapshot* snapshot_; | |
| 458 StringsStorage* names_; | |
| 459 HeapObjectsMap* heap_object_map_; | |
| 460 SnapshottingProgressReportingInterface* progress_; | |
| 461 SnapshotFiller* filler_; | |
| 462 HeapObjectsSet objects_tags_; | |
| 463 HeapObjectsSet strong_gc_subroot_names_; | |
| 464 HeapObjectsSet user_roots_; | |
| 465 HeapObjectsSet weak_containers_; | |
| 466 v8::HeapProfiler::ObjectNameResolver* global_object_name_resolver_; | |
| 467 | |
| 468 friend class IndexedReferencesExtractor; | |
| 469 friend class RootsReferencesExtractor; | |
| 470 | |
| 471 DISALLOW_COPY_AND_ASSIGN(V8HeapExplorer); | |
| 472 }; | |
| 473 | |
| 474 | |
| 475 class NativeGroupRetainedObjectInfo; | |
| 476 | |
| 477 | |
| 478 // An implementation of retained native objects extractor. | |
| 479 class NativeObjectsExplorer { | |
| 480 public: | |
| 481 NativeObjectsExplorer(HeapSnapshot* snapshot, | |
| 482 SnapshottingProgressReportingInterface* progress); | |
| 483 virtual ~NativeObjectsExplorer(); | |
| 484 int EstimateObjectsCount(); | |
| 485 bool IterateAndExtractReferences(SnapshotFiller* filler); | |
| 486 | |
| 487 private: | |
| 488 void FillRetainedObjects(); | |
| 489 void FillImplicitReferences(); | |
| 490 List<HeapObject*>* GetListMaybeDisposeInfo(v8::RetainedObjectInfo* info); | |
| 491 void SetNativeRootReference(v8::RetainedObjectInfo* info); | |
| 492 void SetRootNativeRootsReference(); | |
| 493 void SetWrapperNativeReferences(HeapObject* wrapper, | |
| 494 v8::RetainedObjectInfo* info); | |
| 495 void VisitSubtreeWrapper(Object** p, uint16_t class_id); | |
| 496 | |
| 497 static uint32_t InfoHash(v8::RetainedObjectInfo* info) { | |
| 498 return ComputeIntegerHash(static_cast<uint32_t>(info->GetHash()), | |
| 499 v8::internal::kZeroHashSeed); | |
| 500 } | |
| 501 static bool RetainedInfosMatch(void* key1, void* key2) { | |
| 502 return key1 == key2 || | |
| 503 (reinterpret_cast<v8::RetainedObjectInfo*>(key1))->IsEquivalent( | |
| 504 reinterpret_cast<v8::RetainedObjectInfo*>(key2)); | |
| 505 } | |
| 506 INLINE(static bool StringsMatch(void* key1, void* key2)) { | |
| 507 return strcmp(reinterpret_cast<char*>(key1), | |
| 508 reinterpret_cast<char*>(key2)) == 0; | |
| 509 } | |
| 510 | |
| 511 NativeGroupRetainedObjectInfo* FindOrAddGroupInfo(const char* label); | |
| 512 | |
| 513 Isolate* isolate_; | |
| 514 HeapSnapshot* snapshot_; | |
| 515 StringsStorage* names_; | |
| 516 bool embedder_queried_; | |
| 517 HeapObjectsSet in_groups_; | |
| 518 // RetainedObjectInfo* -> List<HeapObject*>* | |
| 519 HashMap objects_by_info_; | |
| 520 HashMap native_groups_; | |
| 521 HeapEntriesAllocator* synthetic_entries_allocator_; | |
| 522 HeapEntriesAllocator* native_entries_allocator_; | |
| 523 // Used during references extraction. | |
| 524 SnapshotFiller* filler_; | |
| 525 | |
| 526 static HeapThing const kNativesRootObject; | |
| 527 | |
| 528 friend class GlobalHandlesExtractor; | |
| 529 | |
| 530 DISALLOW_COPY_AND_ASSIGN(NativeObjectsExplorer); | |
| 531 }; | |
| 532 | |
| 533 | |
| 534 class HeapSnapshotGenerator : public SnapshottingProgressReportingInterface { | |
| 535 public: | |
| 536 HeapSnapshotGenerator(HeapSnapshot* snapshot, | |
| 537 v8::ActivityControl* control, | |
| 538 v8::HeapProfiler::ObjectNameResolver* resolver, | |
| 539 Heap* heap); | |
| 540 bool GenerateSnapshot(); | |
| 541 | |
| 542 private: | |
| 543 bool FillReferences(); | |
| 544 void ProgressStep(); | |
| 545 bool ProgressReport(bool force = false); | |
| 546 void SetProgressTotal(int iterations_count); | |
| 547 | |
| 548 HeapSnapshot* snapshot_; | |
| 549 v8::ActivityControl* control_; | |
| 550 V8HeapExplorer v8_heap_explorer_; | |
| 551 NativeObjectsExplorer dom_explorer_; | |
| 552 // Mapping from HeapThing pointers to HeapEntry* pointers. | |
| 553 HeapEntriesMap entries_; | |
| 554 // Used during snapshot generation. | |
| 555 int progress_counter_; | |
| 556 int progress_total_; | |
| 557 Heap* heap_; | |
| 558 | |
| 559 DISALLOW_COPY_AND_ASSIGN(HeapSnapshotGenerator); | |
| 560 }; | |
| 561 | |
| 562 class OutputStreamWriter; | |
| 563 | |
| 564 class HeapSnapshotJSONSerializer { | |
| 565 public: | |
| 566 explicit HeapSnapshotJSONSerializer(HeapSnapshot* snapshot) | |
| 567 : snapshot_(snapshot), | |
| 568 strings_(StringsMatch), | |
| 569 next_node_id_(1), | |
| 570 next_string_id_(1), | |
| 571 writer_(NULL) { | |
| 572 } | |
| 573 void Serialize(v8::OutputStream* stream); | |
| 574 | |
| 575 private: | |
| 576 INLINE(static bool StringsMatch(void* key1, void* key2)) { | |
| 577 return strcmp(reinterpret_cast<char*>(key1), | |
| 578 reinterpret_cast<char*>(key2)) == 0; | |
| 579 } | |
| 580 | |
| 581 INLINE(static uint32_t StringHash(const void* string)) { | |
| 582 const char* s = reinterpret_cast<const char*>(string); | |
| 583 int len = static_cast<int>(strlen(s)); | |
| 584 return StringHasher::HashSequentialString( | |
| 585 s, len, v8::internal::kZeroHashSeed); | |
| 586 } | |
| 587 | |
| 588 int GetStringId(const char* s); | |
| 589 int entry_index(HeapEntry* e) { return e->index() * kNodeFieldsCount; } | |
| 590 void SerializeEdge(HeapGraphEdge* edge, bool first_edge); | |
| 591 void SerializeEdges(); | |
| 592 void SerializeImpl(); | |
| 593 void SerializeNode(HeapEntry* entry); | |
| 594 void SerializeNodes(); | |
| 595 void SerializeSnapshot(); | |
| 596 void SerializeTraceTree(); | |
| 597 void SerializeTraceNode(AllocationTraceNode* node); | |
| 598 void SerializeTraceNodeInfos(); | |
| 599 void SerializeSamples(); | |
| 600 void SerializeString(const unsigned char* s); | |
| 601 void SerializeStrings(); | |
| 602 | |
| 603 static const int kEdgeFieldsCount; | |
| 604 static const int kNodeFieldsCount; | |
| 605 | |
| 606 HeapSnapshot* snapshot_; | |
| 607 HashMap strings_; | |
| 608 int next_node_id_; | |
| 609 int next_string_id_; | |
| 610 OutputStreamWriter* writer_; | |
| 611 | |
| 612 friend class HeapSnapshotJSONSerializerEnumerator; | |
| 613 friend class HeapSnapshotJSONSerializerIterator; | |
| 614 | |
| 615 DISALLOW_COPY_AND_ASSIGN(HeapSnapshotJSONSerializer); | |
| 616 }; | |
| 617 | |
| 618 | |
| 619 } } // namespace v8::internal | |
| 620 | |
| 621 #endif // V8_HEAP_SNAPSHOT_GENERATOR_H_ | |
| OLD | NEW |