heap-snapshot-generator.h 20.8 KB
Newer Older
1
// Copyright 2013 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4

5 6
#ifndef V8_PROFILER_HEAP_SNAPSHOT_GENERATOR_H_
#define V8_PROFILER_HEAP_SNAPSHOT_GENERATOR_H_
7

8
#include <deque>
9 10
#include <unordered_map>

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 17 18
namespace v8 {
namespace internal {

19 20
class AllocationTracker;
class AllocationTraceNode;
21
class HeapEntry;
22 23
class HeapIterator;
class HeapProfiler;
24
class HeapSnapshot;
25
class SnapshotFiller;
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42

class HeapGraphEdge BASE_EMBEDDED {
 public:
  enum Type {
    kContextVariable = v8::HeapGraphEdge::kContextVariable,
    kElement = v8::HeapGraphEdge::kElement,
    kProperty = v8::HeapGraphEdge::kProperty,
    kInternal = v8::HeapGraphEdge::kInternal,
    kHidden = v8::HeapGraphEdge::kHidden,
    kShortcut = v8::HeapGraphEdge::kShortcut,
    kWeak = v8::HeapGraphEdge::kWeak
  };

  HeapGraphEdge(Type type, const char* name, int from, int to);
  HeapGraphEdge(Type type, int index, int from, int to);
  void ReplaceToIndexWithEntry(HeapSnapshot* snapshot);

43
  Type type() const { return TypeField::decode(bit_field_); }
44
  int index() const {
45
    DCHECK(type() == kElement || type() == kHidden);
46 47 48
    return index_;
  }
  const char* name() const {
49 50
    DCHECK(type() == kContextVariable || type() == kProperty ||
           type() == kInternal || type() == kShortcut || type() == kWeak);
51 52 53 54 55
    return name_;
  }
  INLINE(HeapEntry* from() const);
  HeapEntry* to() const { return to_entry_; }

56 57
  INLINE(Isolate* isolate() const);

58 59
 private:
  INLINE(HeapSnapshot* snapshot() const);
60
  int from_index() const { return FromIndexField::decode(bit_field_); }
61

62 63 64
  class TypeField : public BitField<Type, 0, 3> {};
  class FromIndexField : public BitField<int, 3, 29> {};
  uint32_t bit_field_;
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
  union {
    // During entries population |to_index_| is used for storing the index,
    // afterwards it is replaced with a pointer to the entry.
    int to_index_;
    HeapEntry* to_entry_;
  };
  union {
    int index_;
    const char* name_;
  };
};


// HeapEntry instances represent an entity from the heap (or a special
// virtual node, e.g. root).
class HeapEntry BASE_EMBEDDED {
 public:
  enum Type {
    kHidden = v8::HeapGraphNode::kHidden,
    kArray = v8::HeapGraphNode::kArray,
    kString = v8::HeapGraphNode::kString,
    kObject = v8::HeapGraphNode::kObject,
    kCode = v8::HeapGraphNode::kCode,
    kClosure = v8::HeapGraphNode::kClosure,
    kRegExp = v8::HeapGraphNode::kRegExp,
    kHeapNumber = v8::HeapGraphNode::kHeapNumber,
    kNative = v8::HeapGraphNode::kNative,
92 93
    kSynthetic = v8::HeapGraphNode::kSynthetic,
    kConsString = v8::HeapGraphNode::kConsString,
94
    kSlicedString = v8::HeapGraphNode::kSlicedString,
bbudge's avatar
bbudge committed
95
    kSymbol = v8::HeapGraphNode::kSymbol
96 97 98 99 100 101 102 103
  };
  static const int kNoEntry;

  HeapEntry() { }
  HeapEntry(HeapSnapshot* snapshot,
            Type type,
            const char* name,
            SnapshotObjectId id,
104 105
            size_t self_size,
            unsigned trace_node_id);
106 107 108 109 110

