heap-snapshot-generator.h 20.3 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 7

#ifndef V8_HEAP_SNAPSHOT_GENERATOR_H_
#define V8_HEAP_SNAPSHOT_GENERATOR_H_

8
#include "src/strings-storage.h"
9

10 11 12
namespace v8 {
namespace internal {

13 14
class AllocationTracker;
class AllocationTraceNode;
15 16
class HeapEntry;
class HeapSnapshot;
17
class SnapshotFiller;
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34

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);

35
  Type type() const { return TypeField::decode(bit_field_); }
36
  int index() const {
37
    DCHECK(type() == kElement || type() == kHidden);
38 39 40
    return index_;
  }
  const char* name() const {
41 42
    DCHECK(type() == kContextVariable || type() == kProperty ||
           type() == kInternal || type() == kShortcut || type() == kWeak);
43 44 45 46 47 48 49
    return name_;
  }
  INLINE(HeapEntry* from() const);
  HeapEntry* to() const { return to_entry_; }

 private:
  INLINE(HeapSnapshot* snapshot() const);
50
  int from_index() const { return FromIndexField::decode(bit_field_); }
51

52 53 54
  class TypeField : public BitField<Type, 0, 3> {};
  class FromIndexField : public BitField<int, 3, 29> {};
  uint32_t bit_field_;
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
  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,
82 83
    kSynthetic = v8::HeapGraphNode::kSynthetic,
    kConsString = v8::HeapGraphNode::kConsString,
84 85
    kSlicedString = v8::HeapGraphNode::kSlicedString,
    kSymbol = v8::HeapGraphNode::kSymbol
86 87 88 89 90 91 92 93
  };
  static const int kNoEntry;

  HeapEntry() { }
  HeapEntry(HeapSnapshot* snapshot,
            Type type,
            const char* name,
            SnapshotObjectId id,
94 95
            size_t self_size,
            unsigned trace_node_id);
96 97 98 99 100

  HeapSnapshot* snapshot() { return snapshot_; }
  Type type() { return static_cast<Type>(type_); }
  const char* name() { return name_; }
  void set_name(const char* name) { name_ = name; }
101
  SnapshotObjectId id() { return id_; }
102
  size_t self_size() { return self_size_; }
103
  unsigned trace_node_id() const { return trace_node_id_; }
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
  INLINE(int index() const);
  int children_count() const { return children_count_; }
  INLINE(int set_children_index(int index));
  void add_child(HeapGraphEdge* edge) {
    children_arr()[children_count_++] = edge;
  }
  Vector<HeapGraphEdge*> children() {
    return Vector<HeapGraphEdge*>(children_arr(), children_count_); }

  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:
  INLINE(HeapGraphEdge** children_arr());
  const char* TypeAsString();

  unsigned type_: 4;
  int children_count_: 28;
  int children_index_;
128
  size_t self_size_;
129 130
  HeapSnapshot* snapshot_;
  const char* name_;
131 132 133
  SnapshotObjectId id_;
  // id of allocation stack trace top node
  unsigned trace_node_id_;
134 135 136 137
};


// HeapSnapshot represents a single heap snapshot. It is stored in
138
// HeapProfiler, which is also a factory for
139 140 141 142 143
// 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:
144
  explicit HeapSnapshot(HeapProfiler* profiler);
145 146
  void Delete();

147
  HeapProfiler* profiler() { return profiler_; }
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
  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_; }
  List<HeapGraphEdge>& edges() { return edges_; }
  List<HeapGraphEdge*>& children() { return children_; }
  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,
165 166
                      size_t size,
                      unsigned trace_node_id);
167
  void AddSyntheticRootEntries();
168 169 170 171 172 173 174
  HeapEntry* GetEntryById(SnapshotObjectId id);
  List<HeapEntry*>* GetSortedEntriesList();
  void FillChildren();

  void Print(int max_depth);

 private:
175 176 177 178
  HeapEntry* AddRootEntry();
  HeapEntry* AddGcRootsEntry();
  HeapEntry* AddGcSubrootEntry(int tag, SnapshotObjectId id);

179
  HeapProfiler* profiler_;
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
  int root_index_;
  int gc_roots_index_;
  int gc_subroot_indexes_[VisitorSynchronization::kNumberOfSyncTags];
  List<HeapEntry> entries_;
  List<HeapGraphEdge> edges_;
  List<HeapGraphEdge*> children_;
  List<HeapEntry*> sorted_entries_;
  SnapshotObjectId max_snapshot_js_object_id_;

  friend class HeapSnapshotTester;

  DISALLOW_COPY_AND_ASSIGN(HeapSnapshot);
};


