1 // Copyright 2013 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #ifndef V8_HEAP_SNAPSHOT_GENERATOR_H_ 29 #define V8_HEAP_SNAPSHOT_GENERATOR_H_ 30 31 #include "profile-generator-inl.h" 32 33 namespace v8 { 34 namespace internal { 35 36 class HeapEntry; 37 class HeapSnapshot; 38 39 class HeapGraphEdge BASE_EMBEDDED { 40 public: 41 enum Type { 42 kContextVariable = v8::HeapGraphEdge::kContextVariable, 43 kElement = v8::HeapGraphEdge::kElement, 44 kProperty = v8::HeapGraphEdge::kProperty, 45 kInternal = v8::HeapGraphEdge::kInternal, 46 kHidden = v8::HeapGraphEdge::kHidden, 47 kShortcut = v8::HeapGraphEdge::kShortcut, 48 kWeak = v8::HeapGraphEdge::kWeak 49 }; 50 51 HeapGraphEdge() { } 52 HeapGraphEdge(Type type, const char* name, int from, int to); 53 HeapGraphEdge(Type type, int index, int from, int to); 54 void ReplaceToIndexWithEntry(HeapSnapshot* snapshot); 55 56 Type type() const { return static_cast<Type>(type_); } 57 int index() const { 58 ASSERT(type_ == kElement || type_ == kHidden || type_ == kWeak); 59 return index_; 60 } 61 const char* name() const { 62 ASSERT(type_ == kContextVariable 63 || type_ == kProperty 64 || type_ == kInternal 65 || type_ == kShortcut); 66 return name_; 67 } 68 INLINE(HeapEntry* from() const); 69 HeapEntry* to() const { return to_entry_; } 70 71 private: 72 INLINE(HeapSnapshot* snapshot() const); 73 74 unsigned type_ : 3; 75 int from_index_ : 29; 76 union { 77 // During entries population |to_index_| is used for storing the index, 78 // afterwards it is replaced with a pointer to the entry. 79 int to_index_; 80 HeapEntry* to_entry_; 81 }; 82 union { 83 int index_; 84 const char* name_; 85 }; 86 }; 87 88 89 // HeapEntry instances represent an entity from the heap (or a special 90 // virtual node, e.g. root). 91 class HeapEntry BASE_EMBEDDED { 92 public: 93 enum Type { 94 kHidden = v8::HeapGraphNode::kHidden, 95 kArray = v8::HeapGraphNode::kArray, 96 kString = v8::HeapGraphNode::kString, 97 kObject = v8::HeapGraphNode::kObject, 98 kCode = v8::HeapGraphNode::kCode, 99 kClosure = v8::HeapGraphNode::kClosure, 100 kRegExp = v8::HeapGraphNode::kRegExp, 101 kHeapNumber = v8::HeapGraphNode::kHeapNumber, 102 kNative = v8::HeapGraphNode::kNative, 103 kSynthetic = v8::HeapGraphNode::kSynthetic 104 }; 105 static const int kNoEntry; 106 107 HeapEntry() { } 108 HeapEntry(HeapSnapshot* snapshot, 109 Type type, 110 const char* name, 111 SnapshotObjectId id, 112 int self_size); 113 114 HeapSnapshot* snapshot() { return snapshot_; } 115 Type type() { return static_cast<Type>(type_); } 116 const char* name() { return name_; } 117 void set_name(const char* name) { name_ = name; } 118 inline SnapshotObjectId id() { return id_; } 119 int self_size() { return self_size_; } 120 INLINE(int index() const); 121 int children_count() const { return children_count_; } 122 INLINE(int set_children_index(int index)); 123 void add_child(HeapGraphEdge* edge) { 124 children_arr()[children_count_++] = edge; 125 } 126 Vector<HeapGraphEdge*> children() { 127 return Vector<HeapGraphEdge*>(children_arr(), children_count_); } 128 129 void SetIndexedReference( 130 HeapGraphEdge::Type type, int index, HeapEntry* entry); 131 void SetNamedReference( 132 HeapGraphEdge::Type type, const char* name, HeapEntry* entry); 133 134 void Print( 135 const char* prefix, const char* edge_name, int max_depth, int indent); 136 137 Handle<HeapObject> GetHeapObject(); 138 139 private: 140 INLINE(HeapGraphEdge** children_arr()); 141 const char* TypeAsString(); 142 143 unsigned type_: 4; 144 int children_count_: 28; 145 int children_index_; 146 int self_size_; 147 SnapshotObjectId id_; 148 HeapSnapshot* snapshot_; 149 const char* name_; 150 }; 151 152 153 class HeapSnapshotsCollection; 154 155 // HeapSnapshot represents a single heap snapshot. It is stored in 156 // HeapSnapshotsCollection, which is also a factory for 157 // HeapSnapshots. All HeapSnapshots share strings copied from JS heap 158 // to be able to return them even if they were collected. 159 // HeapSnapshotGenerator fills in a HeapSnapshot. 160 class HeapSnapshot { 161 public: 162 HeapSnapshot(HeapSnapshotsCollection* collection, 163 const char* title, 164 unsigned uid); 165 void Delete(); 166 167 HeapSnapshotsCollection* collection() { return collection_; } 168 const char* title() { return title_; } 169 unsigned uid() { return uid_; } 170 size_t RawSnapshotSize() const; 171 HeapEntry* root() { return &entries_[root_index_]; } 172 HeapEntry* gc_roots() { return &entries_[gc_roots_index_]; } 173 HeapEntry* natives_root() { return &entries_[natives_root_index_]; } 174 HeapEntry* gc_subroot(int index) { 175 return &entries_[gc_subroot_indexes_[index]]; 176 } 177 List<HeapEntry>& entries() { return entries_; } 178 List<HeapGraphEdge>& edges() { return edges_; } 179 List<HeapGraphEdge*>& children() { return children_; } 180 void RememberLastJSObjectId(); 181 SnapshotObjectId max_snapshot_js_object_id() const { 182 return max_snapshot_js_object_id_; 183 } 184 185 HeapEntry* AddEntry(HeapEntry::Type type, 186 const char* name, 187 SnapshotObjectId id, 188 int size); 189 HeapEntry* AddRootEntry(); 190 HeapEntry* AddGcRootsEntry(); 191 HeapEntry* AddGcSubrootEntry(int tag); 192 HeapEntry* AddNativesRootEntry(); 193 HeapEntry* GetEntryById(SnapshotObjectId id); 194 List<HeapEntry*>* GetSortedEntriesList(); 195 void FillChildren(); 196 197 void Print(int max_depth); 198 void PrintEntriesSize(); 199 200 private: 201 HeapSnapshotsCollection* collection_; 202 const char* title_; 203 unsigned uid_; 204 int root_index_; 205 int gc_roots_index_; 206 int natives_root_index_; 207 int gc_subroot_indexes_[VisitorSynchronization::kNumberOfSyncTags]; 208 List<HeapEntry> entries_; 209 List<HeapGraphEdge> edges_; 210 List<HeapGraphEdge*> children_; 211 List<HeapEntry*> sorted_entries_; 212 SnapshotObjectId max_snapshot_js_object_id_; 213 214 friend class HeapSnapshotTester; 215 216 DISALLOW_COPY_AND_ASSIGN(HeapSnapshot); 217 }; 218 219 220 class HeapObjectsMap { 221 public: 222 explicit HeapObjectsMap(Heap* heap); 223 224 Heap* heap() const { return heap_; } 225 226 void SnapshotGenerationFinished(); 227 SnapshotObjectId FindEntry(Address addr); 228 SnapshotObjectId FindOrAddEntry(Address addr, unsigned int size); 229 void MoveObject(Address from, Address to); 230 SnapshotObjectId last_assigned_id() const { 231 return next_id_ - kObjectIdStep; 232 } 233 234 void StopHeapObjectsTracking(); 235 SnapshotObjectId PushHeapObjectsStats(OutputStream* stream); 236 size_t GetUsedMemorySize() const; 237 238 static SnapshotObjectId GenerateId(v8::RetainedObjectInfo* info); 239 static inline SnapshotObjectId GetNthGcSubrootId(int delta); 240 241 static const int kObjectIdStep = 2; 242 static const SnapshotObjectId kInternalRootObjectId; 243 static const SnapshotObjectId kGcRootsObjectId; 244 static const SnapshotObjectId kNativesRootObjectId; 245 static const SnapshotObjectId kGcRootsFirstSubrootId; 246 static const SnapshotObjectId kFirstAvailableObjectId; 247 248 private: 249 struct EntryInfo { 250 EntryInfo(SnapshotObjectId id, Address addr, unsigned int size) 251 : id(id), addr(addr), size(size), accessed(true) { } 252 EntryInfo(SnapshotObjectId id, Address addr, unsigned int size, bool accessed) 253 : id(id), addr(addr), size(size), accessed(accessed) { } 254 SnapshotObjectId id; 255 Address addr; 256 unsigned int size; 257 bool accessed; 258 }; 259 struct TimeInterval { 260 explicit TimeInterval(SnapshotObjectId id) : id(id), size(0), count(0) { } 261 SnapshotObjectId id; 262 uint32_t size; 263 uint32_t count; 264 }; 265 266 void UpdateHeapObjectsMap(); 267 void RemoveDeadEntries(); 268 269 SnapshotObjectId next_id_; 270 HashMap entries_map_; 271 List<EntryInfo> entries_; 272 List<TimeInterval> time_intervals_; 273 Heap* heap_; 274 275 DISALLOW_COPY_AND_ASSIGN(HeapObjectsMap); 276 }; 277 278 279 class HeapSnapshotsCollection { 280 public: 281 explicit HeapSnapshotsCollection(Heap* heap); 282 ~HeapSnapshotsCollection(); 283 284 Heap* heap() const { return ids_.heap(); } 285 286 bool is_tracking_objects() { return is_tracking_objects_; } 287 SnapshotObjectId PushHeapObjectsStats(OutputStream* stream) { 288 return ids_.PushHeapObjectsStats(stream); 289 } 290 void StartHeapObjectsTracking() { is_tracking_objects_ = true; } 291 void StopHeapObjectsTracking() { ids_.StopHeapObjectsTracking(); } 292 293 HeapSnapshot* NewSnapshot(const char* name, unsigned uid); 294 void SnapshotGenerationFinished(HeapSnapshot* snapshot); 295 List<HeapSnapshot*>* snapshots() { return &snapshots_; } 296 void RemoveSnapshot(HeapSnapshot* snapshot); 297 298 StringsStorage* names() { return &names_; } 299 300 SnapshotObjectId FindObjectId(Address object_addr) { 301 return ids_.FindEntry(object_addr); 302 } 303 SnapshotObjectId GetObjectId(Address object_addr, int object_size) { 304 return ids_.FindOrAddEntry(object_addr, object_size); 305 } 306 Handle<HeapObject> FindHeapObjectById(SnapshotObjectId id); 307 void ObjectMoveEvent(Address from, Address to) { ids_.MoveObject(from, to); } 308 SnapshotObjectId last_assigned_id() const { 309 return ids_.last_assigned_id(); 310 } 311 size_t GetUsedMemorySize() const; 312 313 private: 314 bool is_tracking_objects_; // Whether tracking object moves is needed. 315 List<HeapSnapshot*> snapshots_; 316 StringsStorage names_; 317 // Mapping from HeapObject addresses to objects' uids. 318 HeapObjectsMap ids_; 319 320 DISALLOW_COPY_AND_ASSIGN(HeapSnapshotsCollection); 321 }; 322 323 324 // A typedef for referencing anything that can be snapshotted living 325 // in any kind of heap memory. 326 typedef void* HeapThing; 327 328 329 // An interface that creates HeapEntries by HeapThings. 330 class HeapEntriesAllocator { 331 public: 332 virtual ~HeapEntriesAllocator() { } 333 virtual HeapEntry* AllocateEntry(HeapThing ptr) = 0; 334 }; 335 336 337 // The HeapEntriesMap instance is used to track a mapping between 338 // real heap objects and their representations in heap snapshots. 339 class HeapEntriesMap { 340 public: 341 HeapEntriesMap(); 342 343 int Map(HeapThing thing); 344 void Pair(HeapThing thing, int entry); 345 346 private: 347 static uint32_t Hash(HeapThing thing) { 348 return ComputeIntegerHash( 349 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(thing)), 350 v8::internal::kZeroHashSeed); 351 } 352 static bool HeapThingsMatch(HeapThing key1, HeapThing key2) { 353 return key1 == key2; 354 } 355 356 HashMap entries_; 357 358 friend class HeapObjectsSet; 359 360 DISALLOW_COPY_AND_ASSIGN(HeapEntriesMap); 361 }; 362 363 364 class HeapObjectsSet { 365 public: 366 HeapObjectsSet(); 367 void Clear(); 368 bool Contains(Object* object); 369 void Insert(Object* obj); 370 const char* GetTag(Object* obj); 371 void SetTag(Object* obj, const char* tag); 372 bool is_empty() const { return entries_.occupancy() == 0; } 373 374 private: 375 HashMap entries_; 376 377 DISALLOW_COPY_AND_ASSIGN(HeapObjectsSet); 378 }; 379 380 381 // An interface used to populate a snapshot with nodes and edges. 382 class SnapshotFillerInterface { 383 public: 384 virtual ~SnapshotFillerInterface() { } 385 virtual HeapEntry* AddEntry(HeapThing ptr, 386 HeapEntriesAllocator* allocator) = 0; 387 virtual HeapEntry* FindEntry(HeapThing ptr) = 0; 388 virtual HeapEntry* FindOrAddEntry(HeapThing ptr, 389 HeapEntriesAllocator* allocator) = 0; 390 virtual void SetIndexedReference(HeapGraphEdge::Type type, 391 int parent_entry, 392 int index, 393 HeapEntry* child_entry) = 0; 394 virtual void SetIndexedAutoIndexReference(HeapGraphEdge::Type type, 395 int parent_entry, 396 HeapEntry* child_entry) = 0; 397 virtual void SetNamedReference(HeapGraphEdge::Type type, 398 int parent_entry, 399 const char* reference_name, 400 HeapEntry* child_entry) = 0; 401 virtual void SetNamedAutoIndexReference(HeapGraphEdge::Type type, 402 int parent_entry, 403 HeapEntry* child_entry) = 0; 404 }; 405 406 407 class SnapshottingProgressReportingInterface { 408 public: 409 virtual ~SnapshottingProgressReportingInterface() { } 410 virtual void ProgressStep() = 0; 411 virtual bool ProgressReport(bool force) = 0; 412 }; 413 414 415 // An implementation of V8 heap graph extractor. 416 class V8HeapExplorer : public HeapEntriesAllocator { 417 public: 418 V8HeapExplorer(HeapSnapshot* snapshot, 419 SnapshottingProgressReportingInterface* progress, 420 v8::HeapProfiler::ObjectNameResolver* resolver); 421 virtual ~V8HeapExplorer(); 422 virtual HeapEntry* AllocateEntry(HeapThing ptr); 423 void AddRootEntries(SnapshotFillerInterface* filler); 424 int EstimateObjectsCount(HeapIterator* iterator); 425 bool IterateAndExtractReferences(SnapshotFillerInterface* filler); 426 void TagGlobalObjects(); 427 428 static String* GetConstructorName(JSObject* object); 429 430 static HeapObject* const kInternalRootObject; 431 432 private: 433 HeapEntry* AddEntry(HeapObject* object); 434 HeapEntry* AddEntry(HeapObject* object, 435 HeapEntry::Type type, 436 const char* name); 437 const char* GetSystemEntryName(HeapObject* object); 438 439 void ExtractReferences(HeapObject* obj); 440 void ExtractJSGlobalProxyReferences(int entry, JSGlobalProxy* proxy); 441 void ExtractJSObjectReferences(int entry, JSObject* js_obj); 442 void ExtractStringReferences(int entry, String* obj); 443 void ExtractContextReferences(int entry, Context* context); 444 void ExtractMapReferences(int entry, Map* map); 445 void ExtractSharedFunctionInfoReferences(int entry, 446 SharedFunctionInfo* shared); 447 void ExtractScriptReferences(int entry, Script* script); 448 void ExtractAccessorPairReferences(int entry, AccessorPair* accessors); 449 void ExtractCodeCacheReferences(int entry, CodeCache* code_cache); 450 void ExtractCodeReferences(int entry, Code* code); 451 void ExtractCellReferences(int entry, Cell* cell); 452 void ExtractPropertyCellReferences(int entry, PropertyCell* cell); 453 void ExtractAllocationSiteReferences(int entry, AllocationSite* site); 454 void ExtractClosureReferences(JSObject* js_obj, int entry); 455 void ExtractPropertyReferences(JSObject* js_obj, int entry); 456 bool ExtractAccessorPairProperty(JSObject* js_obj, int entry, 457 Object* key, Object* callback_obj); 458 void ExtractElementReferences(JSObject* js_obj, int entry); 459 void ExtractInternalReferences(JSObject* js_obj, int entry); 460 bool IsEssentialObject(Object* object); 461 void SetContextReference(HeapObject* parent_obj, 462 int parent, 463 String* reference_name, 464 Object* child, 465 int field_offset); 466 void SetNativeBindReference(HeapObject* parent_obj, 467 int parent, 468 const char* reference_name, 469 Object* child); 470 void SetElementReference(HeapObject* parent_obj, 471 int parent, 472 int index, 473 Object* child); 474 void SetInternalReference(HeapObject* parent_obj, 475 int parent, 476 const char* reference_name, 477 Object* child, 478 int field_offset = -1); 479 void SetInternalReference(HeapObject* parent_obj, 480 int parent, 481 int index, 482 Object* child, 483 int field_offset = -1); 484 void SetHiddenReference(HeapObject* parent_obj, 485 int parent, 486 int index, 487 Object* child); 488 void SetWeakReference(HeapObject* parent_obj, 489 int parent, 490 int index, 491 Object* child_obj, 492 int field_offset); 493 void SetPropertyReference(HeapObject* parent_obj, 494 int parent, 495 Name* reference_name, 496 Object* child, 497 const char* name_format_string = NULL, 498 int field_offset = -1); 499 void SetUserGlobalReference(Object* user_global); 500 void SetRootGcRootsReference(); 501 void SetGcRootsReference(VisitorSynchronization::SyncTag tag); 502 void SetGcSubrootReference( 503 VisitorSynchronization::SyncTag tag, bool is_weak, Object* child); 504 const char* GetStrongGcSubrootName(Object* object); 505 void TagObject(Object* obj, const char* tag); 506 507 HeapEntry* GetEntry(Object* obj); 508 509 static inline HeapObject* GetNthGcSubrootObject(int delta); 510 static inline int GetGcSubrootOrder(HeapObject* subroot); 511 512 Heap* heap_; 513 HeapSnapshot* snapshot_; 514 HeapSnapshotsCollection* collection_; 515 SnapshottingProgressReportingInterface* progress_; 516 SnapshotFillerInterface* filler_; 517 HeapObjectsSet objects_tags_; 518 HeapObjectsSet strong_gc_subroot_names_; 519 HeapObjectsSet user_roots_; 520 v8::HeapProfiler::ObjectNameResolver* global_object_name_resolver_; 521 522 static HeapObject* const kGcRootsObject; 523 static HeapObject* const kFirstGcSubrootObject; 524 static HeapObject* const kLastGcSubrootObject; 525 526 friend class IndexedReferencesExtractor; 527 friend class GcSubrootsEnumerator; 528 friend class RootsReferencesExtractor; 529 530 DISALLOW_COPY_AND_ASSIGN(V8HeapExplorer); 531 }; 532 533 534 class NativeGroupRetainedObjectInfo; 535 536 537 // An implementation of retained native objects extractor. 538 class NativeObjectsExplorer { 539 public: 540 NativeObjectsExplorer(HeapSnapshot* snapshot, 541 SnapshottingProgressReportingInterface* progress); 542 virtual ~NativeObjectsExplorer(); 543 void AddRootEntries(SnapshotFillerInterface* filler); 544 int EstimateObjectsCount(); 545 bool IterateAndExtractReferences(SnapshotFillerInterface* filler); 546 547 private: 548 void FillRetainedObjects(); 549 void FillImplicitReferences(); 550 List<HeapObject*>* GetListMaybeDisposeInfo(v8::RetainedObjectInfo* info); 551 void SetNativeRootReference(v8::RetainedObjectInfo* info); 552 void SetRootNativeRootsReference(); 553 void SetWrapperNativeReferences(HeapObject* wrapper, 554 v8::RetainedObjectInfo* info); 555 void VisitSubtreeWrapper(Object** p, uint16_t class_id); 556 557 static uint32_t InfoHash(v8::RetainedObjectInfo* info) { 558 return ComputeIntegerHash(static_cast<uint32_t>(info->GetHash()), 559 v8::internal::kZeroHashSeed); 560 } 561 static bool RetainedInfosMatch(void* key1, void* key2) { 562 return key1 == key2 || 563 (reinterpret_cast<v8::RetainedObjectInfo*>(key1))->IsEquivalent( 564 reinterpret_cast<v8::RetainedObjectInfo*>(key2)); 565 } 566 INLINE(static bool StringsMatch(void* key1, void* key2)) { 567 return strcmp(reinterpret_cast<char*>(key1), 568 reinterpret_cast<char*>(key2)) == 0; 569 } 570 571 NativeGroupRetainedObjectInfo* FindOrAddGroupInfo(const char* label); 572 573 HeapSnapshot* snapshot_; 574 HeapSnapshotsCollection* collection_; 575 SnapshottingProgressReportingInterface* progress_; 576 bool embedder_queried_; 577 HeapObjectsSet in_groups_; 578 // RetainedObjectInfo* -> List<HeapObject*>* 579 HashMap objects_by_info_; 580 HashMap native_groups_; 581 HeapEntriesAllocator* synthetic_entries_allocator_; 582 HeapEntriesAllocator* native_entries_allocator_; 583 // Used during references extraction. 584 SnapshotFillerInterface* filler_; 585 586 static HeapThing const kNativesRootObject; 587 588 friend class GlobalHandlesExtractor; 589 590 DISALLOW_COPY_AND_ASSIGN(NativeObjectsExplorer); 591 }; 592 593 594 class HeapSnapshotGenerator : public SnapshottingProgressReportingInterface { 595 public: 596 HeapSnapshotGenerator(HeapSnapshot* snapshot, 597 v8::ActivityControl* control, 598 v8::HeapProfiler::ObjectNameResolver* resolver, 599 Heap* heap); 600 bool GenerateSnapshot(); 601 602 private: 603 bool FillReferences(); 604 void ProgressStep(); 605 bool ProgressReport(bool force = false); 606 void SetProgressTotal(int iterations_count); 607 608 HeapSnapshot* snapshot_; 609 v8::ActivityControl* control_; 610 V8HeapExplorer v8_heap_explorer_; 611 NativeObjectsExplorer dom_explorer_; 612 // Mapping from HeapThing pointers to HeapEntry* pointers. 613 HeapEntriesMap entries_; 614 // Used during snapshot generation. 615 int progress_counter_; 616 int progress_total_; 617 Heap* heap_; 618 619 DISALLOW_COPY_AND_ASSIGN(HeapSnapshotGenerator); 620 }; 621 622 class OutputStreamWriter; 623 624 class HeapSnapshotJSONSerializer { 625 public: 626 explicit HeapSnapshotJSONSerializer(HeapSnapshot* snapshot) 627 : snapshot_(snapshot), 628 strings_(ObjectsMatch), 629 next_node_id_(1), 630 next_string_id_(1), 631 writer_(NULL) { 632 } 633 void Serialize(v8::OutputStream* stream); 634 635 private: 636 INLINE(static bool ObjectsMatch(void* key1, void* key2)) { 637 return key1 == key2; 638 } 639 640 INLINE(static uint32_t ObjectHash(const void* key)) { 641 return ComputeIntegerHash( 642 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)), 643 v8::internal::kZeroHashSeed); 644 } 645 646 int GetStringId(const char* s); 647 int entry_index(HeapEntry* e) { return e->index() * kNodeFieldsCount; } 648 void SerializeEdge(HeapGraphEdge* edge, bool first_edge); 649 void SerializeEdges(); 650 void SerializeImpl(); 651 void SerializeNode(HeapEntry* entry); 652 void SerializeNodes(); 653 void SerializeSnapshot(); 654 void SerializeString(const unsigned char* s); 655 void SerializeStrings(); 656 void SortHashMap(HashMap* map, List<HashMap::Entry*>* sorted_entries); 657 658 static const int kEdgeFieldsCount; 659 static const int kNodeFieldsCount; 660 661 HeapSnapshot* snapshot_; 662 HashMap strings_; 663 int next_node_id_; 664 int next_string_id_; 665 OutputStreamWriter* writer_; 666 667 friend class HeapSnapshotJSONSerializerEnumerator; 668 friend class HeapSnapshotJSONSerializerIterator; 669 670 DISALLOW_COPY_AND_ASSIGN(HeapSnapshotJSONSerializer); 671 }; 672 673 674 } } // namespace v8::internal 675 676 #endif // V8_HEAP_SNAPSHOT_GENERATOR_H_ 677 678