  HeapSnapshot* snapshot() { return snapshot_; }
  Type type() { return static_cast<Type>(type_); }
  const char* name() { return name_; }
  void set_name(const char* name) { name_ = name; }
111
  SnapshotObjectId id() { return id_; }
112
  size_t self_size() { return self_size_; }
113
  unsigned trace_node_id() const { return trace_node_id_; }
114 115 116 117
  INLINE(int index() const);
  int children_count() const { return children_count_; }
  INLINE(int set_children_index(int index));
  void add_child(HeapGraphEdge* edge) {
118
    *(children_begin() + children_count_++) = edge;
119
  }
120
  HeapGraphEdge* child(int i) { return *(children_begin() + i); }
121
  INLINE(Isolate* isolate() const);
122 123 124 125 126 127 128 129 130 131

  void SetIndexedReference(
      HeapGraphEdge::Type type, int index, HeapEntry* entry);
  void SetNamedReference(
      HeapGraphEdge::Type type, const char* name, HeapEntry* entry);

  void Print(
      const char* prefix, const char* edge_name, int max_depth, int indent);

 private:
132 133
  INLINE(std::deque<HeapGraphEdge*>::iterator children_begin());
  INLINE(std::deque<HeapGraphEdge*>::iterator children_end());
134 135 136 137 138
  const char* TypeAsString();

  unsigned type_: 4;
  int children_count_: 28;
  int children_index_;
139
  size_t self_size_;
140 141
  HeapSnapshot* snapshot_;
  const char* name_;
142 143 144
  SnapshotObjectId id_;
  // id of allocation stack trace top node
  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 151 152 153 154
// HeapSnapshots. All HeapSnapshots share strings copied from JS heap
// to be able to return them even if they were collected.
// HeapSnapshotGenerator fills in a HeapSnapshot.
class HeapSnapshot {
 public:
155
  explicit HeapSnapshot(HeapProfiler* profiler);
156 157
  void Delete();

158
  HeapProfiler* profiler() { return profiler_; }
159 160 161 162 163 164 165
  size_t RawSnapshotSize() const;
  HeapEntry* root() { return &entries_[root_index_]; }
  HeapEntry* gc_roots() { return &entries_[gc_roots_index_]; }
  HeapEntry* gc_subroot(int index) {
    return &entries_[gc_subroot_indexes_[index]];
  }
  List<HeapEntry>& entries() { return entries_; }
166 167
  std::deque<HeapGraphEdge>& edges() { return edges_; }
  std::deque<HeapGraphEdge*>& children() { return children_; }
168 169 170 171 172 173 174 175
  void RememberLastJSObjectId();
  SnapshotObjectId max_snapshot_js_object_id() const {
    return max_snapshot_js_object_id_;
  }

  HeapEntry* AddEntry(HeapEntry::Type type,
                      const char* name,
                      SnapshotObjectId id,
176 177
                      size_t size,
                      unsigned trace_node_id);
178
  void AddSyntheticRootEntries();
179 180 181 182 183 184 185
  HeapEntry* GetEntryById(SnapshotObjectId id);
  List<HeapEntry*>* GetSortedEntriesList();
  void FillChildren();

  void Print(int max_depth);

 private:
186 187 188 189
  HeapEntry* AddRootEntry();
  HeapEntry* AddGcRootsEntry();
  HeapEntry* AddGcSubrootEntry(int tag, SnapshotObjectId id);

190
  HeapProfiler* profiler_;
191 192 193 194
  int root_index_;
  int gc_roots_index_;
  int gc_subroot_indexes_[VisitorSynchronization::kNumberOfSyncTags];
  List<HeapEntry> entries_;
195 196
  std::deque<HeapGraphEdge> edges_;
  std::deque<HeapGraphEdge*> children_;
197 198 199 200 201 202 203 204 205 206 207
  List<HeapEntry*> sorted_entries_;
  SnapshotObjectId max_snapshot_js_object_id_;

  friend class HeapSnapshotTester;

