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