• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/base/macros.h"
12 #include "src/base/optional.h"
13 #include "src/common/globals.h"
14 #include "src/execution/local-isolate.h"
15 #include "src/objects/allocation-site.h"
16 #include "src/objects/api-callbacks.h"
17 #include "src/objects/backing-store.h"
18 #include "src/objects/code.h"
19 #include "src/objects/js-array.h"
20 #include "src/objects/map.h"
21 #include "src/objects/smi.h"
22 #include "src/objects/string-table.h"
23 #include "src/objects/string.h"
24 #include "src/snapshot/serializer-deserializer.h"
25 #include "src/snapshot/snapshot-source-sink.h"
26 
27 namespace v8 {
28 namespace internal {
29 
30 class HeapObject;
31 class Object;
32 
33 // Used for platforms with embedded constant pools to trigger deserialization
34 // of objects found in code.
35 #if defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64) ||   \
36     defined(V8_TARGET_ARCH_PPC) || defined(V8_TARGET_ARCH_S390) ||      \
37     defined(V8_TARGET_ARCH_PPC64) || defined(V8_TARGET_ARCH_RISCV64) || \
38     V8_EMBEDDED_CONSTANT_POOL
39 #define V8_CODE_EMBEDS_OBJECT_POINTER 1
40 #else
41 #define V8_CODE_EMBEDS_OBJECT_POINTER 0
42 #endif
43 
44 // A Deserializer reads a snapshot and reconstructs the Object graph it defines.
45 template <typename IsolateT>
46 class Deserializer : public SerializerDeserializer {
47  public:
48   ~Deserializer() override;
49   Deserializer(const Deserializer&) = delete;
50   Deserializer& operator=(const Deserializer&) = delete;
51 
52  protected:
53   // Create a deserializer from a snapshot byte source.
54   Deserializer(IsolateT* isolate, base::Vector<const byte> payload,
55                uint32_t magic_number, bool deserializing_user_code,
56                bool can_rehash);
57 
58   void DeserializeDeferredObjects();
59 
60   // Create Log events for newly deserialized objects.
61   void LogNewObjectEvents();
62   void LogScriptEvents(Script script);
63   void LogNewMapEvents();
64 
65   // Descriptor arrays are deserialized as "strong", so that there is no risk of
66   // them getting trimmed during a partial deserialization. This method makes
67   // them "weak" again after deserialization completes.
68   void WeakenDescriptorArrays();
69 
70   // This returns the address of an object that has been described in the
71   // snapshot by object vector index.
72   Handle<HeapObject> GetBackReferencedObject();
73 
74   // Add an object to back an attached reference. The order to add objects must
75   // mirror the order they are added in the serializer.
AddAttachedObject(Handle<HeapObject> attached_object)76   void AddAttachedObject(Handle<HeapObject> attached_object) {
77     attached_objects_.push_back(attached_object);
78   }
79 
CheckNoArrayBufferBackingStores()80   void CheckNoArrayBufferBackingStores() {
81     CHECK_EQ(new_off_heap_array_buffers().size(), 0);
82   }
83 
isolate()84   IsolateT* isolate() const { return isolate_; }
85 
main_thread_isolate()86   Isolate* main_thread_isolate() const { return isolate_->AsIsolate(); }
87 
source()88   SnapshotByteSource* source() { return &source_; }
new_allocation_sites()89   const std::vector<Handle<AllocationSite>>& new_allocation_sites() const {
90     return new_allocation_sites_;
91   }
new_code_objects()92   const std::vector<Handle<Code>>& new_code_objects() const {
93     return new_code_objects_;
94   }
new_maps()95   const std::vector<Handle<Map>>& new_maps() const { return new_maps_; }
accessor_infos()96   const std::vector<Handle<AccessorInfo>>& accessor_infos() const {
97     return accessor_infos_;
98   }
call_handler_infos()99   const std::vector<Handle<CallHandlerInfo>>& call_handler_infos() const {
100     return call_handler_infos_;
101   }
new_scripts()102   const std::vector<Handle<Script>>& new_scripts() const {
103     return new_scripts_;
104   }
105 
new_off_heap_array_buffers()106   const std::vector<Handle<JSArrayBuffer>>& new_off_heap_array_buffers() const {
107     return new_off_heap_array_buffers_;
108   }
109 
new_descriptor_arrays()110   const std::vector<Handle<DescriptorArray>>& new_descriptor_arrays() const {
111     return new_descriptor_arrays_;
112   }
113 
backing_store(size_t i)114   std::shared_ptr<BackingStore> backing_store(size_t i) {
115     DCHECK_LT(i, backing_stores_.size());
116     return backing_stores_[i];
117   }
118 
deserializing_user_code()119   bool deserializing_user_code() const { return deserializing_user_code_; }
should_rehash()120   bool should_rehash() const { return should_rehash_; }
121 
122   void Rehash();
123 
124   Handle<HeapObject> ReadObject();
125 
126  private:
127   friend class DeserializerRelocInfoVisitor;
128   // A circular queue of hot objects. This is added to in the same order as in
129   // Serializer::HotObjectsList, but this stores the objects as a vector of
130   // existing handles. This allows us to add Handles to the queue without having
131   // to create new handles. Note that this depends on those Handles staying
132   // valid as long as the HotObjectsList is alive.
133   class HotObjectsList {
134    public:
135     HotObjectsList() = default;
136     HotObjectsList(const HotObjectsList&) = delete;
137     HotObjectsList& operator=(const HotObjectsList&) = delete;
138 
Add(Handle<HeapObject> object)139     void Add(Handle<HeapObject> object) {
140       circular_queue_[index_] = object;
141       index_ = (index_ + 1) & kSizeMask;
142     }
143 
Get(int index)144     Handle<HeapObject> Get(int index) {
145       DCHECK(!circular_queue_[index].is_null());
146       return circular_queue_[index];
147     }
148 
149    private:
150     static const int kSize = kHotObjectCount;
151     static const int kSizeMask = kSize - 1;
152     STATIC_ASSERT(base::bits::IsPowerOfTwo(kSize));
153     Handle<HeapObject> circular_queue_[kSize];
154     int index_ = 0;
155   };
156 
157   void VisitRootPointers(Root root, const char* description,
158                          FullObjectSlot start, FullObjectSlot end) override;
159 
160   void Synchronize(VisitorSynchronization::SyncTag tag) override;
161 
162   template <typename TSlot>
163   inline int WriteAddress(TSlot dest, Address value);
164 
165   template <typename TSlot>
166   inline int WriteExternalPointer(TSlot dest, Address value,
167                                   ExternalPointerTag tag);
168 
169   // Fills in a heap object's data from start to end (exclusive). Start and end
170   // are slot indices within the object.
171   void ReadData(Handle<HeapObject> object, int start_slot_index,
172                 int end_slot_index);
173 
174   // Fills in a contiguous range of full object slots (e.g. root pointers) from
175   // start to end (exclusive).
176   void ReadData(FullMaybeObjectSlot start, FullMaybeObjectSlot end);
177 
178   // Helper for ReadData which reads the given bytecode and fills in some heap
179   // data into the given slot. May fill in zero or multiple slots, so it returns
180   // the number of slots filled.
181   template <typename SlotAccessor>
182   int ReadSingleBytecodeData(byte data, SlotAccessor slot_accessor);
183 
184   // A helper function for ReadData for reading external references.
185   inline Address ReadExternalReferenceCase();
186 
187   // A helper function for reading external pointer tags.
188   ExternalPointerTag ReadExternalPointerTag();
189 
190   Handle<HeapObject> ReadObject(SnapshotSpace space_number);
191   Handle<HeapObject> ReadMetaMap();
192 
193   HeapObjectReferenceType GetAndResetNextReferenceType();
194 
195   template <typename SlotGetter>
196   int ReadRepeatedObject(SlotGetter slot_getter, int repeat_count);
197 
198   // Special handling for serialized code like hooking up internalized strings.
199   void PostProcessNewObject(Handle<Map> map, Handle<HeapObject> obj,
200                             SnapshotSpace space);
201   void PostProcessNewJSReceiver(Map map, Handle<JSReceiver> obj,
202                                 JSReceiver raw_obj, InstanceType instance_type,
203                                 SnapshotSpace space);
204 
205   HeapObject Allocate(AllocationType allocation, int size,
206                       AllocationAlignment alignment);
207 
208   // Cached current isolate.
209   IsolateT* isolate_;
210 
211   // Objects from the attached object descriptions in the serialized user code.
212   std::vector<Handle<HeapObject>> attached_objects_;
213 
214   SnapshotByteSource source_;
215   uint32_t magic_number_;
216 
217   HotObjectsList hot_objects_;
218   std::vector<Handle<Map>> new_maps_;
219   std::vector<Handle<AllocationSite>> new_allocation_sites_;
220   std::vector<Handle<Code>> new_code_objects_;
221   std::vector<Handle<AccessorInfo>> accessor_infos_;
222   std::vector<Handle<CallHandlerInfo>> call_handler_infos_;
223   std::vector<Handle<Script>> new_scripts_;
224   std::vector<Handle<JSArrayBuffer>> new_off_heap_array_buffers_;
225   std::vector<Handle<DescriptorArray>> new_descriptor_arrays_;
226   std::vector<std::shared_ptr<BackingStore>> backing_stores_;
227 
228   // Vector of allocated objects that can be accessed by a backref, by index.
229   std::vector<Handle<HeapObject>> back_refs_;
230 
231   // Unresolved forward references (registered with kRegisterPendingForwardRef)
232   // are collected in order as (object, field offset) pairs. The subsequent
233   // forward ref resolution (with kResolvePendingForwardRef) accesses this
234   // vector by index.
235   //
236   // The vector is cleared when there are no more unresolved forward refs.
237   struct UnresolvedForwardRef {
UnresolvedForwardRefUnresolvedForwardRef238     UnresolvedForwardRef(Handle<HeapObject> object, int offset,
239                          HeapObjectReferenceType ref_type)
240         : object(object), offset(offset), ref_type(ref_type) {}
241 
242     Handle<HeapObject> object;
243     int offset;
244     HeapObjectReferenceType ref_type;
245   };
246   std::vector<UnresolvedForwardRef> unresolved_forward_refs_;
247   int num_unresolved_forward_refs_ = 0;
248 
249   const bool deserializing_user_code_;
250 
251   bool next_reference_is_weak_ = false;
252 
253   // TODO(6593): generalize rehashing, and remove this flag.
254   const bool should_rehash_;
255   std::vector<Handle<HeapObject>> to_rehash_;
256 
257 #ifdef DEBUG
258   uint32_t num_api_references_;
259 
260   // Record the previous object allocated for DCHECKs.
261   Handle<HeapObject> previous_allocation_obj_;
262   int previous_allocation_size_ = 0;
263 #endif  // DEBUG
264 };
265 
266 extern template class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
267     Deserializer<Isolate>;
268 extern template class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
269     Deserializer<LocalIsolate>;
270 
271 enum class DeserializingUserCodeOption {
272   kNotDeserializingUserCode,
273   kIsDeserializingUserCode
274 };
275 
276 // Used to insert a deserialized internalized string into the string table.
277 class StringTableInsertionKey final : public StringTableKey {
278  public:
279   explicit StringTableInsertionKey(
280       Isolate* isolate, Handle<String> string,
281       DeserializingUserCodeOption deserializing_user_code);
282   explicit StringTableInsertionKey(
283       LocalIsolate* isolate, Handle<String> string,
284       DeserializingUserCodeOption deserializing_user_code);
285 
286   template <typename IsolateT>
287   bool IsMatch(IsolateT* isolate, String string);
288 
PrepareForInsertion(Isolate * isolate)289   void PrepareForInsertion(Isolate* isolate) {
290     // When sharing the string table, all string table lookups during snapshot
291     // deserialization are hits.
292     DCHECK(isolate->OwnsStringTable() ||
293            deserializing_user_code_ ==
294                DeserializingUserCodeOption::kIsDeserializingUserCode);
295   }
PrepareForInsertion(LocalIsolate * isolate)296   void PrepareForInsertion(LocalIsolate* isolate) {}
GetHandleForInsertion()297   V8_WARN_UNUSED_RESULT Handle<String> GetHandleForInsertion() {
298     return string_;
299   }
300 
301  private:
302   Handle<String> string_;
303 #ifdef DEBUG
304   DeserializingUserCodeOption deserializing_user_code_;
305 #endif
306   DISALLOW_GARBAGE_COLLECTION(no_gc)
307 };
308 
309 }  // namespace internal
310 }  // namespace v8
311 
312 #endif  // V8_SNAPSHOT_DESERIALIZER_H_
313