  DISALLOW_COPY_AND_ASSIGN(HeapSnapshot);
};


class HeapObjectsMap {
 public:
208 209 210 211 212 213 214 215 216 217
  struct TimeInterval {
    explicit TimeInterval(SnapshotObjectId id)
        : id(id), size(0), count(0), timestamp(base::TimeTicks::Now()) {}
    SnapshotObjectId last_assigned_id() const { return id - kObjectIdStep; }
    SnapshotObjectId id;
    uint32_t size;
    uint32_t count;
    base::TimeTicks timestamp;
  };

218 219 220 221 222
  explicit HeapObjectsMap(Heap* heap);

  Heap* heap() const { return heap_; }

  SnapshotObjectId FindEntry(Address addr);
223 224 225
  SnapshotObjectId FindOrAddEntry(Address addr,
                                  unsigned int size,
                                  bool accessed = true);
226
  bool MoveObject(Address from, Address to, int size);
227
  void UpdateObjectSize(Address addr, int size);
228 229 230 231 232
  SnapshotObjectId last_assigned_id() const {
    return next_id_ - kObjectIdStep;
  }

  void StopHeapObjectsTracking();
233 234
  SnapshotObjectId PushHeapObjectsStats(OutputStream* stream,
                                        int64_t* timestamp_us);
235
  const List<TimeInterval>& samples() const { return time_intervals_; }
236 237
  size_t GetUsedMemorySize() const;

238
  SnapshotObjectId GenerateId(v8::RetainedObjectInfo* info);
239 240 241 242 243 244 245

  static const int kObjectIdStep = 2;
  static const SnapshotObjectId kInternalRootObjectId;
  static const SnapshotObjectId kGcRootsObjectId;
  static const SnapshotObjectId kGcRootsFirstSubrootId;
  static const SnapshotObjectId kFirstAvailableObjectId;

246 247 248
  int FindUntrackedObjects();

  void UpdateHeapObjectsMap();
249
  void RemoveDeadEntries();
250

251 252 253 254 255 256 257 258 259 260 261 262 263
 private:
  struct EntryInfo {
  EntryInfo(SnapshotObjectId id, Address addr, unsigned int size)
      : id(id), addr(addr), size(size), accessed(true) { }
  EntryInfo(SnapshotObjectId id, Address addr, unsigned int size, bool accessed)
      : id(id), addr(addr), size(size), accessed(accessed) { }
    SnapshotObjectId id;
    Address addr;
    unsigned int size;
    bool accessed;
  };

  SnapshotObjectId next_id_;
lpy's avatar
lpy committed
264
  base::HashMap entries_map_;
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
  List<EntryInfo> entries_;
  List<TimeInterval> time_intervals_;
  Heap* heap_;

  DISALLOW_COPY_AND_ASSIGN(HeapObjectsMap);
};


// A typedef for referencing anything that can be snapshotted living
// in any kind of heap memory.
typedef void* HeapThing;


// An interface that creates HeapEntries by HeapThings.
class HeapEntriesAllocator {
 public:
  virtual ~HeapEntriesAllocator() { }
  virtual HeapEntry* AllocateEntry(HeapThing ptr) = 0;
};


// The HeapEntriesMap instance is used to track a mapping between
// real heap objects and their representations in heap snapshots.
class HeapEntriesMap {
 public:
  HeapEntriesMap();

  int Map(HeapThing thing);
  void Pair(HeapThing thing, int entry);

 private:
  static uint32_t Hash(HeapThing thing) {
    return ComputeIntegerHash(
        static_cast<uint32_t>(reinterpret_cast<uintptr_t>(thing)),
        v8::internal::kZeroHashSeed);
  }

lpy's avatar
lpy committed
302
  base::HashMap entries_;
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320

  friend class HeapObjectsSet;

  DISALLOW_COPY_AND_ASSIGN(HeapEntriesMap);
};


class HeapObjectsSet {
 public:
  HeapObjectsSet();
  void Clear();
  bool Contains(Object* object);
  void Insert(Object* obj);
  const char* GetTag(Object* obj);
  void SetTag(Object* obj, const char* tag);
  bool is_empty() const { return entries_.occupancy() == 0; }

 private:
lpy's avatar
lpy committed
321
  base::HashMap entries_;
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343

