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