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