  DISALLOW_COPY_AND_ASSIGN(HeapObjectsSet);
};


class SnapshottingProgressReportingInterface {
 public:
  virtual ~SnapshottingProgressReportingInterface() { }
  virtual void ProgressStep() = 0;
  virtual bool ProgressReport(bool force) = 0;
};


// An implementation of V8 heap graph extractor.
class V8HeapExplorer : public HeapEntriesAllocator {
 public:
  V8HeapExplorer(HeapSnapshot* snapshot,
                 SnapshottingProgressReportingInterface* progress,
                 v8::HeapProfiler::ObjectNameResolver* resolver);
  virtual ~V8HeapExplorer();
  virtual HeapEntry* AllocateEntry(HeapThing ptr);
  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 349 350
  HeapEntry* AddEntry(Address address,
                      HeapEntry::Type type,
                      const char* name,
351
                      size_t size);
352 353 354 355

  static String* GetConstructorName(JSObject* object);

 private:
356 357 358
  typedef bool (V8HeapExplorer::*ExtractReferencesMethod)(int entry,
                                                          HeapObject* object);

359 360
  void MarkVisitedField(HeapObject* obj, int offset);

361 362 363 364
  HeapEntry* AddEntry(HeapObject* object);
  HeapEntry* AddEntry(HeapObject* object,
                      HeapEntry::Type type,
                      const char* name);
365

366 367
  const char* GetSystemEntryName(HeapObject* object);

368 369
  template<V8HeapExplorer::ExtractReferencesMethod extractor>
  bool IterateAndExtractSinglePass();
370 371 372

  bool ExtractReferencesPass1(int entry, HeapObject* obj);
  bool ExtractReferencesPass2(int entry, HeapObject* obj);
373
  void ExtractJSGlobalProxyReferences(int entry, JSGlobalProxy* proxy);
374 375
  void ExtractJSObjectReferences(int entry, JSObject* js_obj);
  void ExtractStringReferences(int entry, String* obj);
376
  void ExtractSymbolReferences(int entry, Symbol* symbol);
377
  void ExtractJSCollectionReferences(int entry, JSCollection* collection);
378 379
  void ExtractJSWeakCollectionReferences(int entry,
                                         JSWeakCollection* collection);
380 381 382 383 384
  void ExtractContextReferences(int entry, Context* context);
  void ExtractMapReferences(int entry, Map* map);
  void ExtractSharedFunctionInfoReferences(int entry,
                                           SharedFunctionInfo* shared);
  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 396
  void ExtractAccessorPairProperty(JSObject* js_obj, int entry, Name* key,
                                   Object* callback_obj, int field_offset = -1);
397 398
  void ExtractElementReferences(JSObject* js_obj, int entry);
  void ExtractInternalReferences(JSObject* js_obj, int entry);
399

400
  bool IsEssentialObject(Object* object);
401 402
  bool IsEssentialHiddenReference(Object* parent, int field_offset);

403
  void SetContextReference(HeapObject* parent_obj,
404 405
                           int parent,
                           String* reference_name,
406 407
                           Object* child,
                           int field_offset);
408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425
  void SetNativeBindReference(HeapObject* parent_obj,
                              int parent,
                              const char* reference_name,
                              Object* child);
  void SetElementReference(HeapObject* parent_obj,
                           int parent,
                           int index,
                           Object* child);
  void SetInternalReference(HeapObject* parent_obj,
                            int parent,
                            const char* reference_name,
                            Object* child,
                            int field_offset = -1);
  void SetInternalReference(HeapObject* parent_obj,
                            int parent,
                            int index,
                            Object* child,
                            int field_offset = -1);
426 427
  void SetHiddenReference(HeapObject* parent_obj, int parent, int index,
                          Object* child, int field_offset);
428 429
  void SetWeakReference(HeapObject* parent_obj,
                        int parent,
430
                        const char* reference_name,
431 432
                        Object* child_obj,
                        int field_offset);
433 434 435 436 437
  void SetWeakReference(HeapObject* parent_obj,
                        int parent,
                        int index,
                        Object* child_obj,
                        int field_offset);
438 439
  void SetPropertyReference(HeapObject* parent_obj,
                            int parent,
440
                            Name* reference_name,
441 442 443
                            Object* child,
                            const char* name_format_string = NULL,
                            int field_offset = -1);
444 445 446 447 448 449
  void SetDataOrAccessorPropertyReference(PropertyKind kind,
                                          JSObject* parent_obj, int parent,
                                          Name* reference_name, Object* child,
                                          const char* name_format_string = NULL,
                                          int field_offset = -1);

450 451 452 453 454 455 456
  void SetUserGlobalReference(Object* user_global);
  void SetRootGcRootsReference();
  void SetGcRootsReference(VisitorSynchronization::SyncTag tag);
  void SetGcSubrootReference(
      VisitorSynchronization::SyncTag tag, bool is_weak, Object* child);
  const char* GetStrongGcSubrootName(Object* object);
  void TagObject(Object* obj, const char* tag);
457 458
  void TagFixedArraySubType(const FixedArray* array,
                            FixedArraySubInstanceType type);
459 460 461 462 463

