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