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