  HeapEntry* GetEntry(Object* obj);

  Heap* heap_;
  HeapSnapshot* snapshot_;
464 465
  StringsStorage* names_;
  HeapObjectsMap* heap_object_map_;
466
  SnapshottingProgressReportingInterface* progress_;
467
  SnapshotFiller* filler_;
468 469
  HeapObjectsSet objects_tags_;
  HeapObjectsSet strong_gc_subroot_names_;
470
  HeapObjectsSet user_roots_;
471
  std::unordered_map<const FixedArray*, FixedArraySubInstanceType> array_types_;
472 473
  v8::HeapProfiler::ObjectNameResolver* global_object_name_resolver_;

474 475
  std::vector<bool> marks_;

476 477 478 479 480 481 482 483 484 485 486 487 488 489
  friend class IndexedReferencesExtractor;
  friend class RootsReferencesExtractor;

  DISALLOW_COPY_AND_ASSIGN(V8HeapExplorer);
};


class NativeGroupRetainedObjectInfo;


// An implementation of retained native objects extractor.
class NativeObjectsExplorer {
 public:
  NativeObjectsExplorer(HeapSnapshot* snapshot,
490
                        SnapshottingProgressReportingInterface* progress);
491 492
  virtual ~NativeObjectsExplorer();
  int EstimateObjectsCount();
493
  bool IterateAndExtractReferences(SnapshotFiller* filler);
494 495 496

 private:
  void FillRetainedObjects();
497
  void FillEdges();
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520
  List<HeapObject*>* GetListMaybeDisposeInfo(v8::RetainedObjectInfo* info);
  void SetNativeRootReference(v8::RetainedObjectInfo* info);
  void SetRootNativeRootsReference();
  void SetWrapperNativeReferences(HeapObject* wrapper,
                                      v8::RetainedObjectInfo* info);
  void VisitSubtreeWrapper(Object** p, uint16_t class_id);

  static uint32_t InfoHash(v8::RetainedObjectInfo* info) {
    return ComputeIntegerHash(static_cast<uint32_t>(info->GetHash()),
                              v8::internal::kZeroHashSeed);
  }
  static bool RetainedInfosMatch(void* key1, void* key2) {
    return key1 == key2 ||
        (reinterpret_cast<v8::RetainedObjectInfo*>(key1))->IsEquivalent(
            reinterpret_cast<v8::RetainedObjectInfo*>(key2));
  }
  INLINE(static bool StringsMatch(void* key1, void* key2)) {
    return strcmp(reinterpret_cast<char*>(key1),
                  reinterpret_cast<char*>(key2)) == 0;
  }

