1 // Copyright 2016 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_DESERIALIZER_H_
6 #define V8_SNAPSHOT_DESERIALIZER_H_
7 
8 #include <utility>
9 #include <vector>
10 
11 #include "src/objects/allocation-site.h"
12 #include "src/objects/api-callbacks.h"
13 #include "src/objects/backing-store.h"
14 #include "src/objects/code.h"
15 #include "src/objects/js-array.h"
16 #include "src/objects/map.h"
17 #include "src/objects/string.h"
18 #include "src/snapshot/deserializer-allocator.h"
19 #include "src/snapshot/serializer-common.h"
20 #include "src/snapshot/snapshot-source-sink.h"
21 
22 namespace v8 {
23 namespace internal {
24 
25 class HeapObject;
26 class Object;
27 
28 // Used for platforms with embedded constant pools to trigger deserialization
29 // of objects found in code.
30 #if defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64) || \
31     defined(V8_TARGET_ARCH_PPC) || defined(V8_TARGET_ARCH_S390) ||    \
32     defined(V8_TARGET_ARCH_PPC64) || V8_EMBEDDED_CONSTANT_POOL
33 #define V8_CODE_EMBEDS_OBJECT_POINTER 1
34 #else
35 #define V8_CODE_EMBEDS_OBJECT_POINTER 0
36 #endif
37 
38 // A Deserializer reads a snapshot and reconstructs the Object graph it defines.
39 class V8_EXPORT_PRIVATE Deserializer : public SerializerDeserializer {
40  public:
41   ~Deserializer() override;
42 
SetRehashability(bool v)43   void SetRehashability(bool v) { can_rehash_ = v; }
GetChecksum()44   uint32_t GetChecksum() const { return source_.GetChecksum(); }
45 
46  protected:
47   // Create a deserializer from a snapshot byte source.
48   template <class Data>
Deserializer(Data * data,bool deserializing_user_code)49   Deserializer(Data* data, bool deserializing_user_code)
50       : isolate_(nullptr),
51         source_(data->Payload()),
52         magic_number_(data->GetMagicNumber()),
53         deserializing_user_code_(deserializing_user_code),
54         can_rehash_(false) {
55     allocator()->DecodeReservation(data->Reservations());
56     // We start the indices here at 1, so that we can distinguish between an
57     // actual index and a nullptr in a deserialized object requiring fix-up.
58     backing_stores_.push_back({});
59   }
60 
61   void Initialize(Isolate* isolate);
62   void DeserializeDeferredObjects();
63 
64   // Create Log events for newly deserialized objects.
65   void LogNewObjectEvents();
66   void LogScriptEvents(Script script);
67   void LogNewMapEvents();
68 
69   // This returns the address of an object that has been described in the
70   // snapshot by chunk index and offset.
71   HeapObject GetBackReferencedObject(SnapshotSpace space);
72 
73   // Add an object to back an attached reference. The order to add objects must
74   // mirror the order they are added in the serializer.
AddAttachedObject(Handle<HeapObject> attached_object)75   void AddAttachedObject(Handle<HeapObject> attached_object) {
76     attached_objects_.push_back(attached_object);
77   }
78 
CheckNoArrayBufferBackingStores()79   void CheckNoArrayBufferBackingStores() {
80     CHECK_EQ(new_off_heap_array_buffers().size(), 0);
81   }
82 
isolate()83   Isolate* isolate() const { return isolate_; }
source()84   SnapshotByteSource* source() { return &source_; }
new_allocation_sites()85   const std::vector<AllocationSite>& new_allocation_sites() const {
86     return new_allocation_sites_;
87   }
new_code_objects()88   const std::vector<Code>& new_code_objects() const {
89     return new_code_objects_;
90   }
new_maps()91   const std::vector<Map>& new_maps() const { return new_maps_; }
accessor_infos()92   const std::vector<AccessorInfo>& accessor_infos() const {
93     return accessor_infos_;
94   }
call_handler_infos()95   const std::vector<CallHandlerInfo>& call_handler_infos() const {
96     return call_handler_infos_;
97   }
new_internalized_strings()98   const std::vector<Handle<String>>& new_internalized_strings() const {
99     return new_internalized_strings_;
100   }
new_scripts()101   const std::vector<Handle<Script>>& new_scripts() const {
102     return new_scripts_;
103   }
104 
new_off_heap_array_buffers()105   const std::vector<Handle<JSArrayBuffer>>& new_off_heap_array_buffers() const {
106     return new_off_heap_array_buffers_;
107   }
108 
backing_store(size_t i)109   std::shared_ptr<BackingStore> backing_store(size_t i) {
110     return backing_stores_[i];
111   }
112 
allocator()113   DeserializerAllocator* allocator() { return &allocator_; }
deserializing_user_code()114   bool deserializing_user_code() const { return deserializing_user_code_; }
can_rehash()115   bool can_rehash() const { return can_rehash_; }
116 
117   void Rehash();
118 
119   // Cached current isolate.
120   Isolate* isolate_;
121 
122  private:
123   void VisitRootPointers(Root root, const char* description,
124                          FullObjectSlot start, FullObjectSlot end) override;
125 
126   void Synchronize(VisitorSynchronization::SyncTag tag) override;
127 
128   template <typename TSlot>
129   inline TSlot Write(TSlot dest, MaybeObject value);
130 
131   template <typename TSlot>
132   inline TSlot WriteAddress(TSlot dest, Address value);
133 
134   // Fills in some heap data in an area from start to end (non-inclusive).  The
135   // space id is used for the write barrier.  The object_address is the address
136   // of the object we are writing into, or nullptr if we are not writing into an
137   // object, i.e. if we are writing a series of tagged values that are not on
138   // the heap. Return false if the object content has been deferred.
139   template <typename TSlot>
140   bool ReadData(TSlot start, TSlot end, SnapshotSpace space,
141                 Address object_address);
142 
143   // A helper function for ReadData, templatized on the bytecode for efficiency.
144   // Returns the new value of {current}.
145   template <typename TSlot, Bytecode bytecode,
146             SnapshotSpace space_number_if_any>
147   inline TSlot ReadDataCase(Isolate* isolate, TSlot current,
148                             Address current_object_address, byte data,
149                             bool write_barrier_needed);
150 
151   // A helper function for ReadData for reading external references.
152   inline Address ReadExternalReferenceCase();
153 
154   HeapObject ReadObject();
155   HeapObject ReadObject(SnapshotSpace space_number);
156   void ReadCodeObjectBody(SnapshotSpace space_number,
157                           Address code_object_address);
158 
159  public:
160   void VisitCodeTarget(Code host, RelocInfo* rinfo);
161   void VisitEmbeddedPointer(Code host, RelocInfo* rinfo);
162   void VisitRuntimeEntry(Code host, RelocInfo* rinfo);
163   void VisitExternalReference(Code host, RelocInfo* rinfo);
164   void VisitInternalReference(Code host, RelocInfo* rinfo);
165   void VisitOffHeapTarget(Code host, RelocInfo* rinfo);
166 
167  private:
168   template <typename TSlot>
169   TSlot ReadRepeatedObject(TSlot current, int repeat_count);
170 
171   // Special handling for serialized code like hooking up internalized strings.
172   HeapObject PostProcessNewObject(HeapObject obj, SnapshotSpace space);
173 
174   // Objects from the attached object descriptions in the serialized user code.
175   std::vector<Handle<HeapObject>> attached_objects_;
176 
177   SnapshotByteSource source_;
178   uint32_t magic_number_;
179 
180   std::vector<Map> new_maps_;
181   std::vector<AllocationSite> new_allocation_sites_;
182   std::vector<Code> new_code_objects_;
183   std::vector<AccessorInfo> accessor_infos_;
184   std::vector<CallHandlerInfo> call_handler_infos_;
185   std::vector<Handle<String>> new_internalized_strings_;
186   std::vector<Handle<Script>> new_scripts_;
187   std::vector<Handle<JSArrayBuffer>> new_off_heap_array_buffers_;
188   std::vector<std::shared_ptr<BackingStore>> backing_stores_;
189 
190   DeserializerAllocator allocator_;
191   const bool deserializing_user_code_;
192 
193   // TODO(6593): generalize rehashing, and remove this flag.
194   bool can_rehash_;
195   std::vector<HeapObject> to_rehash_;
196 
197 #ifdef DEBUG
198   uint32_t num_api_references_;
199 #endif  // DEBUG
200 
201   // For source(), isolate(), and allocator().
202   friend class DeserializerAllocator;
203 
204   DISALLOW_COPY_AND_ASSIGN(Deserializer);
205 };
206 
207 // Used to insert a deserialized internalized string into the string table.
208 class StringTableInsertionKey final : public StringTableKey {
209  public:
210   explicit StringTableInsertionKey(String string);
211 
212   bool IsMatch(String string) override;
213 
214   V8_WARN_UNUSED_RESULT Handle<String> AsHandle(Isolate* isolate) override;
215 
string()216   String string() const { return string_; }
217 
218  private:
219   uint32_t ComputeHashField(String string);
220 
221   String string_;
222   DISALLOW_HEAP_ALLOCATION(no_gc)
223 };
224 
225 }  // namespace internal
226 }  // namespace v8
227 
228 #endif  // V8_SNAPSHOT_DESERIALIZER_H_
229