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