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