// 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 <utility> #include <vector> #include "src/objects/allocation-site.h" #include "src/objects/api-callbacks.h" #include "src/objects/backing-store.h" #include "src/objects/code.h" #include "src/objects/js-array.h" #include "src/objects/map.h" #include "src/objects/string.h" #include "src/snapshot/deserializer-allocator.h" #include "src/snapshot/serializer-common.h" #include "src/snapshot/snapshot-source-sink.h" namespace v8 { namespace internal { class HeapObject; class Object; // 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 // A Deserializer reads a snapshot and reconstructs the Object graph it defines. class V8_EXPORT_PRIVATE Deserializer : public SerializerDeserializer { public: ~Deserializer() override; void SetRehashability(bool v) { can_rehash_ = v; } std::pair<uint32_t, uint32_t> GetChecksum() const { return source_.GetChecksum(); } protected: // Create a deserializer from a snapshot byte source. template <class Data> Deserializer(Data* data, bool deserializing_user_code) : isolate_(nullptr), source_(data->Payload()), magic_number_(data->GetMagicNumber()), deserializing_user_code_(deserializing_user_code), can_rehash_(false) { allocator()->DecodeReservation(data->Reservations()); // We start the indices here at 1, so that we can distinguish between an // actual index and a nullptr in a deserialized object requiring fix-up. backing_stores_.push_back({}); } void Initialize(Isolate* isolate); void DeserializeDeferredObjects(); // Create Log events for newly deserialized objects. void LogNewObjectEvents(); void LogScriptEvents(Script script); void LogNewMapEvents(); // This returns the address of an object that has been described in the // snapshot by chunk index and offset. HeapObject GetBackReferencedObject(SnapshotSpace space); // 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_.push_back(attached_object); } Isolate* isolate() const { return isolate_; } SnapshotByteSource* source() { return &source_; } const std::vector<AllocationSite>& new_allocation_sites() const { return new_allocation_sites_; } const std::vector<Code>& new_code_objects() const { return new_code_objects_; } const std::vector<Map>& new_maps() const { return new_maps_; } const std::vector<AccessorInfo>& accessor_infos() const { return accessor_infos_; } const std::vector<CallHandlerInfo>& call_handler_infos() const { return call_handler_infos_; } const std::vector<Handle<String>>& new_internalized_strings() const { return new_internalized_strings_; } const std::vector<Handle<Script>>& new_scripts() const { return new_scripts_; } DeserializerAllocator* allocator() { return &allocator_; } bool deserializing_user_code() const { return deserializing_user_code_; } bool can_rehash() const { return can_rehash_; } void Rehash(); // Cached current isolate. Isolate* isolate_; private: void VisitRootPointers(Root root, const char* description, FullObjectSlot start, FullObjectSlot end) override; void Synchronize(VisitorSynchronization::SyncTag tag) override; template <typename TSlot> inline TSlot Write(TSlot dest, MaybeObject value); template <typename TSlot> inline TSlot WriteAddress(TSlot dest, Address value); // 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 nullptr 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. template <typename TSlot> bool ReadData(TSlot start, TSlot end, SnapshotSpace space, Address object_address); // A helper function for ReadData, templatized on the bytecode for efficiency. // Returns the new value of {current}. template <typename TSlot, Bytecode bytecode, SnapshotSpace space_number_if_any> inline TSlot ReadDataCase(Isolate* isolate, TSlot current, Address current_object_address, byte data, bool write_barrier_needed); // A helper function for ReadData for reading external references. inline Address ReadExternalReferenceCase(); HeapObject ReadObject(); HeapObject ReadObject(SnapshotSpace space_number); void ReadCodeObjectBody(SnapshotSpace space_number, Address code_object_address); public: void VisitCodeTarget(Code host, RelocInfo* rinfo); void VisitEmbeddedPointer(Code host, RelocInfo* rinfo); void VisitRuntimeEntry(Code host, RelocInfo* rinfo); void VisitExternalReference(Code host, RelocInfo* rinfo); void VisitInternalReference(Code host, RelocInfo* rinfo); void VisitOffHeapTarget(Code host, RelocInfo* rinfo); private: template <typename TSlot> TSlot ReadRepeatedObject(TSlot current, int repeat_count); // Special handling for serialized code like hooking up internalized strings. HeapObject PostProcessNewObject(HeapObject obj, SnapshotSpace space); // Objects from the attached object descriptions in the serialized user code. std::vector<Handle<HeapObject>> attached_objects_; SnapshotByteSource source_; uint32_t magic_number_; std::vector<Map> new_maps_; std::vector<AllocationSite> new_allocation_sites_; std::vector<Code> new_code_objects_; std::vector<AccessorInfo> accessor_infos_; std::vector<CallHandlerInfo> call_handler_infos_; std::vector<Handle<String>> new_internalized_strings_; std::vector<Handle<Script>> new_scripts_; std::vector<std::shared_ptr<BackingStore>> backing_stores_; DeserializerAllocator allocator_; const bool deserializing_user_code_; // TODO(6593): generalize rehashing, and remove this flag. bool can_rehash_; std::vector<HeapObject> to_rehash_; #ifdef DEBUG uint32_t num_api_references_; #endif // DEBUG // For source(), isolate(), and allocator(). friend class DeserializerAllocator; DISALLOW_COPY_AND_ASSIGN(Deserializer); }; // Used to insert a deserialized internalized string into the string table. class StringTableInsertionKey final : public StringTableKey { public: explicit StringTableInsertionKey(String string); bool IsMatch(String string) override; V8_WARN_UNUSED_RESULT Handle<String> AsHandle(Isolate* isolate) override; String string() const { return string_; } private: uint32_t ComputeHashField(String string); String string_; DISALLOW_HEAP_ALLOCATION(no_gc) }; } // namespace internal } // namespace v8 #endif // V8_SNAPSHOT_DESERIALIZER_H_