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