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