class HeapObjectsMap {
 public:
197 198 199 200 201 202 203 204 205 206
  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;
  };

207 208 209 210 211
  explicit HeapObjectsMap(Heap* heap);

  Heap* heap() const { return heap_; }

  SnapshotObjectId FindEntry(Address addr);
212 213 214
  SnapshotObjectId FindOrAddEntry(Address addr,
                                  unsigned int size,
                                  bool accessed = true);
215
  bool MoveObject(Address from, Address to, int size);
216
  void UpdateObjectSize(Address addr, int size);
217 218 219 220 221
  SnapshotObjectId last_assigned_id() const {
    return next_id_ - kObjectIdStep;
  }

  void StopHeapObjectsTracking();
222 223
  SnapshotObjectId PushHeapObjectsStats(OutputStream* stream,
                                        int64_t* timestamp_us);
224
  const List<TimeInterval>& samples() const { return time_intervals_; }
225 226
  size_t GetUsedMemorySize() const;

227
  SnapshotObjectId GenerateId(v8::RetainedObjectInfo* info);
228 229 230 231 232 233 234

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

235 236 237
  int FindUntrackedObjects();

  void UpdateHeapObjectsMap();
238
  void RemoveDeadEntries();
239

240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 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 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332
 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_;
  HashMap entries_map_;
  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);
  }

  HashMap entries_;

  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:
  HashMap entries_;

  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);
333
  bool IterateAndExtractReferences(SnapshotFiller* filler);
334
  void TagGlobalObjects();
335
  void TagCodeObject(Code* code);
336
  void TagBuiltinCodeObject(Code* code, const char* name);
337 338 339
  HeapEntry* AddEntry(Address address,
                      HeapEntry::Type type,
                      const char* name,
340
                      size_t size);
341 342 343 344

  static String* GetConstructorName(JSObject* object);

 private:
345 346 347
  typedef bool (V8HeapExplorer::*ExtractReferencesMethod)(int entry,
                                                          HeapObject* object);

348 349 350 351
  HeapEntry* AddEntry(HeapObject* object);
  HeapEntry* AddEntry(HeapObject* object,
                      HeapEntry::Type type,
                      const char* name);
352

353 354
  const char* GetSystemEntryName(HeapObject* object);

355 356 357 358 359
  template<V8HeapExplorer::ExtractReferencesMethod extractor>
  bool IterateAndExtractSinglePass();

  bool ExtractReferencesPass1(int entry, HeapObject* obj);
  bool ExtractReferencesPass2(int entry, HeapObject* obj);
360
  void ExtractJSGlobalProxyReferences(int entry, JSGlobalProxy* proxy);
361 362
  void ExtractJSObjectReferences(int entry, JSObject* js_obj);
  void ExtractStringReferences(int entry, String* obj);
363
  void ExtractSymbolReferences(int entry, Symbol* symbol);
364
  void ExtractJSCollectionReferences(int entry, JSCollection* collection);
365 366
  void ExtractJSWeakCollectionReferences(int entry,
                                         JSWeakCollection* collection);
367 368 369 370 371
  void ExtractContextReferences(int entry, Context* context);
  void ExtractMapReferences(int entry, Map* map);
  void ExtractSharedFunctionInfoReferences(int entry,
                                           SharedFunctionInfo* shared);
  void ExtractScriptReferences(int entry, Script* script);
372
  void ExtractAccessorInfoReferences(int entry, AccessorInfo* accessor_info);
373
  void ExtractAccessorPairReferences(int entry, AccessorPair* accessors);
374 375
  void ExtractCodeCacheReferences(int entry, CodeCache* code_cache);
  void ExtractCodeReferences(int entry, Code* code);
376
  void ExtractBoxReferences(int entry, Box* box);
377
  void ExtractCellReferences(int entry, Cell* cell);
378
  void ExtractPropertyCellReferences(int entry, PropertyCell* cell);
379
  void ExtractAllocationSiteReferences(int entry, AllocationSite* site);
380
  void ExtractJSArrayBufferReferences(int entry, JSArrayBuffer* buffer);
381
  void ExtractFixedArrayReferences(int entry, FixedArray* array);
382 383
  void ExtractClosureReferences(JSObject* js_obj, int entry);
  void ExtractPropertyReferences(JSObject* js_obj, int entry);
