deserializer.h 10.7 KB
Newer Older
1 2 3 4 5 6 7
// 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_

8
#include <utility>
9 10
#include <vector>

11 12
#include "src/base/macros.h"
#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 26 27 28 29
#include "src/snapshot/snapshot-source-sink.h"

namespace v8 {
namespace internal {

30 31 32
class HeapObject;
class Object;

33 34
// Used for platforms with embedded constant pools to trigger deserialization
// of objects found in code.
Brice Dobry's avatar
Brice Dobry committed
35 36 37 38
#if defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64) ||   \
    defined(V8_TARGET_ARCH_PPC) || defined(V8_TARGET_ARCH_S390) ||      \
    defined(V8_TARGET_ARCH_PPC64) || defined(V8_TARGET_ARCH_RISCV64) || \
    V8_EMBEDDED_CONSTANT_POOL
39 40 41 42 43
#define V8_CODE_EMBEDS_OBJECT_POINTER 1
#else
#define V8_CODE_EMBEDS_OBJECT_POINTER 0
#endif

44
// A Deserializer reads a snapshot and reconstructs the Object graph it defines.
45 46
template <typename IsolateT>
class Deserializer : public SerializerDeserializer {
47
 public:
48
  ~Deserializer() override;
49 50
  Deserializer(const Deserializer&) = delete;
  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 56
               uint32_t magic_number, bool deserializing_user_code,
               bool can_rehash);
57

58
  void DeserializeDeferredObjects();
59

60 61
  // Create Log events for newly deserialized objects.
  void LogNewObjectEvents();
62
  void LogScriptEvents(Script script);
63 64
  void LogNewMapEvents();

65 66 67 68 69
  // Descriptor arrays are deserialized as "strong", so that there is no risk of
  // them getting trimmed during a partial deserialization. This method makes
  // them "weak" again after deserialization completes.
  void WeakenDescriptorArrays();

70
  // This returns the address of an object that has been described in the
71 72
  // snapshot by object vector index.
  Handle<HeapObject> GetBackReferencedObject();
73

74 75 76 77 78 79
  // 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);
  }

80 81 82 83
  void CheckNoArrayBufferBackingStores() {
    CHECK_EQ(new_off_heap_array_buffers().size(), 0);
  }

84 85 86
  IsolateT* isolate() const { return isolate_; }

  Isolate* main_thread_isolate() const { return isolate_->AsIsolate(); }
87

88
  SnapshotByteSource* source() { return &source_; }
89
  const std::vector<Handle<AllocationSite>>& new_allocation_sites() const {
90 91
    return new_allocation_sites_;
  }
92
  const std::vector<Handle<Code>>& new_code_objects() const {
93 94
    return new_code_objects_;
  }
95 96
  const std::vector<Handle<Map>>& new_maps() const { return new_maps_; }
  const std::vector<Handle<AccessorInfo>>& accessor_infos() const {
97 98
    return accessor_infos_;
  }
99
  const std::vector<Handle<CallHandlerInfo>>& call_handler_infos() const {
100 101
    return call_handler_infos_;
  }
102 103 104
  const std::vector<Handle<Script>>& new_scripts() const {
    return new_scripts_;
  }
105

106 107 108 109
  const std::vector<Handle<JSArrayBuffer>>& new_off_heap_array_buffers() const {
    return new_off_heap_array_buffers_;
  }

110 111 112 113
  const std::vector<Handle<DescriptorArray>>& new_descriptor_arrays() const {
    return new_descriptor_arrays_;
  }

114
  std::shared_ptr<BackingStore> backing_store(size_t i) {
115
    DCHECK_LT(i, backing_stores_.size());
116 117 118
    return backing_stores_[i];
  }

119
  bool deserializing_user_code() const { return deserializing_user_code_; }
120
  bool should_rehash() const { return should_rehash_; }
121

122 123
  void Rehash();

124 125
  Handle<HeapObject> ReadObject();

126
 private:
127
  friend class DeserializerRelocInfoVisitor;
128 129 130 131 132 133 134 135
  // A circular queue of hot objects. This is added to in the same order as in
  // Serializer::HotObjectsList, but this stores the objects as a vector of
  // existing handles. This allows us to add Handles to the queue without having
  // to create new handles. Note that this depends on those Handles staying
  // valid as long as the HotObjectsList is alive.
  class HotObjectsList {
   public:
    HotObjectsList() = default;
136 137
    HotObjectsList(const HotObjectsList&) = delete;
    HotObjectsList& operator=(const HotObjectsList&) = delete;
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155

    void Add(Handle<HeapObject> object) {
      circular_queue_[index_] = object;
      index_ = (index_ + 1) & kSizeMask;
    }

    Handle<HeapObject> Get(int index) {
      DCHECK(!circular_queue_[index].is_null());
      return circular_queue_[index];
    }

   private:
    static const int kSize = kHotObjectCount;
    static const int kSizeMask = kSize - 1;
    STATIC_ASSERT(base::bits::IsPowerOfTwo(kSize));
    Handle<HeapObject> circular_queue_[kSize];
    int index_ = 0;
  };
156

157 158
  void VisitRootPointers(Root root, const char* description,
                         FullObjectSlot start, FullObjectSlot end) override;
159 160 161

