Home | History | Annotate | Download | only in snapshot
      1 // Copyright 2012 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_SNAPSHOT_SERIALIZE_H_
      6 #define V8_SNAPSHOT_SERIALIZE_H_
      7 
      8 #include "src/address-map.h"
      9 #include "src/heap/heap.h"
     10 #include "src/objects.h"
     11 #include "src/snapshot/snapshot-source-sink.h"
     12 
     13 namespace v8 {
     14 namespace internal {
     15 
     16 class Isolate;
     17 class ScriptData;
     18 
     19 static const int kDeoptTableSerializeEntryCount = 64;
     20 
     21 // ExternalReferenceTable is a helper class that defines the relationship
     22 // between external references and their encodings. It is used to build
     23 // hashmaps in ExternalReferenceEncoder and ExternalReferenceDecoder.
     24 class ExternalReferenceTable {
     25  public:
     26   static ExternalReferenceTable* instance(Isolate* isolate);
     27 
     28   int size() const { return refs_.length(); }
     29   Address address(int i) { return refs_[i].address; }
     30   const char* name(int i) { return refs_[i].name; }
     31 
     32   inline static Address NotAvailable() { return NULL; }
     33 
     34  private:
     35   struct ExternalReferenceEntry {
     36     Address address;
     37     const char* name;
     38   };
     39 
     40   explicit ExternalReferenceTable(Isolate* isolate);
     41 
     42   void Add(Address address, const char* name) {
     43     ExternalReferenceEntry entry = {address, name};
     44     refs_.Add(entry);
     45   }
     46 
     47   List<ExternalReferenceEntry> refs_;
     48 
     49   DISALLOW_COPY_AND_ASSIGN(ExternalReferenceTable);
     50 };
     51 
     52 
     53 class ExternalReferenceEncoder {
     54  public:
     55   explicit ExternalReferenceEncoder(Isolate* isolate);
     56 
     57   uint32_t Encode(Address key) const;
     58 
     59   const char* NameOfAddress(Isolate* isolate, Address address) const;
     60 
     61  private:
     62   static uint32_t Hash(Address key) {
     63     return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key) >>
     64                                  kPointerSizeLog2);
     65   }
     66 
     67   HashMap* map_;
     68 
     69   DISALLOW_COPY_AND_ASSIGN(ExternalReferenceEncoder);
     70 };
     71 
     72 
     73 class PartialCacheIndexMap : public AddressMapBase {
     74  public:
     75   PartialCacheIndexMap() : map_(HashMap::PointersMatch) {}
     76 
     77   static const int kInvalidIndex = -1;
     78 
     79   // Lookup object in the map. Return its index if found, or create
     80   // a new entry with new_index as value, and return kInvalidIndex.
     81   int LookupOrInsert(HeapObject* obj, int new_index) {
     82     HashMap::Entry* entry = LookupEntry(&map_, obj, false);
     83     if (entry != NULL) return GetValue(entry);
     84     SetValue(LookupEntry(&map_, obj, true), static_cast<uint32_t>(new_index));
     85     return kInvalidIndex;
     86   }
     87 
     88  private:
     89   HashMap map_;
     90 
     91   DISALLOW_COPY_AND_ASSIGN(PartialCacheIndexMap);
     92 };
     93 
     94 
     95 class HotObjectsList {
     96  public:
     97   HotObjectsList() : index_(0) {
     98     for (int i = 0; i < kSize; i++) circular_queue_[i] = NULL;
     99   }
    100 
    101   void Add(HeapObject* object) {
    102     circular_queue_[index_] = object;
    103     index_ = (index_ + 1) & kSizeMask;
    104   }
    105 
    106   HeapObject* Get(int index) {
    107     DCHECK_NOT_NULL(circular_queue_[index]);
    108     return circular_queue_[index];
    109   }
    110 
    111   static const int kNotFound = -1;
    112 
    113   int Find(HeapObject* object) {
    114     for (int i = 0; i < kSize; i++) {
    115       if (circular_queue_[i] == object) return i;
    116     }
    117     return kNotFound;
    118   }
    119 
    120   static const int kSize = 8;
    121 
    122  private:
    123   STATIC_ASSERT(IS_POWER_OF_TWO(kSize));
    124   static const int kSizeMask = kSize - 1;
    125   HeapObject* circular_queue_[kSize];
    126   int index_;
    127 
    128   DISALLOW_COPY_AND_ASSIGN(HotObjectsList);
    129 };
    130 
    131 
    132 // The Serializer/Deserializer class is a common superclass for Serializer and
    133 // Deserializer which is used to store common constants and methods used by
    134 // both.
    135 class SerializerDeserializer: public ObjectVisitor {
    136  public:
    137   static void Iterate(Isolate* isolate, ObjectVisitor* visitor);
    138 
    139   // No reservation for large object space necessary.
    140   static const int kNumberOfPreallocatedSpaces = LAST_PAGED_SPACE + 1;
    141   static const int kNumberOfSpaces = LAST_SPACE + 1;
    142 
    143  protected:
    144   static bool CanBeDeferred(HeapObject* o);
    145 
    146   // ---------- byte code range 0x00..0x7f ----------
    147   // Byte codes in this range represent Where, HowToCode and WhereToPoint.
    148   // Where the pointed-to object can be found:
    149   // The static assert below will trigger when the number of preallocated spaces
    150   // changed. If that happens, update the bytecode ranges in the comments below.
    151   STATIC_ASSERT(5 == kNumberOfSpaces);
    152   enum Where {
    153     // 0x00..0x04  Allocate new object, in specified space.
    154     kNewObject = 0,
    155     // 0x05        Unused (including 0x25, 0x45, 0x65).
    156     // 0x06        Unused (including 0x26, 0x46, 0x66).
    157     // 0x07        Unused (including 0x27, 0x47, 0x67).
    158     // 0x08..0x0c  Reference to previous object from space.
    159     kBackref = 0x08,
    160     // 0x0d        Unused (including 0x2d, 0x4d, 0x6d).
    161     // 0x0e        Unused (including 0x2e, 0x4e, 0x6e).
    162     // 0x0f        Unused (including 0x2f, 0x4f, 0x6f).
    163     // 0x10..0x14  Reference to previous object from space after skip.
    164     kBackrefWithSkip = 0x10,
    165     // 0x15        Unused (including 0x35, 0x55, 0x75).
    166     // 0x16        Unused (including 0x36, 0x56, 0x76).
    167     // 0x17        Misc (including 0x37, 0x57, 0x77).
    168     // 0x18        Root array item.
    169     kRootArray = 0x18,
    170     // 0x19        Object in the partial snapshot cache.
    171     kPartialSnapshotCache = 0x19,
    172     // 0x1a        External reference referenced by id.
    173     kExternalReference = 0x1a,
    174     // 0x1b        Object provided in the attached list.
    175     kAttachedReference = 0x1b,
    176     // 0x1c        Builtin code referenced by index.
    177     kBuiltin = 0x1c
    178     // 0x1d..0x1f  Misc (including 0x3d..0x3f, 0x5d..0x5f, 0x7d..0x7f)
    179   };
    180 
    181   static const int kWhereMask = 0x1f;
    182   static const int kSpaceMask = 7;
    183   STATIC_ASSERT(kNumberOfSpaces <= kSpaceMask + 1);
    184 
    185   // How to code the pointer to the object.
    186   enum HowToCode {
    187     // Straight pointer.
    188     kPlain = 0,
    189     // A pointer inlined in code. What this means depends on the architecture.
    190     kFromCode = 0x20
    191   };
    192 
    193   static const int kHowToCodeMask = 0x20;
    194 
    195   // Where to point within the object.
    196   enum WhereToPoint {
    197     // Points to start of object
    198     kStartOfObject = 0,
    199     // Points to instruction in code object or payload of cell.
    200     kInnerPointer = 0x40
    201   };
    202 
    203   static const int kWhereToPointMask = 0x40;
    204 
    205   // ---------- Misc ----------
    206   // Skip.
    207   static const int kSkip = 0x1d;
    208   // Internal reference encoded as offsets of pc and target from code entry.
    209   static const int kInternalReference = 0x1e;
    210   static const int kInternalReferenceEncoded = 0x1f;
    211   // Do nothing, used for padding.
    212   static const int kNop = 0x3d;
    213   // Move to next reserved chunk.
    214   static const int kNextChunk = 0x3e;
    215   // Deferring object content.
    216   static const int kDeferred = 0x3f;
    217   // Used for the source code of the natives, which is in the executable, but
    218   // is referred to from external strings in the snapshot.
    219   static const int kNativesStringResource = 0x5d;
    220   // Used for the source code for compiled stubs, which is in the executable,
    221   // but is referred to from external strings in the snapshot.
    222   static const int kExtraNativesStringResource = 0x5e;
    223   // A tag emitted at strategic points in the snapshot to delineate sections.
    224   // If the deserializer does not find these at the expected moments then it
    225   // is an indication that the snapshot and the VM do not fit together.
    226   // Examine the build process for architecture, version or configuration
    227   // mismatches.
    228   static const int kSynchronize = 0x17;
    229   // Repeats of variable length.
    230   static const int kVariableRepeat = 0x37;
    231   // Raw data of variable length.
    232   static const int kVariableRawData = 0x57;
    233   // Alignment prefixes 0x7d..0x7f
    234   static const int kAlignmentPrefix = 0x7d;
    235 
    236   // 0x77 unused
    237 
    238   // ---------- byte code range 0x80..0xff ----------
    239   // First 32 root array items.
    240   static const int kNumberOfRootArrayConstants = 0x20;
    241   // 0x80..0x9f
    242   static const int kRootArrayConstants = 0x80;
    243   // 0xa0..0xbf
    244   static const int kRootArrayConstantsWithSkip = 0xa0;
    245   static const int kRootArrayConstantsMask = 0x1f;
    246 
    247   // 8 hot (recently seen or back-referenced) objects with optional skip.
    248   static const int kNumberOfHotObjects = 0x08;
    249   // 0xc0..0xc7
    250   static const int kHotObject = 0xc0;
    251   // 0xc8..0xcf
    252   static const int kHotObjectWithSkip = 0xc8;
    253   static const int kHotObjectMask = 0x07;
    254 
    255   // 32 common raw data lengths.
    256   static const int kNumberOfFixedRawData = 0x20;
    257   // 0xd0..0xef
    258   static const int kFixedRawData = 0xd0;
    259   static const int kOnePointerRawData = kFixedRawData;
    260   static const int kFixedRawDataStart = kFixedRawData - 1;
    261 
    262   // 16 repeats lengths.
    263   static const int kNumberOfFixedRepeat = 0x10;
    264   // 0xf0..0xff
    265   static const int kFixedRepeat = 0xf0;
    266   static const int kFixedRepeatStart = kFixedRepeat - 1;
    267 
    268   // ---------- special values ----------
    269   static const int kAnyOldSpace = -1;
    270 
    271   // Sentinel after a new object to indicate that double alignment is needed.
    272   static const int kDoubleAlignmentSentinel = 0;
    273 
    274   // Used as index for the attached reference representing the source object.
    275   static const int kSourceObjectReference = 0;
    276 
    277   // Used as index for the attached reference representing the global proxy.
    278   static const int kGlobalProxyReference = 0;
    279 
    280   // ---------- member variable ----------
    281   HotObjectsList hot_objects_;
    282 };
    283 
    284 
    285 class SerializedData {
    286  public:
    287   class Reservation {
    288    public:
    289     explicit Reservation(uint32_t size)
    290         : reservation_(ChunkSizeBits::encode(size)) {}
    291 
    292     uint32_t chunk_size() const { return ChunkSizeBits::decode(reservation_); }
    293     bool is_last() const { return IsLastChunkBits::decode(reservation_); }
    294 
    295     void mark_as_last() { reservation_ |= IsLastChunkBits::encode(true); }
    296 
    297    private:
    298     uint32_t reservation_;
    299   };
    300 
    301   SerializedData(byte* data, int size)
    302       : data_(data), size_(size), owns_data_(false) {}
    303   SerializedData() : data_(NULL), size_(0), owns_data_(false) {}
    304 
    305   ~SerializedData() {
    306     if (owns_data_) DeleteArray<byte>(data_);
    307   }
    308 
    309   uint32_t GetMagicNumber() const { return GetHeaderValue(kMagicNumberOffset); }
    310 
    311   class ChunkSizeBits : public BitField<uint32_t, 0, 31> {};
    312   class IsLastChunkBits : public BitField<bool, 31, 1> {};
    313 
    314   static uint32_t ComputeMagicNumber(ExternalReferenceTable* table) {
    315     uint32_t external_refs = table->size();
    316     return 0xC0DE0000 ^ external_refs;
    317   }
    318 
    319  protected:
    320   void SetHeaderValue(int offset, uint32_t value) {
    321     uint32_t* address = reinterpret_cast<uint32_t*>(data_ + offset);
    322     memcpy(reinterpret_cast<uint32_t*>(address), &value, sizeof(value));
    323   }
    324 
    325   uint32_t GetHeaderValue(int offset) const {
    326     uint32_t value;
    327     memcpy(&value, reinterpret_cast<int*>(data_ + offset), sizeof(value));
    328     return value;
    329   }
    330 
    331   void AllocateData(int size);
    332 
    333   static uint32_t ComputeMagicNumber(Isolate* isolate) {
    334     return ComputeMagicNumber(ExternalReferenceTable::instance(isolate));
    335   }
    336 
    337   void SetMagicNumber(Isolate* isolate) {
    338     SetHeaderValue(kMagicNumberOffset, ComputeMagicNumber(isolate));
    339   }
    340 
    341   static const int kMagicNumberOffset = 0;
    342 
    343   byte* data_;
    344   int size_;
    345   bool owns_data_;
    346 };
    347 
    348 
    349 // A Deserializer reads a snapshot and reconstructs the Object graph it defines.
    350 class Deserializer: public SerializerDeserializer {
    351  public:
    352   // Create a deserializer from a snapshot byte source.
    353   template <class Data>
    354   explicit Deserializer(Data* data)
    355       : isolate_(NULL),
    356         source_(data->Payload()),
    357         magic_number_(data->GetMagicNumber()),
    358         external_reference_table_(NULL),
    359         deserialized_large_objects_(0),
    360         deserializing_user_code_(false),
    361         next_alignment_(kWordAligned) {
    362     DecodeReservation(data->Reservations());
    363   }
    364 
    365   ~Deserializer() override;
    366 
    367   // Deserialize the snapshot into an empty heap.
    368   void Deserialize(Isolate* isolate);
    369 
    370   // Deserialize a single object and the objects reachable from it.
    371   MaybeHandle<Object> DeserializePartial(Isolate* isolate,
    372                                          Handle<JSGlobalProxy> global_proxy);
    373 
    374   // Deserialize a shared function info. Fail gracefully.
    375   MaybeHandle<SharedFunctionInfo> DeserializeCode(Isolate* isolate);
    376 
    377   // Pass a vector of externally-provided objects referenced by the snapshot.
    378   // The ownership to its backing store is handed over as well.
    379   void SetAttachedObjects(Vector<Handle<Object> > attached_objects) {
    380     attached_objects_ = attached_objects;
    381   }
    382 
    383  private:
    384   void VisitPointers(Object** start, Object** end) override;
    385 
    386   void VisitRuntimeEntry(RelocInfo* rinfo) override { UNREACHABLE(); }
    387 
    388   void Initialize(Isolate* isolate);
    389 
    390   bool deserializing_user_code() { return deserializing_user_code_; }
    391 
    392   void DecodeReservation(Vector<const SerializedData::Reservation> res);
    393 
    394   bool ReserveSpace();
    395 
    396   void UnalignedCopy(Object** dest, Object** src) {
    397     memcpy(dest, src, sizeof(*src));
    398   }
    399 
    400   void SetAlignment(byte data) {
    401     DCHECK_EQ(kWordAligned, next_alignment_);
    402     int alignment = data - (kAlignmentPrefix - 1);
    403     DCHECK_LE(kWordAligned, alignment);
    404     DCHECK_LE(alignment, kSimd128Unaligned);
    405     next_alignment_ = static_cast<AllocationAlignment>(alignment);
    406   }
    407 
    408   void DeserializeDeferredObjects();
    409 
    410   void FlushICacheForNewIsolate();
    411   void FlushICacheForNewCodeObjects();
    412 
    413   void CommitPostProcessedObjects(Isolate* isolate);
    414 
    415   // Fills in some heap data in an area from start to end (non-inclusive).  The
    416   // space id is used for the write barrier.  The object_address is the address
    417   // of the object we are writing into, or NULL if we are not writing into an
    418   // object, i.e. if we are writing a series of tagged values that are not on
    419   // the heap. Return false if the object content has been deferred.
    420   bool ReadData(Object** start, Object** end, int space,
    421                 Address object_address);
    422   void ReadObject(int space_number, Object** write_back);
    423   Address Allocate(int space_index, int size);
    424 
    425   // Special handling for serialized code like hooking up internalized strings.
    426   HeapObject* PostProcessNewObject(HeapObject* obj, int space);
    427 
    428   // This returns the address of an object that has been described in the
    429   // snapshot by chunk index and offset.
    430   HeapObject* GetBackReferencedObject(int space);
    431 
    432   Object** CopyInNativesSource(Vector<const char> source_vector,
    433                                Object** current);
    434 
    435   // Cached current isolate.
    436   Isolate* isolate_;
    437 
    438   // Objects from the attached object descriptions in the serialized user code.
    439   Vector<Handle<Object> > attached_objects_;
    440 
    441   SnapshotByteSource source_;
    442   uint32_t magic_number_;
    443 
    444   // The address of the next object that will be allocated in each space.
    445   // Each space has a number of chunks reserved by the GC, with each chunk
    446   // fitting into a page. Deserialized objects are allocated into the
    447   // current chunk of the target space by bumping up high water mark.
    448   Heap::Reservation reservations_[kNumberOfSpaces];
    449   uint32_t current_chunk_[kNumberOfPreallocatedSpaces];
    450   Address high_water_[kNumberOfPreallocatedSpaces];
    451 
    452   ExternalReferenceTable* external_reference_table_;
    453 
    454   List<HeapObject*> deserialized_large_objects_;
    455   List<Code*> new_code_objects_;
    456   List<Handle<String> > new_internalized_strings_;
    457   List<Handle<Script> > new_scripts_;
    458 
    459   bool deserializing_user_code_;
    460 
    461   AllocationAlignment next_alignment_;
    462 
    463   DISALLOW_COPY_AND_ASSIGN(Deserializer);
    464 };
    465 
    466 
    467 class CodeAddressMap;
    468 
    469 // There can be only one serializer per V8 process.
    470 class Serializer : public SerializerDeserializer {
    471  public:
    472   Serializer(Isolate* isolate, SnapshotByteSink* sink);
    473   ~Serializer() override;
    474   void VisitPointers(Object** start, Object** end) override;
    475 
    476   void EncodeReservations(List<SerializedData::Reservation>* out) const;
    477 
    478   void SerializeDeferredObjects();
    479 
    480   Isolate* isolate() const { return isolate_; }
    481 
    482   BackReferenceMap* back_reference_map() { return &back_reference_map_; }
    483   RootIndexMap* root_index_map() { return &root_index_map_; }
    484 
    485 #ifdef OBJECT_PRINT
    486   void CountInstanceType(Map* map, int size);
    487 #endif  // OBJECT_PRINT
    488 
    489  protected:
    490   class ObjectSerializer;
    491   class RecursionScope {
    492    public:
    493     explicit RecursionScope(Serializer* serializer) : serializer_(serializer) {
    494       serializer_->recursion_depth_++;
    495     }
    496     ~RecursionScope() { serializer_->recursion_depth_--; }
    497     bool ExceedsMaximum() {
    498       return serializer_->recursion_depth_ >= kMaxRecursionDepth;
    499     }
    500 
    501    private:
    502     static const int kMaxRecursionDepth = 32;
    503     Serializer* serializer_;
    504   };
    505 
    506   virtual void SerializeObject(HeapObject* o, HowToCode how_to_code,
    507                                WhereToPoint where_to_point, int skip) = 0;
    508 
    509   void PutRoot(int index, HeapObject* object, HowToCode how, WhereToPoint where,
    510                int skip);
    511 
    512   void PutBackReference(HeapObject* object, BackReference reference);
    513 
    514   // Emit alignment prefix if necessary, return required padding space in bytes.
    515   int PutAlignmentPrefix(HeapObject* object);
    516 
    517   // Returns true if the object was successfully serialized.
    518   bool SerializeKnownObject(HeapObject* obj, HowToCode how_to_code,
    519                             WhereToPoint where_to_point, int skip);
    520 
    521   inline void FlushSkip(int skip) {
    522     if (skip != 0) {
    523       sink_->Put(kSkip, "SkipFromSerializeObject");
    524       sink_->PutInt(skip, "SkipDistanceFromSerializeObject");
    525     }
    526   }
    527 
    528   bool BackReferenceIsAlreadyAllocated(BackReference back_reference);
    529 
    530   // This will return the space for an object.
    531   BackReference AllocateLargeObject(int size);
    532   BackReference Allocate(AllocationSpace space, int size);
    533   int EncodeExternalReference(Address addr) {
    534     return external_reference_encoder_.Encode(addr);
    535   }
    536 
    537   // GetInt reads 4 bytes at once, requiring padding at the end.
    538   void Pad();
    539 
    540   // Some roots should not be serialized, because their actual value depends on
    541   // absolute addresses and they are reset after deserialization, anyway.
    542   bool ShouldBeSkipped(Object** current);
    543 
    544   // We may not need the code address map for logging for every instance
    545   // of the serializer.  Initialize it on demand.
    546   void InitializeCodeAddressMap();
    547 
    548   Code* CopyCode(Code* code);
    549 
    550   inline uint32_t max_chunk_size(int space) const {
    551     DCHECK_LE(0, space);
    552     DCHECK_LT(space, kNumberOfSpaces);
    553     return max_chunk_size_[space];
    554   }
    555 
    556   SnapshotByteSink* sink() const { return sink_; }
    557 
    558   void QueueDeferredObject(HeapObject* obj) {
    559     DCHECK(back_reference_map_.Lookup(obj).is_valid());
    560     deferred_objects_.Add(obj);
    561   }
    562 
    563   void OutputStatistics(const char* name);
    564 
    565   Isolate* isolate_;
    566 
    567   SnapshotByteSink* sink_;
    568   ExternalReferenceEncoder external_reference_encoder_;
    569 
    570   BackReferenceMap back_reference_map_;
    571   RootIndexMap root_index_map_;
    572 
    573   int recursion_depth_;
    574 
    575   friend class Deserializer;
    576   friend class ObjectSerializer;
    577   friend class RecursionScope;
    578   friend class SnapshotData;
    579 
    580  private:
    581   CodeAddressMap* code_address_map_;
    582   // Objects from the same space are put into chunks for bulk-allocation
    583   // when deserializing. We have to make sure that each chunk fits into a
    584   // page. So we track the chunk size in pending_chunk_ of a space, but
    585   // when it exceeds a page, we complete the current chunk and start a new one.
    586   uint32_t pending_chunk_[kNumberOfPreallocatedSpaces];
    587   List<uint32_t> completed_chunks_[kNumberOfPreallocatedSpaces];
    588   uint32_t max_chunk_size_[kNumberOfPreallocatedSpaces];
    589 
    590   // We map serialized large objects to indexes for back-referencing.
    591   uint32_t large_objects_total_size_;
    592   uint32_t seen_large_objects_index_;
    593 
    594   List<byte> code_buffer_;
    595 
    596   // To handle stack overflow.
    597   List<HeapObject*> deferred_objects_;
    598 
    599 #ifdef OBJECT_PRINT
    600   static const int kInstanceTypes = 256;
    601   int* instance_type_count_;
    602   size_t* instance_type_size_;
    603 #endif  // OBJECT_PRINT
    604 
    605   DISALLOW_COPY_AND_ASSIGN(Serializer);
    606 };
    607 
    608 
    609 class PartialSerializer : public Serializer {
    610  public:
    611   PartialSerializer(Isolate* isolate, Serializer* startup_snapshot_serializer,
    612                     SnapshotByteSink* sink)
    613       : Serializer(isolate, sink),
    614         startup_serializer_(startup_snapshot_serializer),
    615         global_object_(NULL) {
    616     InitializeCodeAddressMap();
    617   }
    618 
    619   ~PartialSerializer() override { OutputStatistics("PartialSerializer"); }
    620 
    621   // Serialize the objects reachable from a single object pointer.
    622   void Serialize(Object** o);
    623   void SerializeObject(HeapObject* o, HowToCode how_to_code,
    624                        WhereToPoint where_to_point, int skip) override;
    625 
    626  private:
    627   int PartialSnapshotCacheIndex(HeapObject* o);
    628   bool ShouldBeInThePartialSnapshotCache(HeapObject* o);
    629 
    630   Serializer* startup_serializer_;
    631   Object* global_object_;
    632   PartialCacheIndexMap partial_cache_index_map_;
    633   DISALLOW_COPY_AND_ASSIGN(PartialSerializer);
    634 };
    635 
    636 
    637 class StartupSerializer : public Serializer {
    638  public:
    639   StartupSerializer(Isolate* isolate, SnapshotByteSink* sink);
    640   ~StartupSerializer() override { OutputStatistics("StartupSerializer"); }
    641 
    642   // The StartupSerializer has to serialize the root array, which is slightly
    643   // different.
    644   void VisitPointers(Object** start, Object** end) override;
    645 
    646   // Serialize the current state of the heap.  The order is:
    647   // 1) Strong references.
    648   // 2) Partial snapshot cache.
    649   // 3) Weak references (e.g. the string table).
    650   virtual void SerializeStrongReferences();
    651   void SerializeObject(HeapObject* o, HowToCode how_to_code,
    652                        WhereToPoint where_to_point, int skip) override;
    653   void SerializeWeakReferencesAndDeferred();
    654 
    655  private:
    656   intptr_t root_index_wave_front_;
    657   DISALLOW_COPY_AND_ASSIGN(StartupSerializer);
    658 };
    659 
    660 
    661 class CodeSerializer : public Serializer {
    662  public:
    663   static ScriptData* Serialize(Isolate* isolate,
    664                                Handle<SharedFunctionInfo> info,
    665                                Handle<String> source);
    666 
    667   MUST_USE_RESULT static MaybeHandle<SharedFunctionInfo> Deserialize(
    668       Isolate* isolate, ScriptData* cached_data, Handle<String> source);
    669 
    670   static const int kSourceObjectIndex = 0;
    671   STATIC_ASSERT(kSourceObjectReference == kSourceObjectIndex);
    672 
    673   static const int kCodeStubsBaseIndex = 1;
    674 
    675   String* source() const {
    676     DCHECK(!AllowHeapAllocation::IsAllowed());
    677     return source_;
    678   }
    679 
    680   const List<uint32_t>* stub_keys() const { return &stub_keys_; }
    681 
    682  private:
    683   CodeSerializer(Isolate* isolate, SnapshotByteSink* sink, String* source)
    684       : Serializer(isolate, sink), source_(source) {
    685     back_reference_map_.AddSourceString(source);
    686   }
    687 
    688   ~CodeSerializer() override { OutputStatistics("CodeSerializer"); }
    689 
    690   void SerializeObject(HeapObject* o, HowToCode how_to_code,
    691                        WhereToPoint where_to_point, int skip) override;
    692 
    693   void SerializeBuiltin(int builtin_index, HowToCode how_to_code,
    694                         WhereToPoint where_to_point);
    695   void SerializeIC(Code* ic, HowToCode how_to_code,
    696                    WhereToPoint where_to_point);
    697   void SerializeCodeStub(uint32_t stub_key, HowToCode how_to_code,
    698                          WhereToPoint where_to_point);
    699   void SerializeGeneric(HeapObject* heap_object, HowToCode how_to_code,
    700                         WhereToPoint where_to_point);
    701   int AddCodeStubKey(uint32_t stub_key);
    702 
    703   DisallowHeapAllocation no_gc_;
    704   String* source_;
    705   List<uint32_t> stub_keys_;
    706   DISALLOW_COPY_AND_ASSIGN(CodeSerializer);
    707 };
    708 
    709 
    710 // Wrapper around reservation sizes and the serialization payload.
    711 class SnapshotData : public SerializedData {
    712  public:
    713   // Used when producing.
    714   explicit SnapshotData(const Serializer& ser);
    715 
    716   // Used when consuming.
    717   explicit SnapshotData(const Vector<const byte> snapshot)
    718       : SerializedData(const_cast<byte*>(snapshot.begin()), snapshot.length()) {
    719     CHECK(IsSane());
    720   }
    721 
    722   Vector<const Reservation> Reservations() const;
    723   Vector<const byte> Payload() const;
    724 
    725   Vector<const byte> RawData() const {
    726     return Vector<const byte>(data_, size_);
    727   }
    728 
    729  private:
    730   bool IsSane();
    731 
    732   // The data header consists of uint32_t-sized entries:
    733   // [0] magic number and external reference count
    734   // [1] version hash
    735   // [2] number of reservation size entries
    736   // [3] payload length
    737   // ... reservations
    738   // ... serialized payload
    739   static const int kCheckSumOffset = kMagicNumberOffset + kInt32Size;
    740   static const int kNumReservationsOffset = kCheckSumOffset + kInt32Size;
    741   static const int kPayloadLengthOffset = kNumReservationsOffset + kInt32Size;
    742   static const int kHeaderSize = kPayloadLengthOffset + kInt32Size;
    743 };
    744 
    745 
    746 // Wrapper around ScriptData to provide code-serializer-specific functionality.
    747 class SerializedCodeData : public SerializedData {
    748  public:
    749   // Used when consuming.
    750   static SerializedCodeData* FromCachedData(Isolate* isolate,
    751                                             ScriptData* cached_data,
    752                                             String* source);
    753 
    754   // Used when producing.
    755   SerializedCodeData(const List<byte>& payload, const CodeSerializer& cs);
    756 
    757   // Return ScriptData object and relinquish ownership over it to the caller.
    758   ScriptData* GetScriptData();
    759 
    760   Vector<const Reservation> Reservations() const;
    761   Vector<const byte> Payload() const;
    762 
    763   Vector<const uint32_t> CodeStubKeys() const;
    764 
    765  private:
    766   explicit SerializedCodeData(ScriptData* data);
    767 
    768   enum SanityCheckResult {
    769     CHECK_SUCCESS = 0,
    770     MAGIC_NUMBER_MISMATCH = 1,
    771     VERSION_MISMATCH = 2,
    772     SOURCE_MISMATCH = 3,
    773     CPU_FEATURES_MISMATCH = 4,
    774     FLAGS_MISMATCH = 5,
    775     CHECKSUM_MISMATCH = 6
    776   };
    777 
    778   SanityCheckResult SanityCheck(Isolate* isolate, String* source) const;
    779 
    780   uint32_t SourceHash(String* source) const;
    781 
    782   // The data header consists of uint32_t-sized entries:
    783   // [0] magic number and external reference count
    784   // [1] version hash
    785   // [2] source hash
    786   // [3] cpu features
    787   // [4] flag hash
    788   // [5] number of code stub keys
    789   // [6] number of reservation size entries
    790   // [7] payload length
    791   // [8] payload checksum part 1
    792   // [9] payload checksum part 2
    793   // ...  reservations
    794   // ...  code stub keys
    795   // ...  serialized payload
    796   static const int kVersionHashOffset = kMagicNumberOffset + kInt32Size;
    797   static const int kSourceHashOffset = kVersionHashOffset + kInt32Size;
    798   static const int kCpuFeaturesOffset = kSourceHashOffset + kInt32Size;
    799   static const int kFlagHashOffset = kCpuFeaturesOffset + kInt32Size;
    800   static const int kNumReservationsOffset = kFlagHashOffset + kInt32Size;
    801   static const int kNumCodeStubKeysOffset = kNumReservationsOffset + kInt32Size;
    802   static const int kPayloadLengthOffset = kNumCodeStubKeysOffset + kInt32Size;
    803   static const int kChecksum1Offset = kPayloadLengthOffset + kInt32Size;
    804   static const int kChecksum2Offset = kChecksum1Offset + kInt32Size;
    805   static const int kHeaderSize = kChecksum2Offset + kInt32Size;
    806 };
    807 }  // namespace internal
    808 }  // namespace v8
    809 
    810 #endif  // V8_SNAPSHOT_SERIALIZE_H_
    811