The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / heap-snapshot-generator.h @ f230a1cf

History | View | Annotate | Download (23.5 KB)

1
// Copyright 2013 the V8 project authors. All rights reserved.
2
// Redistribution and use in source and binary forms, with or without
3
// modification, are permitted provided that the following conditions are
4
// met:
5
//
6
//     * Redistributions of source code must retain the above copyright
7
//       notice, this list of conditions and the following disclaimer.
8
//     * Redistributions in binary form must reproduce the above
9
//       copyright notice, this list of conditions and the following
10
//       disclaimer in the documentation and/or other materials provided
11
//       with the distribution.
12
//     * Neither the name of Google Inc. nor the names of its
13
//       contributors may be used to endorse or promote products derived
14
//       from this software without specific prior written permission.
15
//
16
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27

    
28
#ifndef V8_HEAP_SNAPSHOT_GENERATOR_H_
29
#define V8_HEAP_SNAPSHOT_GENERATOR_H_
30

    
31
#include "profile-generator-inl.h"
32

    
33
namespace v8 {
34
namespace internal {
35

    
36
class AllocationTracker;
37
class AllocationTraceNode;
38
class HeapEntry;
39
class HeapSnapshot;
40

    
41
class HeapGraphEdge BASE_EMBEDDED {
42
 public:
43
  enum Type {
44
    kContextVariable = v8::HeapGraphEdge::kContextVariable,
45
    kElement = v8::HeapGraphEdge::kElement,
46
    kProperty = v8::HeapGraphEdge::kProperty,
47
    kInternal = v8::HeapGraphEdge::kInternal,
48
    kHidden = v8::HeapGraphEdge::kHidden,
49
    kShortcut = v8::HeapGraphEdge::kShortcut,
50
    kWeak = v8::HeapGraphEdge::kWeak
51
  };
52

    
53
  HeapGraphEdge() { }
54
  HeapGraphEdge(Type type, const char* name, int from, int to);
55
  HeapGraphEdge(Type type, int index, int from, int to);
56
  void ReplaceToIndexWithEntry(HeapSnapshot* snapshot);
57

    
58
  Type type() const { return static_cast<Type>(type_); }
59
  int index() const {
60
    ASSERT(type_ == kElement || type_ == kHidden || type_ == kWeak);
61
    return index_;
62
  }
63
  const char* name() const {
64
    ASSERT(type_ == kContextVariable
65
        || type_ == kProperty
66
        || type_ == kInternal
67
        || type_ == kShortcut);
68
    return name_;
69
  }
70
  INLINE(HeapEntry* from() const);
71
  HeapEntry* to() const { return to_entry_; }
72

    
73
 private:
74
  INLINE(HeapSnapshot* snapshot() const);
75

    
76
  unsigned type_ : 3;
77
  int from_index_ : 29;
78
  union {
79
    // During entries population |to_index_| is used for storing the index,
80
    // afterwards it is replaced with a pointer to the entry.
81
    int to_index_;
82
    HeapEntry* to_entry_;
83
  };
84
  union {
85
    int index_;
86
    const char* name_;
87
  };
88
};
89

    
90

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

    
111
  HeapEntry() { }
112
  HeapEntry(HeapSnapshot* snapshot,
113
            Type type,
114
            const char* name,
115
            SnapshotObjectId id,
116
            int self_size);
117

    
118
  HeapSnapshot* snapshot() { return snapshot_; }
119
  Type type() { return static_cast<Type>(type_); }
120
  const char* name() { return name_; }
121
  void set_name(const char* name) { name_ = name; }
122
  inline SnapshotObjectId id() { return id_; }
123
  int self_size() { return self_size_; }
124
  INLINE(int index() const);
125
  int children_count() const { return children_count_; }
126
  INLINE(int set_children_index(int index));
127
  void add_child(HeapGraphEdge* edge) {
128
    children_arr()[children_count_++] = edge;
129
  }
130
  Vector<HeapGraphEdge*> children() {
131
    return Vector<HeapGraphEdge*>(children_arr(), children_count_); }
132

    
133
  void SetIndexedReference(
134
      HeapGraphEdge::Type type, int index, HeapEntry* entry);
135
  void SetNamedReference(
136
      HeapGraphEdge::Type type, const char* name, HeapEntry* entry);
137

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

    
141
  Handle<HeapObject> GetHeapObject();
142

    
143
 private:
144
  INLINE(HeapGraphEdge** children_arr());
145
  const char* TypeAsString();
146

    
147
  unsigned type_: 4;
148
  int children_count_: 28;
149
  int children_index_;
150
  int self_size_;
151
  SnapshotObjectId id_;
152
  HeapSnapshot* snapshot_;
153
  const char* name_;
154
};
155

    
156

    
157
class HeapSnapshotsCollection;
158

    
159
// HeapSnapshot represents a single heap snapshot. It is stored in
160
// HeapSnapshotsCollection, which is also a factory for
161
// HeapSnapshots. All HeapSnapshots share strings copied from JS heap
162
// to be able to return them even if they were collected.
163
// HeapSnapshotGenerator fills in a HeapSnapshot.
164
class HeapSnapshot {
165
 public:
166
  HeapSnapshot(HeapSnapshotsCollection* collection,
167
               const char* title,
168
               unsigned uid);
169
  void Delete();
170

    
171
  HeapSnapshotsCollection* collection() { return collection_; }
172
  const char* title() { return title_; }
173
  unsigned uid() { return uid_; }
174
  size_t RawSnapshotSize() const;
175
  HeapEntry* root() { return &entries_[root_index_]; }
176
  HeapEntry* gc_roots() { return &entries_[gc_roots_index_]; }
177
  HeapEntry* natives_root() { return &entries_[natives_root_index_]; }
178
  HeapEntry* gc_subroot(int index) {
179
    return &entries_[gc_subroot_indexes_[index]];
180
  }
181
  List<HeapEntry>& entries() { return entries_; }
182
  List<HeapGraphEdge>& edges() { return edges_; }
183
  List<HeapGraphEdge*>& children() { return children_; }
184
  void RememberLastJSObjectId();
185
  SnapshotObjectId max_snapshot_js_object_id() const {
186
    return max_snapshot_js_object_id_;
187
  }
188

    
189
  HeapEntry* AddEntry(HeapEntry::Type type,
190
                      const char* name,
191
                      SnapshotObjectId id,
192
                      int size);
193
  HeapEntry* AddRootEntry();
194
  HeapEntry* AddGcRootsEntry();
195
  HeapEntry* AddGcSubrootEntry(int tag);
196
  HeapEntry* AddNativesRootEntry();
197
  HeapEntry* GetEntryById(SnapshotObjectId id);
198
  List<HeapEntry*>* GetSortedEntriesList();
199
  void FillChildren();
200

    
201
  void Print(int max_depth);
202
  void PrintEntriesSize();
203

    
204
 private:
205
  HeapSnapshotsCollection* collection_;
206
  const char* title_;
207
  unsigned uid_;
208
  int root_index_;
209
  int gc_roots_index_;
210
  int natives_root_index_;
211
  int gc_subroot_indexes_[VisitorSynchronization::kNumberOfSyncTags];
212
  List<HeapEntry> entries_;
213
  List<HeapGraphEdge> edges_;
214
  List<HeapGraphEdge*> children_;
215
  List<HeapEntry*> sorted_entries_;
216
  SnapshotObjectId max_snapshot_js_object_id_;
217

    
218
  friend class HeapSnapshotTester;
219

    
220
  DISALLOW_COPY_AND_ASSIGN(HeapSnapshot);
221
};
222

    
223

    
224
class HeapObjectsMap {
225
 public:
226
  explicit HeapObjectsMap(Heap* heap);
227

    
228
  Heap* heap() const { return heap_; }
229

    
230
  void SnapshotGenerationFinished();
231
  SnapshotObjectId FindEntry(Address addr);
232
  SnapshotObjectId FindOrAddEntry(Address addr,
233
                                  unsigned int size,
234
                                  bool accessed = true);
235
  void MoveObject(Address from, Address to, int size);
236
  void NewObject(Address addr, int size);
237
  void UpdateObjectSize(Address addr, int size);
238
  SnapshotObjectId last_assigned_id() const {
239
    return next_id_ - kObjectIdStep;
240
  }
241

    
242
  void StopHeapObjectsTracking();
243
  SnapshotObjectId PushHeapObjectsStats(OutputStream* stream);
244
  size_t GetUsedMemorySize() const;
245

    
246
  static SnapshotObjectId GenerateId(Heap* heap, v8::RetainedObjectInfo* info);
247
  static inline SnapshotObjectId GetNthGcSubrootId(int delta);
248

    
249
  static const int kObjectIdStep = 2;
250
  static const SnapshotObjectId kInternalRootObjectId;
251
  static const SnapshotObjectId kGcRootsObjectId;
252
  static const SnapshotObjectId kNativesRootObjectId;
253
  static const SnapshotObjectId kGcRootsFirstSubrootId;
254
  static const SnapshotObjectId kFirstAvailableObjectId;
255

    
256
  int FindUntrackedObjects();
257

    
258
  void UpdateHeapObjectsMap();
259

    
260
 private:
261
  struct EntryInfo {
262
  EntryInfo(SnapshotObjectId id, Address addr, unsigned int size)
263
      : id(id), addr(addr), size(size), accessed(true) { }
264
  EntryInfo(SnapshotObjectId id, Address addr, unsigned int size, bool accessed)
265
      : id(id), addr(addr), size(size), accessed(accessed) { }
266
    SnapshotObjectId id;
267
    Address addr;
268
    unsigned int size;
269
    bool accessed;
270
  };
271
  struct TimeInterval {
272
    explicit TimeInterval(SnapshotObjectId id) : id(id), size(0), count(0) { }
273
    SnapshotObjectId id;
274
    uint32_t size;
275
    uint32_t count;
276
  };
277

    
278
  void RemoveDeadEntries();
279

    
280
  SnapshotObjectId next_id_;
281
  HashMap entries_map_;
282
  List<EntryInfo> entries_;
283
  List<TimeInterval> time_intervals_;
284
  Heap* heap_;
285

    
286
  DISALLOW_COPY_AND_ASSIGN(HeapObjectsMap);
287
};
288

    
289

    
290
class HeapSnapshotsCollection {
291
 public:
292
  explicit HeapSnapshotsCollection(Heap* heap);
293
  ~HeapSnapshotsCollection();
294

    
295
  Heap* heap() const { return ids_.heap(); }
296

    
297
  bool is_tracking_objects() { return is_tracking_objects_; }
298
  SnapshotObjectId PushHeapObjectsStats(OutputStream* stream) {
299
    return ids_.PushHeapObjectsStats(stream);
300
  }
301
  void StartHeapObjectsTracking();
302
  void StopHeapObjectsTracking();
303

    
304
  HeapSnapshot* NewSnapshot(const char* name, unsigned uid);
305
  void SnapshotGenerationFinished(HeapSnapshot* snapshot);
306
  List<HeapSnapshot*>* snapshots() { return &snapshots_; }
307
  void RemoveSnapshot(HeapSnapshot* snapshot);
308

    
309
  StringsStorage* names() { return &names_; }
310
  AllocationTracker* allocation_tracker() { return allocation_tracker_; }
311

    
312
  SnapshotObjectId FindObjectId(Address object_addr) {
313
    return ids_.FindEntry(object_addr);
314
  }
315
  SnapshotObjectId GetObjectId(Address object_addr, int object_size) {
316
    return ids_.FindOrAddEntry(object_addr, object_size);
317
  }
318
  Handle<HeapObject> FindHeapObjectById(SnapshotObjectId id);
319
  void ObjectMoveEvent(Address from, Address to, int size) {
320
    ids_.MoveObject(from, to, size);
321
  }
322
  void NewObjectEvent(Address addr, int size);
323
  void UpdateObjectSizeEvent(Address addr, int size) {
324
    ids_.UpdateObjectSize(addr, size);
325
  }
326
  SnapshotObjectId last_assigned_id() const {
327
    return ids_.last_assigned_id();
328
  }
329
  size_t GetUsedMemorySize() const;
330

    
331
  int FindUntrackedObjects() { return ids_.FindUntrackedObjects(); }
332

    
333
  void UpdateHeapObjectsMap() { ids_.UpdateHeapObjectsMap(); }
334

    
335
 private:
336
  bool is_tracking_objects_;  // Whether tracking object moves is needed.
337
  List<HeapSnapshot*> snapshots_;
338
  StringsStorage names_;
339
  // Mapping from HeapObject addresses to objects' uids.
340
  HeapObjectsMap ids_;
341
  AllocationTracker* allocation_tracker_;
342

    
343
  DISALLOW_COPY_AND_ASSIGN(HeapSnapshotsCollection);
344
};
345

    
346

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

    
351

    
352
// An interface that creates HeapEntries by HeapThings.
353
class HeapEntriesAllocator {
354
 public:
355
  virtual ~HeapEntriesAllocator() { }
356
  virtual HeapEntry* AllocateEntry(HeapThing ptr) = 0;
357
};
358

    
359

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

    
366
  int Map(HeapThing thing);
367
  void Pair(HeapThing thing, int entry);
368

    
369
 private:
370
  static uint32_t Hash(HeapThing thing) {
371
    return ComputeIntegerHash(
372
        static_cast<uint32_t>(reinterpret_cast<uintptr_t>(thing)),
373
        v8::internal::kZeroHashSeed);
374
  }
375
  static bool HeapThingsMatch(HeapThing key1, HeapThing key2) {
376
    return key1 == key2;
377
  }
378

    
379
  HashMap entries_;
380

    
381
  friend class HeapObjectsSet;
382

    
383
  DISALLOW_COPY_AND_ASSIGN(HeapEntriesMap);
384
};
385

    
386

    
387
class HeapObjectsSet {
388
 public:
389
  HeapObjectsSet();
390
  void Clear();
391
  bool Contains(Object* object);
392
  void Insert(Object* obj);
393
  const char* GetTag(Object* obj);
394
  void SetTag(Object* obj, const char* tag);
395
  bool is_empty() const { return entries_.occupancy() == 0; }
396

    
397
 private:
398
  HashMap entries_;
399

    
400
  DISALLOW_COPY_AND_ASSIGN(HeapObjectsSet);
401
};
402

    
403

    
404
// An interface used to populate a snapshot with nodes and edges.
405
class SnapshotFillerInterface {
406
 public:
407
  virtual ~SnapshotFillerInterface() { }
408
  virtual HeapEntry* AddEntry(HeapThing ptr,
409
                              HeapEntriesAllocator* allocator) = 0;
410
  virtual HeapEntry* FindEntry(HeapThing ptr) = 0;
411
  virtual HeapEntry* FindOrAddEntry(HeapThing ptr,
412
                                    HeapEntriesAllocator* allocator) = 0;
413
  virtual void SetIndexedReference(HeapGraphEdge::Type type,
414
                                   int parent_entry,
415
                                   int index,
416
                                   HeapEntry* child_entry) = 0;
417
  virtual void SetIndexedAutoIndexReference(HeapGraphEdge::Type type,
418
                                            int parent_entry,
419
                                            HeapEntry* child_entry) = 0;
420
  virtual void SetNamedReference(HeapGraphEdge::Type type,
421
                                 int parent_entry,
422
                                 const char* reference_name,
423
                                 HeapEntry* child_entry) = 0;
424
  virtual void SetNamedAutoIndexReference(HeapGraphEdge::Type type,
425
                                          int parent_entry,
426
                                          HeapEntry* child_entry) = 0;
427
};
428

    
429

    
430
class SnapshottingProgressReportingInterface {
431
 public:
432
  virtual ~SnapshottingProgressReportingInterface() { }
433
  virtual void ProgressStep() = 0;
434
  virtual bool ProgressReport(bool force) = 0;
435
};
436

    
437

    
438
// An implementation of V8 heap graph extractor.
439
class V8HeapExplorer : public HeapEntriesAllocator {
440
 public:
441
  V8HeapExplorer(HeapSnapshot* snapshot,
442
                 SnapshottingProgressReportingInterface* progress,
443
                 v8::HeapProfiler::ObjectNameResolver* resolver);
444
  virtual ~V8HeapExplorer();
445
  virtual HeapEntry* AllocateEntry(HeapThing ptr);
446
  void AddRootEntries(SnapshotFillerInterface* filler);
447
  int EstimateObjectsCount(HeapIterator* iterator);
448
  bool IterateAndExtractReferences(SnapshotFillerInterface* filler);
449
  void TagGlobalObjects();
450

    
451
  static String* GetConstructorName(JSObject* object);
452

    
453
  static HeapObject* const kInternalRootObject;
454

    
455
 private:
456
  HeapEntry* AddEntry(HeapObject* object);
457
  HeapEntry* AddEntry(HeapObject* object,
458
                      HeapEntry::Type type,
459
                      const char* name);
460
  const char* GetSystemEntryName(HeapObject* object);
461

    
462
  void ExtractReferences(HeapObject* obj);
463
  void ExtractJSGlobalProxyReferences(int entry, JSGlobalProxy* proxy);
464
  void ExtractJSObjectReferences(int entry, JSObject* js_obj);
465
  void ExtractStringReferences(int entry, String* obj);
466
  void ExtractContextReferences(int entry, Context* context);
467
  void ExtractMapReferences(int entry, Map* map);
468
  void ExtractSharedFunctionInfoReferences(int entry,
469
                                           SharedFunctionInfo* shared);
470
  void ExtractScriptReferences(int entry, Script* script);
471
  void ExtractAccessorPairReferences(int entry, AccessorPair* accessors);
472
  void ExtractCodeCacheReferences(int entry, CodeCache* code_cache);
473
  void ExtractCodeReferences(int entry, Code* code);
474
  void ExtractCellReferences(int entry, Cell* cell);
475
  void ExtractPropertyCellReferences(int entry, PropertyCell* cell);
476
  void ExtractAllocationSiteReferences(int entry, AllocationSite* site);
477
  void ExtractClosureReferences(JSObject* js_obj, int entry);
478
  void ExtractPropertyReferences(JSObject* js_obj, int entry);
479
  bool ExtractAccessorPairProperty(JSObject* js_obj, int entry,
480
                                   Object* key, Object* callback_obj);
481
  void ExtractElementReferences(JSObject* js_obj, int entry);
482
  void ExtractInternalReferences(JSObject* js_obj, int entry);
483
  bool IsEssentialObject(Object* object);
484
  void SetContextReference(HeapObject* parent_obj,
485
                           int parent,
486
                           String* reference_name,
487
                           Object* child,
488
                           int field_offset);
489
  void SetNativeBindReference(HeapObject* parent_obj,
490
                              int parent,
491
                              const char* reference_name,
492
                              Object* child);
493
  void SetElementReference(HeapObject* parent_obj,
494
                           int parent,
495
                           int index,
496
                           Object* child);
497
  void SetInternalReference(HeapObject* parent_obj,
498
                            int parent,
499
                            const char* reference_name,
500
                            Object* child,
501
                            int field_offset = -1);
502
  void SetInternalReference(HeapObject* parent_obj,
503
                            int parent,
504
                            int index,
505
                            Object* child,
506
                            int field_offset = -1);
507
  void SetHiddenReference(HeapObject* parent_obj,
508
                          int parent,
509
                          int index,
510
                          Object* child);
511
  void SetWeakReference(HeapObject* parent_obj,
512
                        int parent,
513
                        int index,
514
                        Object* child_obj,
515
                        int field_offset);
516
  void SetPropertyReference(HeapObject* parent_obj,
517
                            int parent,
518
                            Name* reference_name,
519
                            Object* child,
520
                            const char* name_format_string = NULL,
521
                            int field_offset = -1);
522
  void SetUserGlobalReference(Object* user_global);
523
  void SetRootGcRootsReference();
524
  void SetGcRootsReference(VisitorSynchronization::SyncTag tag);
525
  void SetGcSubrootReference(
526
      VisitorSynchronization::SyncTag tag, bool is_weak, Object* child);
527
  const char* GetStrongGcSubrootName(Object* object);
528
  void TagObject(Object* obj, const char* tag);
529

    
530
  HeapEntry* GetEntry(Object* obj);
531

    
532
  static inline HeapObject* GetNthGcSubrootObject(int delta);
533
  static inline int GetGcSubrootOrder(HeapObject* subroot);
534

    
535
  Heap* heap_;
536
  HeapSnapshot* snapshot_;
537
  HeapSnapshotsCollection* collection_;
538
  SnapshottingProgressReportingInterface* progress_;
539
  SnapshotFillerInterface* filler_;
540
  HeapObjectsSet objects_tags_;
541
  HeapObjectsSet strong_gc_subroot_names_;
542
  HeapObjectsSet user_roots_;
543
  v8::HeapProfiler::ObjectNameResolver* global_object_name_resolver_;
544

    
545
  static HeapObject* const kGcRootsObject;
546
  static HeapObject* const kFirstGcSubrootObject;
547
  static HeapObject* const kLastGcSubrootObject;
548

    
549
  friend class IndexedReferencesExtractor;
550
  friend class GcSubrootsEnumerator;
551
  friend class RootsReferencesExtractor;
552

    
553
  DISALLOW_COPY_AND_ASSIGN(V8HeapExplorer);
554
};
555

    
556

    
557
class NativeGroupRetainedObjectInfo;
558

    
559

    
560
// An implementation of retained native objects extractor.
561
class NativeObjectsExplorer {
562
 public:
563
  NativeObjectsExplorer(HeapSnapshot* snapshot,
564
                        SnapshottingProgressReportingInterface* progress);
565
  virtual ~NativeObjectsExplorer();
566
  void AddRootEntries(SnapshotFillerInterface* filler);
567
  int EstimateObjectsCount();
568
  bool IterateAndExtractReferences(SnapshotFillerInterface* filler);
569

    
570
 private:
571
  void FillRetainedObjects();
572
  void FillImplicitReferences();
573
  List<HeapObject*>* GetListMaybeDisposeInfo(v8::RetainedObjectInfo* info);
574
  void SetNativeRootReference(v8::RetainedObjectInfo* info);
575
  void SetRootNativeRootsReference();
576
  void SetWrapperNativeReferences(HeapObject* wrapper,
577
                                      v8::RetainedObjectInfo* info);
578
  void VisitSubtreeWrapper(Object** p, uint16_t class_id);
579

    
580
  static uint32_t InfoHash(v8::RetainedObjectInfo* info) {
581
    return ComputeIntegerHash(static_cast<uint32_t>(info->GetHash()),
582
                              v8::internal::kZeroHashSeed);
583
  }
584
  static bool RetainedInfosMatch(void* key1, void* key2) {
585
    return key1 == key2 ||
586
        (reinterpret_cast<v8::RetainedObjectInfo*>(key1))->IsEquivalent(
587
            reinterpret_cast<v8::RetainedObjectInfo*>(key2));
588
  }
589
  INLINE(static bool StringsMatch(void* key1, void* key2)) {
590
    return strcmp(reinterpret_cast<char*>(key1),
591
                  reinterpret_cast<char*>(key2)) == 0;
592
  }
593

    
594
  NativeGroupRetainedObjectInfo* FindOrAddGroupInfo(const char* label);
595

    
596
  Isolate* isolate_;
597
  HeapSnapshot* snapshot_;
598
  HeapSnapshotsCollection* collection_;
599
  SnapshottingProgressReportingInterface* progress_;
600
  bool embedder_queried_;
601
  HeapObjectsSet in_groups_;
602
  // RetainedObjectInfo* -> List<HeapObject*>*
603
  HashMap objects_by_info_;
604
  HashMap native_groups_;
605
  HeapEntriesAllocator* synthetic_entries_allocator_;
606
  HeapEntriesAllocator* native_entries_allocator_;
607
  // Used during references extraction.
608
  SnapshotFillerInterface* filler_;
609

    
610
  static HeapThing const kNativesRootObject;
611

    
612
  friend class GlobalHandlesExtractor;
613

    
614
  DISALLOW_COPY_AND_ASSIGN(NativeObjectsExplorer);
615
};
616

    
617

    
618
class HeapSnapshotGenerator : public SnapshottingProgressReportingInterface {
619
 public:
620
  HeapSnapshotGenerator(HeapSnapshot* snapshot,
621
                        v8::ActivityControl* control,
622
                        v8::HeapProfiler::ObjectNameResolver* resolver,
623
                        Heap* heap);
624
  bool GenerateSnapshot();
625

    
626
 private:
627
  bool FillReferences();
628
  void ProgressStep();
629
  bool ProgressReport(bool force = false);
630
  void SetProgressTotal(int iterations_count);
631

    
632
  HeapSnapshot* snapshot_;
633
  v8::ActivityControl* control_;
634
  V8HeapExplorer v8_heap_explorer_;
635
  NativeObjectsExplorer dom_explorer_;
636
  // Mapping from HeapThing pointers to HeapEntry* pointers.
637
  HeapEntriesMap entries_;
638
  // Used during snapshot generation.
639
  int progress_counter_;
640
  int progress_total_;
641
  Heap* heap_;
642

    
643
  DISALLOW_COPY_AND_ASSIGN(HeapSnapshotGenerator);
644
};
645

    
646
class OutputStreamWriter;
647

    
648
class HeapSnapshotJSONSerializer {
649
 public:
650
  explicit HeapSnapshotJSONSerializer(HeapSnapshot* snapshot)
651
      : snapshot_(snapshot),
652
        strings_(StringsMatch),
653
        next_node_id_(1),
654
        next_string_id_(1),
655
        writer_(NULL) {
656
  }
657
  void Serialize(v8::OutputStream* stream);
658

    
659
 private:
660
  INLINE(static bool StringsMatch(void* key1, void* key2)) {
661
    return strcmp(reinterpret_cast<char*>(key1),
662
                  reinterpret_cast<char*>(key2)) == 0;
663
  }
664

    
665
  INLINE(static uint32_t StringHash(const void* string)) {
666
    const char* s = reinterpret_cast<const char*>(string);
667
    int len = static_cast<int>(strlen(s));
668
    return StringHasher::HashSequentialString(
669
        s, len, v8::internal::kZeroHashSeed);
670
  }
671

    
672
  int GetStringId(const char* s);
673
  int entry_index(HeapEntry* e) { return e->index() * kNodeFieldsCount; }
674
  void SerializeEdge(HeapGraphEdge* edge, bool first_edge);
675
  void SerializeEdges();
676
  void SerializeImpl();
677
  void SerializeNode(HeapEntry* entry);
678
  void SerializeNodes();
679
  void SerializeSnapshot();
680
  void SerializeTraceTree();
681
  void SerializeTraceNode(AllocationTraceNode* node);
682
  void SerializeTraceNodeInfos();
683
  void SerializeString(const unsigned char* s);
684
  void SerializeStrings();
685

    
686
  static const int kEdgeFieldsCount;
687
  static const int kNodeFieldsCount;
688

    
689
  HeapSnapshot* snapshot_;
690
  HashMap strings_;
691
  int next_node_id_;
692
  int next_string_id_;
693
  OutputStreamWriter* writer_;
694

    
695
  friend class HeapSnapshotJSONSerializerEnumerator;
696
  friend class HeapSnapshotJSONSerializerIterator;
697

    
698
  DISALLOW_COPY_AND_ASSIGN(HeapSnapshotJSONSerializer);
699
};
700

    
701

    
702
} }  // namespace v8::internal
703

    
704
#endif  // V8_HEAP_SNAPSHOT_GENERATOR_H_
705