  void Synchronize(VisitorSynchronization::SyncTag tag) override;

162
  template <typename TSlot>
163
  inline int WriteAddress(TSlot dest, Address value);
164

165
  template <typename TSlot>
166 167
  inline int WriteExternalPointer(TSlot dest, Address value,
                                  ExternalPointerTag tag);
168

169 170 171 172
  // Fills in a heap object's data from start to end (exclusive). Start and end
  // are slot indices within the object.
  void ReadData(Handle<HeapObject> object, int start_slot_index,
                int end_slot_index);
173

174 175 176
  // Fills in a contiguous range of full object slots (e.g. root pointers) from
  // start to end (exclusive).
  void ReadData(FullMaybeObjectSlot start, FullMaybeObjectSlot end);
177

178 179
  // Helper for ReadData which reads the given bytecode and fills in some heap
  // data into the given slot. May fill in zero or multiple slots, so it returns
180 181 182
  // the number of slots filled.
  template <typename SlotAccessor>
  int ReadSingleBytecodeData(byte data, SlotAccessor slot_accessor);
183

184
  // A helper function for ReadData for reading external references.
185
  inline Address ReadExternalReferenceCase();
186

187 188 189
  // A helper function for reading external pointer tags.
  ExternalPointerTag ReadExternalPointerTag();

190 191
  Handle<HeapObject> ReadObject(SnapshotSpace space_number);
  Handle<HeapObject> ReadMetaMap();
192 193

  HeapObjectReferenceType GetAndResetNextReferenceType();
194

195 196
  template <typename SlotGetter>
  int ReadRepeatedObject(SlotGetter slot_getter, int repeat_count);
197 198

  // Special handling for serialized code like hooking up internalized strings.
199 200
  void PostProcessNewObject(Handle<Map> map, Handle<HeapObject> obj,
                            SnapshotSpace space);
201 202 203
  void PostProcessNewJSReceiver(Map map, Handle<JSReceiver> obj,
                                JSReceiver raw_obj, InstanceType instance_type,
                                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 215 216

  SnapshotByteSource source_;
  uint32_t magic_number_;

217
  HotObjectsList hot_objects_;
218 219 220 221 222
  std::vector<Handle<Map>> new_maps_;
  std::vector<Handle<AllocationSite>> new_allocation_sites_;
  std::vector<Handle<Code>> new_code_objects_;
  std::vector<Handle<AccessorInfo>> accessor_infos_;
  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 229 230
  // Vector of allocated objects that can be accessed by a backref, by index.
  std::vector<Handle<HeapObject>> back_refs_;

231 232 233 234 235 236
  // Unresolved forward references (registered with kRegisterPendingForwardRef)
  // are collected in order as (object, field offset) pairs. The subsequent
  // forward ref resolution (with kResolvePendingForwardRef) accesses this
  // vector by index.
  //
  // The vector is cleared when there are no more unresolved forward refs.
237
  struct UnresolvedForwardRef {
238
    UnresolvedForwardRef(Handle<HeapObject> object, int offset,
239 240 241
                         HeapObjectReferenceType ref_type)
        : object(object), offset(offset), ref_type(ref_type) {}

242
    Handle<HeapObject> object;
243 244 245 246
    int offset;
    HeapObjectReferenceType ref_type;
  };
  std::vector<UnresolvedForwardRef> unresolved_forward_refs_;
247 248
  int num_unresolved_forward_refs_ = 0;

249
  const bool deserializing_user_code_;
250

251 252
  bool next_reference_is_weak_ = false;

253
  // TODO(6593): generalize rehashing, and remove this flag.
254
  const bool should_rehash_;
255
  std::vector<Handle<HeapObject>> to_rehash_;
256

257 258
#ifdef DEBUG
  uint32_t num_api_references_;
259

260 261 262 263
  // Record the previous object allocated for DCHECKs.
  Handle<HeapObject> previous_allocation_obj_;
  int previous_allocation_size_ = 0;
#endif  // DEBUG
264 265
};

266 267 268 269 270
extern template class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
    Deserializer<Isolate>;
extern template class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
    Deserializer<LocalIsolate>;

271 272 273 274 275
enum class DeserializingUserCodeOption {
  kNotDeserializingUserCode,
  kIsDeserializingUserCode
};

276
// Used to insert a deserialized internalized string into the string table.
277
class StringTableInsertionKey final : public StringTableKey {
278
 public:
279 280 281 282 283 284
  explicit StringTableInsertionKey(
      Isolate* isolate, Handle<String> string,
      DeserializingUserCodeOption deserializing_user_code);
  explicit StringTableInsertionKey(
      LocalIsolate* isolate, Handle<String> string,
      DeserializingUserCodeOption deserializing_user_code);
285

286 287
  template <typename IsolateT>
  bool IsMatch(IsolateT* isolate, String string);
288

289
  void PrepareForInsertion(Isolate* isolate) {
290 291 292 293 294 295
    // When sharing the string table, all string table lookups during snapshot
    // deserialization are hits.
    DCHECK(isolate->OwnsStringTable() ||
           deserializing_user_code_ ==
               DeserializingUserCodeOption::kIsDeserializingUserCode);
  }
296 297
  void PrepareForInsertion(LocalIsolate* isolate) {}
  V8_WARN_UNUSED_RESULT Handle<String> GetHandleForInsertion() {
298 299
    return string_;
  }
300 301

 private:
302
  Handle<String> string_;
303 304 305
#ifdef DEBUG
  DeserializingUserCodeOption deserializing_user_code_;
#endif
306
  DISALLOW_GARBAGE_COLLECTION(no_gc)
307 308
};

309 310 311 312
}  // namespace internal
}  // namespace v8

#endif  // V8_SNAPSHOT_DESERIALIZER_H_