Home | History | Annotate | Download | only in src
      1 // Copyright 2013 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #ifndef V8_HEAP_SNAPSHOT_GENERATOR_H_
     29 #define V8_HEAP_SNAPSHOT_GENERATOR_H_
     30 
     31 #include "profile-generator-inl.h"
     32 
     33 namespace v8 {
     34 namespace internal {
     35 
     36 class AllocationTracker;
     37 class AllocationTraceNode;
     38 class HeapEntry;
     39 class HeapSnapshot;
     40 
     41 class HeapGraphEdge BASE_EMBEDDED {
     42  public:
     43   enum Type {
     44     kContextVariable = v8::HeapGraphEdge::kContextVariable,
     45     kElement = v8::HeapGraphEdge::kElement,
     46     kProperty = v8::HeapGraphEdge::kProperty,
     47     kInternal = v8::HeapGraphEdge::kInternal,
     48     kHidden = v8::HeapGraphEdge::kHidden,
     49     kShortcut = v8::HeapGraphEdge::kShortcut,
     50     kWeak = v8::HeapGraphEdge::kWeak
     51   };
     52 
     53   HeapGraphEdge() { }
     54   HeapGraphEdge(Type type, const char* name, int from, int to);
     55   HeapGraphEdge(Type type, int index, int from, int to);
     56   void ReplaceToIndexWithEntry(HeapSnapshot* snapshot);
     57 
     58   Type type() const { return static_cast<Type>(type_); }
     59   int index() const {
     60     ASSERT(type_ == kElement || type_ == kHidden || type_ == kWeak);
     61     return index_;
     62   }
     63   const char* name() const {
     64     ASSERT(type_ == kContextVariable
     65         || type_ == kProperty
     66         || type_ == kInternal
     67         || type_ == kShortcut);
     68     return name_;
     69   }
     70   INLINE(HeapEntry* from() const);
     71   HeapEntry* to() const { return to_entry_; }
     72 
     73  private:
     74   INLINE(HeapSnapshot* snapshot() const);
     75 
     76   unsigned type_ : 3;
     77   int from_index_ : 29;
     78   union {
     79     // During entries population |to_index_| is used for storing the index,
     80     // afterwards it is replaced with a pointer to the entry.
     81     int to_index_;
     82     HeapEntry* to_entry_;
     83   };
     84   union {
     85     int index_;
     86     const char* name_;
     87   };
     88 };
     89 
     90 
     91 // HeapEntry instances represent an entity from the heap (or a special
     92 // virtual node, e.g. root).
     93 class HeapEntry BASE_EMBEDDED {
     94  public:
     95   enum Type {
     96     kHidden = v8::HeapGraphNode::kHidden,
     97     kArray = v8::HeapGraphNode::kArray,
     98     kString = v8::HeapGraphNode::kString,
     99     kObject = v8::HeapGraphNode::kObject,
    100     kCode = v8::HeapGraphNode::kCode,
    101     kClosure = v8::HeapGraphNode::kClosure,
    102     kRegExp = v8::HeapGraphNode::kRegExp,
    103     kHeapNumber = v8::HeapGraphNode::kHeapNumber,
    104     kNative = v8::HeapGraphNode::kNative,
    105     kSynthetic = v8::HeapGraphNode::kSynthetic,
    106     kConsString = v8::HeapGraphNode::kConsString,
    107     kSlicedString = v8::HeapGraphNode::kSlicedString
    108   };
    109   static const int kNoEntry;
    110 
    111   HeapEntry() { }
    112   HeapEntry(HeapSnapshot* snapshot,
    113             Type type,
    114             const char* name,
    115             SnapshotObjectId id,
    116             int self_size);
    117 
    118   HeapSnapshot* snapshot() { return snapshot_; }
    119   Type type() { return static_cast<Type>(type_); }
    120   const char* name() { return name_; }
    121   void set_name(const char* name) { name_ = name; }
    122   inline SnapshotObjectId id() { return id_; }
    123   int self_size() { return self_size_; }
    124   INLINE(int index() const);
    125   int children_count() const { return children_count_; }
    126   INLINE(int set_children_index(int index));
    127   void add_child(HeapGraphEdge* edge) {
    128     children_arr()[children_count_++] = edge;
    129   }
    130   Vector<HeapGraphEdge*> children() {
    131     return Vector<HeapGraphEdge*>(children_arr(), children_count_); }
    132 
    133   void SetIndexedReference(
    134       HeapGraphEdge::Type type, int index, HeapEntry* entry);
    135   void SetNamedReference(
    136       HeapGraphEdge::Type type, const char* name, HeapEntry* entry);
    137 
    138   void Print(
    139       const char* prefix, const char* edge_name, int max_depth, int indent);
    140 
    141   Handle<HeapObject> GetHeapObject();
    142 
    143  private:
    144   INLINE(HeapGraphEdge** children_arr());
    145   const char* TypeAsString();
    146 
    147   unsigned type_: 4;
    148   int children_count_: 28;
    149   int children_index_;
    150   int self_size_;
    151   SnapshotObjectId id_;
    152   HeapSnapshot* snapshot_;
    153   const char* name_;
    154 };
    155 
    156 
    157 // HeapSnapshot represents a single heap snapshot. It is stored in
    158 // HeapProfiler, which is also a factory for
    159 // HeapSnapshots. All HeapSnapshots share strings copied from JS heap
    160 // to be able to return them even if they were collected.
    161 // HeapSnapshotGenerator fills in a HeapSnapshot.
    162 class HeapSnapshot {
    163  public:
    164   HeapSnapshot(HeapProfiler* profiler,
    165                const char* title,
    166                unsigned uid);
    167   void Delete();
    168 
    169   HeapProfiler* profiler() { return profiler_; }
    170   const char* title() { return title_; }
    171   unsigned uid() { return uid_; }
    172   size_t RawSnapshotSize() const;
    173   HeapEntry* root() { return &entries_[root_index_]; }
    174   HeapEntry* gc_roots() { return &entries_[gc_roots_index_]; }
    175   HeapEntry* natives_root() { return &entries_[natives_root_index_]; }
    176   HeapEntry* gc_subroot(int index) {
    177     return &entries_[gc_subroot_indexes_[index]];
    178   }
    179   List<HeapEntry>& entries() { return entries_; }
    180   List<HeapGraphEdge>& edges() { return edges_; }
    181   List<HeapGraphEdge*>& children() { return children_; }
    182   void RememberLastJSObjectId();
    183   SnapshotObjectId max_snapshot_js_object_id() const {
    184     return max_snapshot_js_object_id_;
    185   }
    186 
    187   HeapEntry* AddEntry(HeapEntry::Type type,
    188                       const char* name,
    189                       SnapshotObjectId id,
    190                       int size);
    191   HeapEntry* AddRootEntry();
    192   HeapEntry* AddGcRootsEntry();
    193   HeapEntry* AddGcSubrootEntry(int tag);
    194   HeapEntry* AddNativesRootEntry();
    195   HeapEntry* GetEntryById(SnapshotObjectId id);
    196   List<HeapEntry*>* GetSortedEntriesList();
    197   void FillChildren();
    198 
    199   void Print(int max_depth);
    200   void PrintEntriesSize();
    201 
    202  private:
    203   HeapProfiler* profiler_;
    204   const char* title_;
    205   unsigned uid_;
    206   int root_index_;
    207   int gc_roots_index_;
    208   int natives_root_index_;
    209   int gc_subroot_indexes_[VisitorSynchronization::kNumberOfSyncTags];
    210   List<HeapEntry> entries_;
    211   List<HeapGraphEdge> edges_;
    212   List<HeapGraphEdge*> children_;
    213   List<HeapEntry*> sorted_entries_;
    214   SnapshotObjectId max_snapshot_js_object_id_;
    215 
    216   friend class HeapSnapshotTester;
    217 
    218   DISALLOW_COPY_AND_ASSIGN(HeapSnapshot);
    219 };
    220 
    221 
    222 class HeapObjectsMap {
    223  public:
    224   explicit HeapObjectsMap(Heap* heap);
    225 
    226   Heap* heap() const { return heap_; }
    227 
    228   SnapshotObjectId FindEntry(Address addr);
    229   SnapshotObjectId FindOrAddEntry(Address addr,
    230                                   unsigned int size,
    231                                   bool accessed = true);
    232   void MoveObject(Address from, Address to, int size);
    233   void UpdateObjectSize(Address addr, int size);
    234   SnapshotObjectId last_assigned_id() const {
    235     return next_id_ - kObjectIdStep;
    236   }
    237 
    238   void StopHeapObjectsTracking();
    239   SnapshotObjectId PushHeapObjectsStats(OutputStream* stream);
    240   size_t GetUsedMemorySize() const;
    241 
    242   SnapshotObjectId GenerateId(v8::RetainedObjectInfo* info);
    243   static inline SnapshotObjectId GetNthGcSubrootId(int delta);
    244 
    245   static const int kObjectIdStep = 2;
    246   static const SnapshotObjectId kInternalRootObjectId;
    247   static const SnapshotObjectId kGcRootsObjectId;
    248   static const SnapshotObjectId kNativesRootObjectId;
    249   static const SnapshotObjectId kGcRootsFirstSubrootId;
    250   static const SnapshotObjectId kFirstAvailableObjectId;
    251 
    252   int FindUntrackedObjects();
    253 
    254   void UpdateHeapObjectsMap();
    255   void RemoveDeadEntries();
    256 
    257  private:
    258   struct EntryInfo {
    259   EntryInfo(SnapshotObjectId id, Address addr, unsigned int size)
    260       : id(id), addr(addr), size(size), accessed(true) { }
    261   EntryInfo(SnapshotObjectId id, Address addr, unsigned int size, bool accessed)
    262       : id(id), addr(addr), size(size), accessed(accessed) { }
    263     SnapshotObjectId id;
    264     Address addr;
    265     unsigned int size;
    266     bool accessed;
    267   };
    268   struct TimeInterval {
    269     explicit TimeInterval(SnapshotObjectId id) : id(id), size(0), count(0) { }
    270     SnapshotObjectId id;
    271     uint32_t size;
    272     uint32_t count;
    273   };
    274 
    275   SnapshotObjectId next_id_;
    276   HashMap entries_map_;
    277   List<EntryInfo> entries_;
    278   List<TimeInterval> time_intervals_;
    279   Heap* heap_;
    280 
    281   DISALLOW_COPY_AND_ASSIGN(HeapObjectsMap);
    282 };
    283 
    284 
    285 // A typedef for referencing anything that can be snapshotted living
    286 // in any kind of heap memory.
    287 typedef void* HeapThing;
    288 
    289 
    290 // An interface that creates HeapEntries by HeapThings.
    291 class HeapEntriesAllocator {
    292  public:
    293   virtual ~HeapEntriesAllocator() { }
    294   virtual HeapEntry* AllocateEntry(HeapThing ptr) = 0;
    295 };
    296 
    297 
    298 // The HeapEntriesMap instance is used to track a mapping between
    299 // real heap objects and their representations in heap snapshots.
    300 class HeapEntriesMap {
    301  public:
    302   HeapEntriesMap();
    303 
    304   int Map(HeapThing thing);
    305   void Pair(HeapThing thing, int entry);
    306 
    307  private:
    308   static uint32_t Hash(HeapThing thing) {
    309     return ComputeIntegerHash(
    310         static_cast<uint32_t>(reinterpret_cast<uintptr_t>(thing)),
    311         v8::internal::kZeroHashSeed);
    312   }
    313   static bool HeapThingsMatch(HeapThing key1, HeapThing key2) {
    314     return key1 == key2;
    315   }
    316 
    317   HashMap entries_;
    318 
    319   friend class HeapObjectsSet;
    320 
    321   DISALLOW_COPY_AND_ASSIGN(HeapEntriesMap);
    322 };
    323 
    324 
    325 class HeapObjectsSet {
    326  public:
    327   HeapObjectsSet();
    328   void Clear();
    329   bool Contains(Object* object);
    330   void Insert(Object* obj);
    331   const char* GetTag(Object* obj);
    332   void SetTag(Object* obj, const char* tag);
    333   bool is_empty() const { return entries_.occupancy() == 0; }
    334 
    335  private:
    336   HashMap entries_;
    337 
    338   DISALLOW_COPY_AND_ASSIGN(HeapObjectsSet);
    339 };
    340 
    341 
    342 // An interface used to populate a snapshot with nodes and edges.
    343 class SnapshotFillerInterface {
    344  public:
    345   virtual ~SnapshotFillerInterface() { }
    346   virtual HeapEntry* AddEntry(HeapThing ptr,
    347                               HeapEntriesAllocator* allocator) = 0;
    348   virtual HeapEntry* FindEntry(HeapThing ptr) = 0;
    349   virtual HeapEntry* FindOrAddEntry(HeapThing ptr,
    350                                     HeapEntriesAllocator* allocator) = 0;
    351   virtual void SetIndexedReference(HeapGraphEdge::Type type,
    352                                    int parent_entry,
    353                                    int index,
    354                                    HeapEntry* child_entry) = 0;
    355   virtual void SetIndexedAutoIndexReference(HeapGraphEdge::Type type,
    356                                             int parent_entry,
    357                                             HeapEntry* child_entry) = 0;
    358   virtual void SetNamedReference(HeapGraphEdge::Type type,
    359                                  int parent_entry,
    360                                  const char* reference_name,
    361                                  HeapEntry* child_entry) = 0;
    362   virtual void SetNamedAutoIndexReference(HeapGraphEdge::Type type,
    363                                           int parent_entry,
    364                                           HeapEntry* child_entry) = 0;
    365 };
    366 
    367 
    368 class SnapshottingProgressReportingInterface {
    369  public:
    370   virtual ~SnapshottingProgressReportingInterface() { }
    371   virtual void ProgressStep() = 0;
    372   virtual bool ProgressReport(bool force) = 0;
    373 };
    374 
    375 
    376 // An implementation of V8 heap graph extractor.
    377 class V8HeapExplorer : public HeapEntriesAllocator {
    378  public:
    379   V8HeapExplorer(HeapSnapshot* snapshot,
    380                  SnapshottingProgressReportingInterface* progress,
    381                  v8::HeapProfiler::ObjectNameResolver* resolver);
    382   virtual ~V8HeapExplorer();
    383   virtual HeapEntry* AllocateEntry(HeapThing ptr);
    384   void AddRootEntries(SnapshotFillerInterface* filler);
    385   int EstimateObjectsCount(HeapIterator* iterator);
    386   bool IterateAndExtractReferences(SnapshotFillerInterface* filler);
    387   void TagGlobalObjects();
    388   void TagCodeObject(Code* code);
    389   void TagCodeObject(Code* code, const char* external_name);
    390 
    391   static String* GetConstructorName(JSObject* object);
    392 
    393   static HeapObject* const kInternalRootObject;
    394 
    395  private:
    396   HeapEntry* AddEntry(HeapObject* object);
    397   HeapEntry* AddEntry(HeapObject* object,
    398                       HeapEntry::Type type,
    399                       const char* name);
    400   const char* GetSystemEntryName(HeapObject* object);
    401 
    402   void ExtractReferences(HeapObject* obj);
    403   void ExtractJSGlobalProxyReferences(int entry, JSGlobalProxy* proxy);
    404   void ExtractJSObjectReferences(int entry, JSObject* js_obj);
    405   void ExtractStringReferences(int entry, String* obj);
    406   void ExtractContextReferences(int entry, Context* context);
    407   void ExtractMapReferences(int entry, Map* map);
    408   void ExtractSharedFunctionInfoReferences(int entry,
    409                                            SharedFunctionInfo* shared);
    410   void ExtractScriptReferences(int entry, Script* script);
    411   void ExtractAccessorPairReferences(int entry, AccessorPair* accessors);
    412   void ExtractCodeCacheReferences(int entry, CodeCache* code_cache);
    413   void ExtractCodeReferences(int entry, Code* code);
    414   void ExtractCellReferences(int entry, Cell* cell);
    415   void ExtractPropertyCellReferences(int entry, PropertyCell* cell);
    416   void ExtractAllocationSiteReferences(int entry, AllocationSite* site);
    417   void ExtractClosureReferences(JSObject* js_obj, int entry);
    418   void ExtractPropertyReferences(JSObject* js_obj, int entry);
    419   bool ExtractAccessorPairProperty(JSObject* js_obj, int entry,
    420                                    Object* key, Object* callback_obj);
    421   void ExtractElementReferences(JSObject* js_obj, int entry);
    422   void ExtractInternalReferences(JSObject* js_obj, int entry);
    423   bool IsEssentialObject(Object* object);
    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,
    448                           int parent,
    449                           int index,
    450                           Object* child);
    451   void SetWeakReference(HeapObject* parent_obj,
    452                         int parent,
    453                         int index,
    454                         Object* child_obj,
    455                         int field_offset);
    456   void SetPropertyReference(HeapObject* parent_obj,
    457                             int parent,
    458                             Name* reference_name,
    459                             Object* child,
    460                             const char* name_format_string = NULL,
    461                             int field_offset = -1);
    462   void SetUserGlobalReference(Object* user_global);
    463   void SetRootGcRootsReference();
    464   void SetGcRootsReference(VisitorSynchronization::SyncTag tag);
    465   void SetGcSubrootReference(
    466       VisitorSynchronization::SyncTag tag, bool is_weak, Object* child);
    467   const char* GetStrongGcSubrootName(Object* object);
    468   void TagObject(Object* obj, const char* tag);
    469 
    470   HeapEntry* GetEntry(Object* obj);
    471 
    472   static inline HeapObject* GetNthGcSubrootObject(int delta);
    473   static inline int GetGcSubrootOrder(HeapObject* subroot);
    474 
    475   Heap* heap_;
    476   HeapSnapshot* snapshot_;
    477   StringsStorage* names_;
    478   HeapObjectsMap* heap_object_map_;
    479   SnapshottingProgressReportingInterface* progress_;
    480   SnapshotFillerInterface* filler_;
    481   HeapObjectsSet objects_tags_;
    482   HeapObjectsSet strong_gc_subroot_names_;
    483   HeapObjectsSet user_roots_;
    484   v8::HeapProfiler::ObjectNameResolver* global_object_name_resolver_;
    485 
    486   static HeapObject* const kGcRootsObject;
    487   static HeapObject* const kFirstGcSubrootObject;
    488   static HeapObject* const kLastGcSubrootObject;
    489 
    490   friend class IndexedReferencesExtractor;
    491   friend class GcSubrootsEnumerator;
    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   void AddRootEntries(SnapshotFillerInterface* filler);
    508   int EstimateObjectsCount();
    509   bool IterateAndExtractReferences(SnapshotFillerInterface* filler);
    510 
    511  private:
    512   void FillRetainedObjects();
    513   void FillImplicitReferences();
    514   List<HeapObject*>* GetListMaybeDisposeInfo(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   static uint32_t InfoHash(v8::RetainedObjectInfo* info) {
    522     return ComputeIntegerHash(static_cast<uint32_t>(info->GetHash()),
    523                               v8::internal::kZeroHashSeed);
    524   }
    525   static bool RetainedInfosMatch(void* key1, void* key2) {
    526     return key1 == key2 ||
    527         (reinterpret_cast<v8::RetainedObjectInfo*>(key1))->IsEquivalent(
    528             reinterpret_cast<v8::RetainedObjectInfo*>(key2));
    529   }
    530   INLINE(static bool StringsMatch(void* key1, void* key2)) {
    531     return strcmp(reinterpret_cast<char*>(key1),
    532                   reinterpret_cast<char*>(key2)) == 0;
    533   }
    534 
    535   NativeGroupRetainedObjectInfo* FindOrAddGroupInfo(const char* label);
    536 
    537   Isolate* isolate_;
    538   HeapSnapshot* snapshot_;
    539   StringsStorage* names_;
    540   SnapshottingProgressReportingInterface* progress_;
    541   bool embedder_queried_;
    542   HeapObjectsSet in_groups_;
    543   // RetainedObjectInfo* -> List<HeapObject*>*
    544   HashMap objects_by_info_;
    545   HashMap native_groups_;
    546   HeapEntriesAllocator* synthetic_entries_allocator_;
    547   HeapEntriesAllocator* native_entries_allocator_;
    548   // Used during references extraction.
    549   SnapshotFillerInterface* filler_;
    550 
    551   static HeapThing const kNativesRootObject;
    552 
    553   friend class GlobalHandlesExtractor;
    554 
    555   DISALLOW_COPY_AND_ASSIGN(NativeObjectsExplorer);
    556 };
    557 
    558 
    559 class HeapSnapshotGenerator : public SnapshottingProgressReportingInterface {
    560  public:
    561   HeapSnapshotGenerator(HeapSnapshot* snapshot,
    562                         v8::ActivityControl* control,
    563                         v8::HeapProfiler::ObjectNameResolver* resolver,
    564                         Heap* heap);
    565   bool GenerateSnapshot();
    566 
    567  private:
    568   bool FillReferences();
    569   void ProgressStep();
    570   bool ProgressReport(bool force = false);
    571   void SetProgressTotal(int iterations_count);
    572 
    573   HeapSnapshot* snapshot_;
    574   v8::ActivityControl* control_;
    575   V8HeapExplorer v8_heap_explorer_;
    576   NativeObjectsExplorer dom_explorer_;
    577   // Mapping from HeapThing pointers to HeapEntry* pointers.
    578   HeapEntriesMap entries_;
    579   // Used during snapshot generation.
    580   int progress_counter_;
    581   int progress_total_;
    582   Heap* heap_;
    583 
    584   DISALLOW_COPY_AND_ASSIGN(HeapSnapshotGenerator);
    585 };
    586 
    587 class OutputStreamWriter;
    588 
    589 class HeapSnapshotJSONSerializer {
    590  public:
    591   explicit HeapSnapshotJSONSerializer(HeapSnapshot* snapshot)
    592       : snapshot_(snapshot),
    593         strings_(StringsMatch),
    594         next_node_id_(1),
    595         next_string_id_(1),
    596         writer_(NULL) {
    597   }
    598   void Serialize(v8::OutputStream* stream);
    599 
    600  private:
    601   INLINE(static bool StringsMatch(void* key1, void* key2)) {
    602     return strcmp(reinterpret_cast<char*>(key1),
    603                   reinterpret_cast<char*>(key2)) == 0;
    604   }
    605 
    606   INLINE(static uint32_t StringHash(const void* string)) {
    607     const char* s = reinterpret_cast<const char*>(string);
    608     int len = static_cast<int>(strlen(s));
    609     return StringHasher::HashSequentialString(
    610         s, len, v8::internal::kZeroHashSeed);
    611   }
    612 
    613   int GetStringId(const char* s);
    614   int entry_index(HeapEntry* e) { return e->index() * kNodeFieldsCount; }
    615   void SerializeEdge(HeapGraphEdge* edge, bool first_edge);
    616   void SerializeEdges();
    617   void SerializeImpl();
    618   void SerializeNode(HeapEntry* entry);
    619   void SerializeNodes();
    620   void SerializeSnapshot();
    621   void SerializeTraceTree();
    622   void SerializeTraceNode(AllocationTraceNode* node);
    623   void SerializeTraceNodeInfos();
    624   void SerializeString(const unsigned char* s);
    625   void SerializeStrings();
    626 
    627   static const int kEdgeFieldsCount;
    628   static const int kNodeFieldsCount;
    629 
    630   HeapSnapshot* snapshot_;
    631   HashMap strings_;
    632   int next_node_id_;
    633   int next_string_id_;
    634   OutputStreamWriter* writer_;
    635 
    636   friend class HeapSnapshotJSONSerializerEnumerator;
    637   friend class HeapSnapshotJSONSerializerIterator;
    638 
    639   DISALLOW_COPY_AND_ASSIGN(HeapSnapshotJSONSerializer);
    640 };
    641 
    642 
    643 } }  // namespace v8::internal
    644 
    645 #endif  // V8_HEAP_SNAPSHOT_GENERATOR_H_
    646