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 <memory> 10 #include <unordered_map> 11 #include <unordered_set> 12 #include <vector> 13 14 #include "include/v8-profiler.h" 15 #include "src/base/platform/time.h" 16 #include "src/objects/fixed-array.h" 17 #include "src/objects/hash-table.h" 18 #include "src/objects/heap-object.h" 19 #include "src/objects/js-objects.h" 20 #include "src/objects/literal-objects.h" 21 #include "src/objects/objects.h" 22 #include "src/objects/visitors.h" 23 #include "src/profiler/strings-storage.h" 24 #include "src/strings/string-hasher.h" 25 26 namespace v8 { 27 namespace internal { 28 29 class AllocationTraceNode; 30 class HeapEntry; 31 class HeapProfiler; 32 class HeapSnapshot; 33 class HeapSnapshotGenerator; 34 class JSArrayBuffer; 35 class JSCollection; 36 class JSGeneratorObject; 37 class JSGlobalObject; 38 class JSGlobalProxy; 39 class JSPromise; 40 class JSWeakCollection; 41 class SafepointScope; 42 43 struct SourceLocation { SourceLocationSourceLocation44 SourceLocation(int entry_index, int scriptId, int line, int col) 45 : entry_index(entry_index), scriptId(scriptId), line(line), col(col) {} 46 47 const int entry_index; 48 const int scriptId; 49 const int line; 50 const int col; 51 }; 52 53 class HeapGraphEdge { 54 public: 55 enum Type { 56 kContextVariable = v8::HeapGraphEdge::kContextVariable, 57 kElement = v8::HeapGraphEdge::kElement, 58 kProperty = v8::HeapGraphEdge::kProperty, 59 kInternal = v8::HeapGraphEdge::kInternal, 60 kHidden = v8::HeapGraphEdge::kHidden, 61 kShortcut = v8::HeapGraphEdge::kShortcut, 62 kWeak = v8::HeapGraphEdge::kWeak 63 }; 64 65 HeapGraphEdge(Type type, const char* name, HeapEntry* from, HeapEntry* to); 66 HeapGraphEdge(Type type, int index, HeapEntry* from, HeapEntry* to); 67 type()68 Type type() const { return TypeField::decode(bit_field_); } index()69 int index() const { 70 DCHECK(type() == kElement || type() == kHidden); 71 return index_; 72 } name()73 const char* name() const { 74 DCHECK(type() == kContextVariable || type() == kProperty || 75 type() == kInternal || type() == kShortcut || type() == kWeak); 76 return name_; 77 } 78 V8_INLINE HeapEntry* from() const; to()79 HeapEntry* to() const { return to_entry_; } 80 81 V8_INLINE Isolate* isolate() const; 82 83 private: 84 V8_INLINE HeapSnapshot* snapshot() const; from_index()85 int from_index() const { return FromIndexField::decode(bit_field_); } 86 87 using TypeField = base::BitField<Type, 0, 3>; 88 using FromIndexField = base::BitField<int, 3, 29>; 89 uint32_t bit_field_; 90 HeapEntry* to_entry_; 91 union { 92 int index_; 93 const char* name_; 94 }; 95 }; 96 97 98 // HeapEntry instances represent an entity from the heap (or a special 99 // virtual node, e.g. root). 100 class HeapEntry { 101 public: 102 enum Type { 103 kHidden = v8::HeapGraphNode::kHidden, 104 kArray = v8::HeapGraphNode::kArray, 105 kString = v8::HeapGraphNode::kString, 106 kObject = v8::HeapGraphNode::kObject, 107 kCode = v8::HeapGraphNode::kCode, 108 kClosure = v8::HeapGraphNode::kClosure, 109 kRegExp = v8::HeapGraphNode::kRegExp, 110 kHeapNumber = v8::HeapGraphNode::kHeapNumber, 111 kNative = v8::HeapGraphNode::kNative, 112 kSynthetic = v8::HeapGraphNode::kSynthetic, 113 kConsString = v8::HeapGraphNode::kConsString, 114 kSlicedString = v8::HeapGraphNode::kSlicedString, 115 kSymbol = v8::HeapGraphNode::kSymbol, 116 kBigInt = v8::HeapGraphNode::kBigInt 117 }; 118 119 HeapEntry(HeapSnapshot* snapshot, int index, Type type, const char* name, 120 SnapshotObjectId id, size_t self_size, unsigned trace_node_id); 121 snapshot()122 HeapSnapshot* snapshot() { return snapshot_; } type()123 Type type() const { return static_cast<Type>(type_); } set_type(Type type)124 void set_type(Type type) { type_ = type; } name()125 const char* name() const { return name_; } set_name(const char * name)126 void set_name(const char* name) { name_ = name; } id()127 SnapshotObjectId id() const { return id_; } self_size()128 size_t self_size() const { return self_size_; } trace_node_id()129 unsigned trace_node_id() const { return trace_node_id_; } index()130 int index() const { return index_; } 131 V8_INLINE int children_count() const; 132 V8_INLINE int set_children_index(int index); 133 V8_INLINE void add_child(HeapGraphEdge* edge); 134 V8_INLINE HeapGraphEdge* child(int i); 135 V8_INLINE Isolate* isolate() const; 136 set_detachedness(v8::EmbedderGraph::Node::Detachedness value)137 void set_detachedness(v8::EmbedderGraph::Node::Detachedness value) { 138 detachedness_ = static_cast<uint8_t>(value); 139 } detachedness()140 uint8_t detachedness() const { return detachedness_; } 141 142 void SetIndexedReference( 143 HeapGraphEdge::Type type, int index, HeapEntry* entry); 144 void SetNamedReference( 145 HeapGraphEdge::Type type, const char* name, HeapEntry* entry); SetIndexedAutoIndexReference(HeapGraphEdge::Type type,HeapEntry * child)146 void SetIndexedAutoIndexReference(HeapGraphEdge::Type type, 147 HeapEntry* child) { 148 SetIndexedReference(type, children_count_ + 1, child); 149 } 150 void SetNamedAutoIndexReference(HeapGraphEdge::Type type, 151 const char* description, HeapEntry* child, 152 StringsStorage* strings); 153 154 V8_EXPORT_PRIVATE void Print(const char* prefix, const char* edge_name, 155 int max_depth, int indent) const; 156 157 private: 158 V8_INLINE std::vector<HeapGraphEdge*>::iterator children_begin() const; 159 V8_INLINE std::vector<HeapGraphEdge*>::iterator children_end() const; 160 const char* TypeAsString() const; 161 162 unsigned type_: 4; 163 unsigned index_ : 28; // Supports up to ~250M objects. 164 union { 165 // The count is used during the snapshot build phase, 166 // then it gets converted into the index by the |FillChildren| function. 167 unsigned children_count_; 168 unsigned children_end_index_; 169 }; 170 #ifdef V8_TARGET_ARCH_64_BIT 171 size_t self_size_ : 48; 172 #else // !V8_TARGET_ARCH_64_BIT 173 size_t self_size_; 174 #endif // !V8_TARGET_ARCH_64_BIT 175 uint8_t detachedness_ = 0; 176 HeapSnapshot* snapshot_; 177 const char* name_; 178 SnapshotObjectId id_; 179 // id of allocation stack trace top node 180 unsigned trace_node_id_; 181 }; 182 183 // HeapSnapshot represents a single heap snapshot. It is stored in 184 // HeapProfiler, which is also a factory for 185 // HeapSnapshots. All HeapSnapshots share strings copied from JS heap 186 // to be able to return them even if they were collected. 187 // HeapSnapshotGenerator fills in a HeapSnapshot. 188 class HeapSnapshot { 189 public: 190 explicit HeapSnapshot(HeapProfiler* profiler, bool global_objects_as_roots); 191 void Delete(); 192 profiler()193 HeapProfiler* profiler() const { return profiler_; } root()194 HeapEntry* root() const { return root_entry_; } gc_roots()195 HeapEntry* gc_roots() const { return gc_roots_entry_; } gc_subroot(Root root)196 HeapEntry* gc_subroot(Root root) const { 197 return gc_subroot_entries_[static_cast<int>(root)]; 198 } entries()199 std::deque<HeapEntry>& entries() { return entries_; } entries()200 const std::deque<HeapEntry>& entries() const { return entries_; } edges()201 std::deque<HeapGraphEdge>& edges() { return edges_; } edges()202 const std::deque<HeapGraphEdge>& edges() const { return edges_; } children()203 std::vector<HeapGraphEdge*>& children() { return children_; } locations()204 const std::vector<SourceLocation>& locations() const { return locations_; } 205 void RememberLastJSObjectId(); max_snapshot_js_object_id()206 SnapshotObjectId max_snapshot_js_object_id() const { 207 return max_snapshot_js_object_id_; 208 } is_complete()209 bool is_complete() const { return !children_.empty(); } treat_global_objects_as_roots()210 bool treat_global_objects_as_roots() const { 211 return treat_global_objects_as_roots_; 212 } 213 214 void AddLocation(HeapEntry* entry, int scriptId, int line, int col); 215 HeapEntry* AddEntry(HeapEntry::Type type, 216 const char* name, 217 SnapshotObjectId id, 218 size_t size, 219 unsigned trace_node_id); 220 void AddSyntheticRootEntries(); 221 HeapEntry* GetEntryById(SnapshotObjectId id); 222 void FillChildren(); 223 224 void Print(int max_depth); 225 226 private: 227 void AddRootEntry(); 228 void AddGcRootsEntry(); 229 void AddGcSubrootEntry(Root root, SnapshotObjectId id); 230 231 HeapProfiler* profiler_; 232 HeapEntry* root_entry_ = nullptr; 233 HeapEntry* gc_roots_entry_ = nullptr; 234 HeapEntry* gc_subroot_entries_[static_cast<int>(Root::kNumberOfRoots)]; 235 // For |entries_| we rely on the deque property, that it never reallocates 236 // backing storage, thus all entry pointers remain valid for the duration 237 // of snapshotting. 238 std::deque<HeapEntry> entries_; 239 std::deque<HeapGraphEdge> edges_; 240 std::vector<HeapGraphEdge*> children_; 241 std::unordered_map<SnapshotObjectId, HeapEntry*> entries_by_id_cache_; 242 std::vector<SourceLocation> locations_; 243 SnapshotObjectId max_snapshot_js_object_id_ = -1; 244 bool treat_global_objects_as_roots_; 245 246 DISALLOW_COPY_AND_ASSIGN(HeapSnapshot); 247 }; 248 249 250 class HeapObjectsMap { 251 public: 252 struct TimeInterval { TimeIntervalTimeInterval253 explicit TimeInterval(SnapshotObjectId id) 254 : id(id), size(0), count(0), timestamp(base::TimeTicks::Now()) {} last_assigned_idTimeInterval255 SnapshotObjectId last_assigned_id() const { return id - kObjectIdStep; } 256 SnapshotObjectId id; 257 uint32_t size; 258 uint32_t count; 259 base::TimeTicks timestamp; 260 }; 261 262 explicit HeapObjectsMap(Heap* heap); 263 heap()264 Heap* heap() const { return heap_; } 265 266 SnapshotObjectId FindEntry(Address addr); 267 SnapshotObjectId FindOrAddEntry(Address addr, 268 unsigned int size, 269 bool accessed = true); 270 SnapshotObjectId FindMergedNativeEntry(NativeObject addr); 271 void AddMergedNativeEntry(NativeObject addr, Address canonical_addr); 272 bool MoveObject(Address from, Address to, int size); 273 void UpdateObjectSize(Address addr, int size); last_assigned_id()274 SnapshotObjectId last_assigned_id() const { 275 return next_id_ - kObjectIdStep; 276 } 277 278 void StopHeapObjectsTracking(); 279 SnapshotObjectId PushHeapObjectsStats(OutputStream* stream, 280 int64_t* timestamp_us); samples()281 const std::vector<TimeInterval>& samples() const { return time_intervals_; } 282 283 static const int kObjectIdStep = 2; 284 static const SnapshotObjectId kInternalRootObjectId; 285 static const SnapshotObjectId kGcRootsObjectId; 286 static const SnapshotObjectId kGcRootsFirstSubrootId; 287 static const SnapshotObjectId kFirstAvailableObjectId; 288 289 void UpdateHeapObjectsMap(); 290 void RemoveDeadEntries(); 291 292 private: 293 struct EntryInfo { EntryInfoEntryInfo294 EntryInfo(SnapshotObjectId id, Address addr, unsigned int size, 295 bool accessed) 296 : id(id), addr(addr), size(size), accessed(accessed) {} 297 SnapshotObjectId id; 298 Address addr; 299 unsigned int size; 300 bool accessed; 301 }; 302 303 SnapshotObjectId next_id_; 304 // TODO(jkummerow): Use a map that uses {Address} as the key type. 305 base::HashMap entries_map_; 306 std::vector<EntryInfo> entries_; 307 std::vector<TimeInterval> time_intervals_; 308 // Map from NativeObject to EntryInfo index in entries_. 309 std::unordered_map<NativeObject, size_t> merged_native_entries_map_; 310 Heap* heap_; 311 312 DISALLOW_COPY_AND_ASSIGN(HeapObjectsMap); 313 }; 314 315 // A typedef for referencing anything that can be snapshotted living 316 // in any kind of heap memory. 317 using HeapThing = void*; 318 319 // An interface that creates HeapEntries by HeapThings. 320 class HeapEntriesAllocator { 321 public: 322 virtual ~HeapEntriesAllocator() = default; 323 virtual HeapEntry* AllocateEntry(HeapThing ptr) = 0; 324 }; 325 326 class SnapshottingProgressReportingInterface { 327 public: 328 virtual ~SnapshottingProgressReportingInterface() = default; 329 virtual void ProgressStep() = 0; 330 virtual bool ProgressReport(bool force) = 0; 331 }; 332 333 // An implementation of V8 heap graph extractor. 334 class V8_EXPORT_PRIVATE V8HeapExplorer : public HeapEntriesAllocator { 335 public: 336 V8HeapExplorer(HeapSnapshot* snapshot, 337 SnapshottingProgressReportingInterface* progress, 338 v8::HeapProfiler::ObjectNameResolver* resolver); 339 ~V8HeapExplorer() override = default; 340 341 HeapEntry* AllocateEntry(HeapThing ptr) override; 342 int EstimateObjectsCount(); 343 bool IterateAndExtractReferences(HeapSnapshotGenerator* generator); 344 void CollectGlobalObjectsTags(); 345 void MakeGlobalObjectTagMap(const SafepointScope& safepoint_scope); 346 void TagBuiltinCodeObject(Code code, const char* name); 347 HeapEntry* AddEntry(Address address, 348 HeapEntry::Type type, 349 const char* name, 350 size_t size); 351 352 static JSFunction GetConstructor(JSReceiver receiver); 353 static String GetConstructorName(JSObject object); 354 355 private: 356 void MarkVisitedField(int offset); 357 358 HeapEntry* AddEntry(HeapObject object); 359 HeapEntry* AddEntry(HeapObject object, HeapEntry::Type type, 360 const char* name); 361 362 const char* GetSystemEntryName(HeapObject object); 363 364 void ExtractLocation(HeapEntry* entry, HeapObject object); 365 void ExtractLocationForJSFunction(HeapEntry* entry, JSFunction func); 366 void ExtractReferences(HeapEntry* entry, HeapObject obj); 367 void ExtractJSGlobalProxyReferences(HeapEntry* entry, JSGlobalProxy proxy); 368 void ExtractJSObjectReferences(HeapEntry* entry, JSObject js_obj); 369 void ExtractStringReferences(HeapEntry* entry, String obj); 370 void ExtractSymbolReferences(HeapEntry* entry, Symbol symbol); 371 void ExtractJSCollectionReferences(HeapEntry* entry, JSCollection collection); 372 void ExtractJSWeakCollectionReferences(HeapEntry* entry, 373 JSWeakCollection collection); 374 void ExtractEphemeronHashTableReferences(HeapEntry* entry, 375 EphemeronHashTable table); 376 void ExtractContextReferences(HeapEntry* entry, Context context); 377 void ExtractMapReferences(HeapEntry* entry, Map map); 378 void ExtractSharedFunctionInfoReferences(HeapEntry* entry, 379 SharedFunctionInfo shared); 380 void ExtractScriptReferences(HeapEntry* entry, Script script); 381 void ExtractAccessorInfoReferences(HeapEntry* entry, 382 AccessorInfo accessor_info); 383 void ExtractAccessorPairReferences(HeapEntry* entry, AccessorPair accessors); 384 void ExtractCodeReferences(HeapEntry* entry, Code code); 385 void ExtractCellReferences(HeapEntry* entry, Cell cell); 386 void ExtractFeedbackCellReferences(HeapEntry* entry, 387 FeedbackCell feedback_cell); 388 void ExtractPropertyCellReferences(HeapEntry* entry, PropertyCell cell); 389 void ExtractAllocationSiteReferences(HeapEntry* entry, AllocationSite site); 390 void ExtractArrayBoilerplateDescriptionReferences( 391 HeapEntry* entry, ArrayBoilerplateDescription value); 392 void ExtractJSArrayBufferReferences(HeapEntry* entry, JSArrayBuffer buffer); 393 void ExtractJSPromiseReferences(HeapEntry* entry, JSPromise promise); 394 void ExtractJSGeneratorObjectReferences(HeapEntry* entry, 395 JSGeneratorObject generator); 396 void ExtractFixedArrayReferences(HeapEntry* entry, FixedArray array); 397 void ExtractFeedbackVectorReferences(HeapEntry* entry, 398 FeedbackVector feedback_vector); 399 void ExtractDescriptorArrayReferences(HeapEntry* entry, 400 DescriptorArray array); 401 template <typename T> 402 void ExtractWeakArrayReferences(int header_size, HeapEntry* entry, T array); 403 void ExtractPropertyReferences(JSObject js_obj, HeapEntry* entry); 404 void ExtractAccessorPairProperty(HeapEntry* entry, Name key, 405 Object callback_obj, int field_offset = -1); 406 void ExtractElementReferences(JSObject js_obj, HeapEntry* entry); 407 void ExtractInternalReferences(JSObject js_obj, HeapEntry* entry); 408 409 bool IsEssentialObject(Object object); 410 bool IsEssentialHiddenReference(Object parent, int field_offset); 411 412 void SetContextReference(HeapEntry* parent_entry, String reference_name, 413 Object child, int field_offset); 414 void SetNativeBindReference(HeapEntry* parent_entry, 415 const char* reference_name, Object child); 416 void SetElementReference(HeapEntry* parent_entry, int index, Object child); 417 void SetInternalReference(HeapEntry* parent_entry, const char* reference_name, 418 Object child, int field_offset = -1); 419 void SetInternalReference(HeapEntry* parent_entry, int index, Object child, 420 int field_offset = -1); 421 void SetHiddenReference(HeapObject parent_obj, HeapEntry* parent_entry, 422 int index, Object child, int field_offset); 423 void SetWeakReference(HeapEntry* parent_entry, const char* reference_name, 424 Object child_obj, int field_offset); 425 void SetWeakReference(HeapEntry* parent_entry, int index, Object child_obj, 426 int field_offset); 427 void SetPropertyReference(HeapEntry* parent_entry, Name reference_name, 428 Object child, 429 const char* name_format_string = nullptr, 430 int field_offset = -1); 431 void SetDataOrAccessorPropertyReference( 432 PropertyKind kind, HeapEntry* parent_entry, Name reference_name, 433 Object child, const char* name_format_string = nullptr, 434 int field_offset = -1); 435 436 void SetUserGlobalReference(Object user_global); 437 void SetRootGcRootsReference(); 438 void SetGcRootsReference(Root root); 439 void SetGcSubrootReference(Root root, const char* description, bool is_weak, 440 Object child); 441 const char* GetStrongGcSubrootName(Object object); 442 void TagObject(Object obj, const char* tag); 443 444 HeapEntry* GetEntry(Object obj); 445 446 Heap* heap_; 447 HeapSnapshot* snapshot_; 448 StringsStorage* names_; 449 HeapObjectsMap* heap_object_map_; 450 SnapshottingProgressReportingInterface* progress_; 451 HeapSnapshotGenerator* generator_ = nullptr; 452 std::vector<std::pair<Handle<JSGlobalObject>, const char*>> 453 global_object_tag_pairs_; 454 std::unordered_map<JSGlobalObject, const char*, Object::Hasher> 455 global_object_tag_map_; 456 std::unordered_map<Object, const char*, Object::Hasher> 457 strong_gc_subroot_names_; 458 std::unordered_set<JSGlobalObject, Object::Hasher> user_roots_; 459 v8::HeapProfiler::ObjectNameResolver* global_object_name_resolver_; 460 461 std::vector<bool> visited_fields_; 462 463 friend class IndexedReferencesExtractor; 464 friend class RootsReferencesExtractor; 465 466 DISALLOW_COPY_AND_ASSIGN(V8HeapExplorer); 467 }; 468 469 // An implementation of retained native objects extractor. 470 class NativeObjectsExplorer { 471 public: 472 NativeObjectsExplorer(HeapSnapshot* snapshot, 473 SnapshottingProgressReportingInterface* progress); 474 bool IterateAndExtractReferences(HeapSnapshotGenerator* generator); 475 476 private: 477 // Returns an entry for a given node, where node may be a V8 node or an 478 // embedder node. Returns the coresponding wrapper node if present. 479 HeapEntry* EntryForEmbedderGraphNode(EmbedderGraph::Node* node); 480 void MergeNodeIntoEntry(HeapEntry* entry, EmbedderGraph::Node* original_node, 481 EmbedderGraph::Node* wrapper_node); 482 483 Isolate* isolate_; 484 HeapSnapshot* snapshot_; 485 StringsStorage* names_; 486 HeapObjectsMap* heap_object_map_; 487 std::unique_ptr<HeapEntriesAllocator> embedder_graph_entries_allocator_; 488 // Used during references extraction. 489 HeapSnapshotGenerator* generator_ = nullptr; 490 491 static HeapThing const kNativesRootObject; 492 493 friend class GlobalHandlesExtractor; 494 495 DISALLOW_COPY_AND_ASSIGN(NativeObjectsExplorer); 496 }; 497 498 class HeapSnapshotGenerator : public SnapshottingProgressReportingInterface { 499 public: 500 // The HeapEntriesMap instance is used to track a mapping between 501 // real heap objects and their representations in heap snapshots. 502 using HeapEntriesMap = std::unordered_map<HeapThing, HeapEntry*>; 503 504 HeapSnapshotGenerator(HeapSnapshot* snapshot, 505 v8::ActivityControl* control, 506 v8::HeapProfiler::ObjectNameResolver* resolver, 507 Heap* heap); 508 bool GenerateSnapshot(); 509 FindEntry(HeapThing ptr)510 HeapEntry* FindEntry(HeapThing ptr) { 511 auto it = entries_map_.find(ptr); 512 return it != entries_map_.end() ? it->second : nullptr; 513 } 514 AddEntry(HeapThing ptr,HeapEntriesAllocator * allocator)515 HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) { 516 return entries_map_.emplace(ptr, allocator->AllocateEntry(ptr)) 517 .first->second; 518 } 519 FindOrAddEntry(HeapThing ptr,HeapEntriesAllocator * allocator)520 HeapEntry* FindOrAddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) { 521 HeapEntry* entry = FindEntry(ptr); 522 return entry != nullptr ? entry : AddEntry(ptr, allocator); 523 } 524 525 private: 526 bool FillReferences(); 527 void ProgressStep() override; 528 bool ProgressReport(bool force = false) override; 529 void InitProgressCounter(); 530 531 HeapSnapshot* snapshot_; 532 v8::ActivityControl* control_; 533 V8HeapExplorer v8_heap_explorer_; 534 NativeObjectsExplorer dom_explorer_; 535 // Mapping from HeapThing pointers to HeapEntry indices. 536 HeapEntriesMap entries_map_; 537 // Used during snapshot generation. 538 int progress_counter_; 539 int progress_total_; 540 Heap* heap_; 541 542 DISALLOW_COPY_AND_ASSIGN(HeapSnapshotGenerator); 543 }; 544 545 class OutputStreamWriter; 546 547 class HeapSnapshotJSONSerializer { 548 public: HeapSnapshotJSONSerializer(HeapSnapshot * snapshot)549 explicit HeapSnapshotJSONSerializer(HeapSnapshot* snapshot) 550 : snapshot_(snapshot), 551 strings_(StringsMatch), 552 next_node_id_(1), 553 next_string_id_(1), 554 writer_(nullptr) {} 555 void Serialize(v8::OutputStream* stream); 556 557 private: StringsMatch(void * key1,void * key2)558 V8_INLINE static bool StringsMatch(void* key1, void* key2) { 559 return strcmp(reinterpret_cast<char*>(key1), 560 reinterpret_cast<char*>(key2)) == 0; 561 } 562 563 V8_INLINE static uint32_t StringHash(const void* string); 564 565 int GetStringId(const char* s); 566 V8_INLINE int to_node_index(const HeapEntry* e); 567 V8_INLINE int to_node_index(int entry_index); 568 void SerializeEdge(HeapGraphEdge* edge, bool first_edge); 569 void SerializeEdges(); 570 void SerializeImpl(); 571 void SerializeNode(const HeapEntry* entry); 572 void SerializeNodes(); 573 void SerializeSnapshot(); 574 void SerializeTraceTree(); 575 void SerializeTraceNode(AllocationTraceNode* node); 576 void SerializeTraceNodeInfos(); 577 void SerializeSamples(); 578 void SerializeString(const unsigned char* s); 579 void SerializeStrings(); 580 void SerializeLocation(const SourceLocation& location); 581 void SerializeLocations(); 582 583 static const int kEdgeFieldsCount; 584 static const int kNodeFieldsCount; 585 586 HeapSnapshot* snapshot_; 587 base::CustomMatcherHashMap strings_; 588 int next_node_id_; 589 int next_string_id_; 590 OutputStreamWriter* writer_; 591 592 friend class HeapSnapshotJSONSerializerEnumerator; 593 friend class HeapSnapshotJSONSerializerIterator; 594 595 DISALLOW_COPY_AND_ASSIGN(HeapSnapshotJSONSerializer); 596 }; 597 598 599 } // namespace internal 600 } // namespace v8 601 602 #endif // V8_PROFILER_HEAP_SNAPSHOT_GENERATOR_H_ 603