384 385
  void ExtractAccessorPairProperty(JSObject* js_obj, int entry, Name* key,
                                   Object* callback_obj, int field_offset = -1);
386 387
  void ExtractElementReferences(JSObject* js_obj, int entry);
  void ExtractInternalReferences(JSObject* js_obj, int entry);
388

389
  bool IsEssentialObject(Object* object);
390
  void SetContextReference(HeapObject* parent_obj,
391 392
                           int parent,
                           String* reference_name,
393 394
                           Object* child,
                           int field_offset);
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418
  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);
  void SetHiddenReference(HeapObject* parent_obj,
                          int parent,
                          int index,
                          Object* child);
  void SetWeakReference(HeapObject* parent_obj,
                        int parent,
419
                        const char* reference_name,
420 421
                        Object* child_obj,
                        int field_offset);
422 423 424 425 426
  void SetWeakReference(HeapObject* parent_obj,
                        int parent,
                        int index,
                        Object* child_obj,
                        int field_offset);
427 428
  void SetPropertyReference(HeapObject* parent_obj,
                            int parent,
429
                            Name* reference_name,
430 431 432
                            Object* child,
                            const char* name_format_string = NULL,
                            int field_offset = -1);
433 434 435 436 437 438
  void SetDataOrAccessorPropertyReference(PropertyKind kind,
                                          JSObject* parent_obj, int parent,
                                          Name* reference_name, Object* child,
                                          const char* name_format_string = NULL,
                                          int field_offset = -1);

439 440 441 442 443 444 445
  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);
446
  void MarkAsWeakContainer(Object* object);
447 448 449 450 451

  HeapEntry* GetEntry(Object* obj);

  Heap* heap_;
  HeapSnapshot* snapshot_;
452 453
  StringsStorage* names_;
  HeapObjectsMap* heap_object_map_;
454
  SnapshottingProgressReportingInterface* progress_;
455
  SnapshotFiller* filler_;
456 457
  HeapObjectsSet objects_tags_;
  HeapObjectsSet strong_gc_subroot_names_;
458
  HeapObjectsSet user_roots_;
459
  HeapObjectsSet weak_containers_;
460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475
  v8::HeapProfiler::ObjectNameResolver* global_object_name_resolver_;

  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,
476
                        SnapshottingProgressReportingInterface* progress);
477 478
  virtual ~NativeObjectsExplorer();
  int EstimateObjectsCount();
479
  bool IterateAndExtractReferences(SnapshotFiller* filler);
480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506

 private:
  void FillRetainedObjects();
  void FillImplicitReferences();
  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);

507
  Isolate* isolate_;
508
  HeapSnapshot* snapshot_;
509
  StringsStorage* names_;
510 511 512 513 514 515 516 517
  bool embedder_queried_;
  HeapObjectsSet in_groups_;
  // RetainedObjectInfo* -> List<HeapObject*>*
  HashMap objects_by_info_;
  HashMap native_groups_;
  HeapEntriesAllocator* synthetic_entries_allocator_;
  HeapEntriesAllocator* native_entries_allocator_;
  // Used during references extraction.
518
  SnapshotFiller* filler_;
519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 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

  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),
562
        strings_(StringsMatch),
563 564 565 566 567 568 569
        next_node_id_(1),
        next_string_id_(1),
        writer_(NULL) {
  }
  void Serialize(v8::OutputStream* stream);

 private:
570 571 572
  INLINE(static bool StringsMatch(void* key1, void* key2)) {
    return strcmp(reinterpret_cast<char*>(key1),
                  reinterpret_cast<char*>(key2)) == 0;
573 574
  }

575 576 577 578 579
  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);
580 581 582 583 584 585 586 587 588 589
  }

  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();
590 591 592
  void SerializeTraceTree();
  void SerializeTraceNode(AllocationTraceNode* node);
  void SerializeTraceNodeInfos();
593
  void SerializeSamples();
594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 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_;
  HashMap strings_;
  int next_node_id_;
  int next_string_id_;
  OutputStreamWriter* writer_;

  friend class HeapSnapshotJSONSerializerEnumerator;
  friend class HeapSnapshotJSONSerializerIterator;

  DISALLOW_COPY_AND_ASSIGN(HeapSnapshotJSONSerializer);
};


} }  // namespace v8::internal

#endif  // V8_HEAP_SNAPSHOT_GENERATOR_H_