text: // Copyright 2016 the V8 project authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  #ifndef V8_SNAPSHOT_DESERIALIZER_H_
  #define V8_SNAPSHOT_DESERIALIZER_H_
  
  #include "src/heap/heap.h"
  #include "src/objects.h"
  #include "src/snapshot/serializer-common.h"
  #include "src/snapshot/snapshot-source-sink.h"
  
  namespace v8 {
  namespace internal {
  
  // Used for platforms with embedded constant pools to trigger deserialization
  // of objects found in code.
  #if defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64) || \
      defined(V8_TARGET_ARCH_PPC) || defined(V8_TARGET_ARCH_S390) ||    \
      V8_EMBEDDED_CONSTANT_POOL
  #define V8_CODE_EMBEDS_OBJECT_POINTER 1
  #else
  #define V8_CODE_EMBEDS_OBJECT_POINTER 0
  #endif
  
  class Heap;
  
  // A Deserializer reads a snapshot and reconstructs the Object graph it defines.
  class Deserializer : public SerializerDeserializer {
   public:
    // Create a deserializer from a snapshot byte source.
    template <class Data>
    explicit Deserializer(Data* data, bool deserializing_user_code = false)
        : isolate_(NULL),
          source_(data->Payload()),
          magic_number_(data->GetMagicNumber()),
          num_extra_references_(data->GetExtraReferences()),
          next_map_index_(0),
          external_reference_table_(NULL),
          deserialized_large_objects_(0),
          deserializing_user_code_(deserializing_user_code),
          next_alignment_(kWordAligned) {
      DecodeReservation(data->Reservations());
    }
  
    ~Deserializer() override;
  
    // Deserialize the snapshot into an empty heap.
    void Deserialize(Isolate* isolate);
  
    // Deserialize a single object and the objects reachable from it.
    MaybeHandle<Object> DeserializePartial(
        Isolate* isolate, Handle<JSGlobalProxy> global_proxy,
        v8::DeserializeInternalFieldsCallback internal_fields_deserializer);
  
    // Deserialize an object graph. Fail gracefully.
    MaybeHandle<HeapObject> DeserializeObject(Isolate* isolate);
  
    // Add an object to back an attached reference. The order to add objects must
    // mirror the order they are added in the serializer.
    void AddAttachedObject(Handle<HeapObject> attached_object) {
      attached_objects_.Add(attached_object);
    }
  
   private:
    void VisitPointers(Object** start, Object** end) override;
  
    void Synchronize(VisitorSynchronization::SyncTag tag) override;
  
    void VisitRuntimeEntry(RelocInfo* rinfo) override { UNREACHABLE(); }
  
    void Initialize(Isolate* isolate);
  
    bool deserializing_user_code() { return deserializing_user_code_; }
  
    void DecodeReservation(Vector<const SerializedData::Reservation> res);
  
    bool ReserveSpace();
  
    void UnalignedCopy(Object** dest, Object** src) {
      memcpy(dest, src, sizeof(*src));
    }
  
    void SetAlignment(byte data) {
      DCHECK_EQ(kWordAligned, next_alignment_);
      int alignment = data - (kAlignmentPrefix - 1);
      DCHECK_LE(kWordAligned, alignment);
      DCHECK_LE(alignment, kDoubleUnaligned);
      next_alignment_ = static_cast<AllocationAlignment>(alignment);
    }
  
    void DeserializeDeferredObjects();
    void DeserializeInternalFields(
        v8::DeserializeInternalFieldsCallback internal_fields_deserializer);
  
    void FlushICacheForNewIsolate();
    void FlushICacheForNewCodeObjectsAndRecordEmbeddedObjects();
  
    void CommitPostProcessedObjects(Isolate* isolate);
  
    // Fills in some heap data in an area from start to end (non-inclusive).  The
    // space id is used for the write barrier.  The object_address is the address
    // of the object we are writing into, or NULL if we are not writing into an
    // object, i.e. if we are writing a series of tagged values that are not on
    // the heap. Return false if the object content has been deferred.
    bool ReadData(Object** start, Object** end, int space,
                  Address object_address);
    void ReadObject(int space_number, Object** write_back);
    Address Allocate(int space_index, int size);
  
    // Special handling for serialized code like hooking up internalized strings.
    HeapObject* PostProcessNewObject(HeapObject* obj, int space);
  
    // This returns the address of an object that has been described in the
    // snapshot by chunk index and offset.
    HeapObject* GetBackReferencedObject(int space);
  
    Object** CopyInNativesSource(Vector<const char> source_vector,
                                 Object** current);
  
    // Cached current isolate.
    Isolate* isolate_;
  
    // Objects from the attached object descriptions in the serialized user code.
    List<Handle<HeapObject> > attached_objects_;
  
    SnapshotByteSource source_;
    uint32_t magic_number_;
    uint32_t num_extra_references_;
  
    // The address of the next object that will be allocated in each space.
    // Each space has a number of chunks reserved by the GC, with each chunk
    // fitting into a page. Deserialized objects are allocated into the
    // current chunk of the target space by bumping up high water mark.
    Heap::Reservation reservations_[kNumberOfSpaces];
    uint32_t current_chunk_[kNumberOfPreallocatedSpaces];
    Address high_water_[kNumberOfPreallocatedSpaces];
    int next_map_index_;
    List<Address> allocated_maps_;
  
    ExternalReferenceTable* external_reference_table_;
  
    List<HeapObject*> deserialized_large_objects_;
    List<Code*> new_code_objects_;
    List<AccessorInfo*> accessor_infos_;
    List<Handle<String> > new_internalized_strings_;
    List<Handle<Script> > new_scripts_;
  
    bool deserializing_user_code_;
  
    AllocationAlignment next_alignment_;
  
    DISALLOW_COPY_AND_ASSIGN(Deserializer);
  };
  
  }  // namespace internal
  }  // namespace v8
  
  #endif  // V8_SNAPSHOT_DESERIALIZER_H_
  