  NativeGroupRetainedObjectInfo* FindOrAddGroupInfo(const char* label);

521
  Isolate* isolate_;
522
  HeapSnapshot* snapshot_;
523
  StringsStorage* names_;
524 525 526
  bool embedder_queried_;
  HeapObjectsSet in_groups_;
  // RetainedObjectInfo* -> List<HeapObject*>*
527 528
  base::CustomMatcherHashMap objects_by_info_;
  base::CustomMatcherHashMap native_groups_;
529 530 531
  HeapEntriesAllocator* synthetic_entries_allocator_;
  HeapEntriesAllocator* native_entries_allocator_;
  // Used during references extraction.
532
  SnapshotFiller* filler_;
533
  v8::HeapProfiler::RetainerEdges edges_;
534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576

  static HeapThing const kNativesRootObject;

  friend class GlobalHandlesExtractor;

  DISALLOW_COPY_AND_ASSIGN(NativeObjectsExplorer);
};


class HeapSnapshotGenerator : public SnapshottingProgressReportingInterface {
 public:
  HeapSnapshotGenerator(HeapSnapshot* snapshot,
                        v8::ActivityControl* control,
                        v8::HeapProfiler::ObjectNameResolver* resolver,
                        Heap* heap);
  bool GenerateSnapshot();

 private:
  bool FillReferences();
  void ProgressStep();
  bool ProgressReport(bool force = false);
  void SetProgressTotal(int iterations_count);

  HeapSnapshot* snapshot_;
  v8::ActivityControl* control_;
  V8HeapExplorer v8_heap_explorer_;
  NativeObjectsExplorer dom_explorer_;
  // Mapping from HeapThing pointers to HeapEntry* pointers.
  HeapEntriesMap entries_;
  // Used during snapshot generation.
  int progress_counter_;
  int progress_total_;
  Heap* heap_;

  DISALLOW_COPY_AND_ASSIGN(HeapSnapshotGenerator);
};

class OutputStreamWriter;

class HeapSnapshotJSONSerializer {
 public:
  explicit HeapSnapshotJSONSerializer(HeapSnapshot* snapshot)
      : snapshot_(snapshot),
577
        strings_(StringsMatch),
578 579 580 581 582 583 584
        next_node_id_(1),
        next_string_id_(1),
        writer_(NULL) {
  }
  void Serialize(v8::OutputStream* stream);

 private:
585 586 587
  INLINE(static bool StringsMatch(void* key1, void* key2)) {
    return strcmp(reinterpret_cast<char*>(key1),
                  reinterpret_cast<char*>(key2)) == 0;
588 589
  }

590 591 592 593 594
  INLINE(static uint32_t StringHash(const void* string)) {
    const char* s = reinterpret_cast<const char*>(string);
    int len = static_cast<int>(strlen(s));
    return StringHasher::HashSequentialString(
        s, len, v8::internal::kZeroHashSeed);
595 596 597 598 599 600 601 602 603 604
  }

  int GetStringId(const char* s);
  int entry_index(HeapEntry* e) { return e->index() * kNodeFieldsCount; }
  void SerializeEdge(HeapGraphEdge* edge, bool first_edge);
  void SerializeEdges();
  void SerializeImpl();
  void SerializeNode(HeapEntry* entry);
  void SerializeNodes();
  void SerializeSnapshot();
605 606 607
  void SerializeTraceTree();
  void SerializeTraceNode(AllocationTraceNode* node);
  void SerializeTraceNodeInfos();
608
  void SerializeSamples();
609 610 611 612 613 614 615
  void SerializeString(const unsigned char* s);
  void SerializeStrings();

  static const int kEdgeFieldsCount;
  static const int kNodeFieldsCount;

  HeapSnapshot* snapshot_;
616
  base::CustomMatcherHashMap strings_;
617 618 619 620 621 622 623 624 625 626 627
  int next_node_id_;
  int next_string_id_;
  OutputStreamWriter* writer_;

  friend class HeapSnapshotJSONSerializerEnumerator;
  friend class HeapSnapshotJSONSerializerIterator;

  DISALLOW_COPY_AND_ASSIGN(HeapSnapshotJSONSerializer);
};


628 629
}  // namespace internal
}  // namespace v8
630

631
#endif  // V8_PROFILER_HEAP_SNAPSHOT_GENERATOR_H_