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