Home | History | Annotate | Download | only in profiler
      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 {
     37   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 
     62   Type type() const { return TypeField::decode(bit_field_); }
     63   int index() const {
     64     DCHECK(type() == kElement || type() == kHidden);
     65     return index_;
     66   }
     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;
     73   HeapEntry* to() const { return to_entry_; }
     74 
     75   V8_INLINE Isolate* isolate() const;
     76 
     77  private:
     78   V8_INLINE HeapSnapshot* snapshot() const;
     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 
    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 
    127   HeapSnapshot* snapshot() { return snapshot_; }
    128   Type type() const { return static_cast<Type>(type_); }
    129   void set_type(Type type) { type_ = type; }
    130   const char* name() const { return name_; }
    131   void set_name(const char* name) { name_ = name; }
    132   SnapshotObjectId id() const { return id_; }
    133   size_t self_size() const { return self_size_; }
    134   unsigned trace_node_id() const { return trace_node_id_; }
    135   V8_INLINE int index() const;
    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 
    177   HeapProfiler* profiler() { return profiler_; }
    178   HeapEntry* root() { return &entries_[root_index_]; }
    179   HeapEntry* gc_roots() { return &entries_[gc_roots_index_]; }
    180   HeapEntry* gc_subroot(Root root) {
    181     return &entries_[gc_subroot_indexes_[static_cast<int>(root)]];
    182   }
    183   std::vector<HeapEntry>& entries() { return entries_; }
    184   std::deque<HeapGraphEdge>& edges() { return edges_; }
    185   std::deque<HeapGraphEdge*>& children() { return children_; }
    186   const std::vector<SourceLocation>& locations() const { return locations_; }
    187   void RememberLastJSObjectId();
    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 {
    230     explicit TimeInterval(SnapshotObjectId id)
    231         : id(id), size(0), count(0), timestamp(base::TimeTicks::Now()) {}
    232     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 
    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);
    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);
    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 {
    271     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:
    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:
    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);
    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:
    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 {
    522     std::size_t operator()(v8::RetainedObjectInfo* info) const {
    523       return ComputeIntegerHash(static_cast<uint32_t>(info->GetHash()));
    524     }
    525   };
    526   struct RetainedInfoEquals {
    527     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:
    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:
    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