serializer-deserializer.h 11 KB
Newer Older
1
// Copyright 2020 the V8 project authors. All rights reserved.
2 3 4
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6
#ifndef V8_SNAPSHOT_SERIALIZER_DESERIALIZER_H_
#define V8_SNAPSHOT_SERIALIZER_DESERIALIZER_H_
7

8
#include "src/objects/visitors.h"
9
#include "src/snapshot/references.h"
10 11 12 13

namespace v8 {
namespace internal {

14
class CallHandlerInfo;
15 16
class Isolate;

17 18 19 20
// The Serializer/Deserializer class is a common superclass for Serializer and
// Deserializer which is used to store common constants and methods used by
// both.
class SerializerDeserializer : public RootVisitor {
21
 public:
22
  static void Iterate(Isolate* isolate, RootVisitor* visitor);
23

24 25 26 27
 protected:
  class HotObjectsList {
   public:
    HotObjectsList() = default;
28

29 30 31 32 33
    void Add(HeapObject object) {
      DCHECK(!AllowHeapAllocation::IsAllowed());
      circular_queue_[index_] = object;
      index_ = (index_ + 1) & kSizeMask;
    }
34

35 36 37 38 39
    HeapObject Get(int index) {
      DCHECK(!AllowHeapAllocation::IsAllowed());
      DCHECK(!circular_queue_[index].is_null());
      return circular_queue_[index];
    }
40

41
    static const int kNotFound = -1;
42

43 44 45 46 47 48
    int Find(HeapObject object) {
      DCHECK(!AllowHeapAllocation::IsAllowed());
      for (int i = 0; i < kSize; i++) {
        if (circular_queue_[i] == object) return i;
      }
      return kNotFound;
49 50
    }

51
    static const int kSize = 8;
52

53 54 55 56 57
   private:
    STATIC_ASSERT(base::bits::IsPowerOfTwo(kSize));
    static const int kSizeMask = kSize - 1;
    HeapObject circular_queue_[kSize];
    int index_ = 0;
58

59 60
    DISALLOW_COPY_AND_ASSIGN(HotObjectsList);
  };
61

62
  static bool CanBeDeferred(HeapObject o);
63

64
  void RestoreExternalReferenceRedirectors(
65
      Isolate* isolate, const std::vector<AccessorInfo>& accessor_infos);
66
  void RestoreExternalReferenceRedirectors(
67
      Isolate* isolate, const std::vector<CallHandlerInfo>& call_handler_infos);
68

69 70 71
  static const int kNumberOfSpaces =
      static_cast<int>(SnapshotSpace::kNumberOfSpaces);

72 73
// clang-format off
#define UNUSED_SERIALIZER_BYTE_CODES(V)                           \
74
  V(0x05) V(0x06) V(0x07) V(0x0d) V(0x0e) V(0x0f)                 \
75 76
  /* Free range 0x2a..0x2f */                                     \
  V(0x2a) V(0x2b) V(0x2c) V(0x2d) V(0x2e) V(0x2f)                 \
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
  /* Free range 0x30..0x3f */                                     \
  V(0x30) V(0x31) V(0x32) V(0x33) V(0x34) V(0x35) V(0x36) V(0x37) \
  V(0x38) V(0x39) V(0x3a) V(0x3b) V(0x3c) V(0x3d) V(0x3e) V(0x3f) \
  /* Free range 0x97..0x9f */                                     \
  V(0x98) V(0x99) V(0x9a) V(0x9b) V(0x9c) V(0x9d) V(0x9e) V(0x9f) \
  /* Free range 0xa0..0xaf */                                     \
  V(0xa0) V(0xa1) V(0xa2) V(0xa3) V(0xa4) V(0xa5) V(0xa6) V(0xa7) \
  V(0xa8) V(0xa9) V(0xaa) V(0xab) V(0xac) V(0xad) V(0xae) V(0xaf) \
  /* Free range 0xb0..0xbf */                                     \
  V(0xb0) V(0xb1) V(0xb2) V(0xb3) V(0xb4) V(0xb5) V(0xb6) V(0xb7) \
  V(0xb8) V(0xb9) V(0xba) V(0xbb) V(0xbc) V(0xbd) V(0xbe) V(0xbf) \
  /* Free range 0xc0..0xcf */                                     \
  V(0xc0) V(0xc1) V(0xc2) V(0xc3) V(0xc4) V(0xc5) V(0xc6) V(0xc7) \
  V(0xc8) V(0xc9) V(0xca) V(0xcb) V(0xcc) V(0xcd) V(0xce) V(0xcf) \
  /* Free range 0xd0..0xdf */                                     \
  V(0xd0) V(0xd1) V(0xd2) V(0xd3) V(0xd4) V(0xd5) V(0xd6) V(0xd7) \
  V(0xd8) V(0xd9) V(0xda) V(0xdb) V(0xdc) V(0xdd) V(0xde) V(0xdf) \
  /* Free range 0xe0..0xef */                                     \
  V(0xe0) V(0xe1) V(0xe2) V(0xe3) V(0xe4) V(0xe5) V(0xe6) V(0xe7) \
  V(0xe8) V(0xe9) V(0xea) V(0xeb) V(0xec) V(0xed) V(0xee) V(0xef) \
  /* Free range 0xf0..0xff */                                     \
  V(0xf0) V(0xf1) V(0xf2) V(0xf3) V(0xf4) V(0xf5) V(0xf6) V(0xf7) \
  V(0xf8) V(0xf9) V(0xfa) V(0xfb) V(0xfc) V(0xfd) V(0xfe) V(0xff)
  // clang-format on

102
  // The static assert below will trigger when the number of preallocated spaces
103 104
  // changed. If that happens, update the kNewObject and kBackref bytecode
  // ranges in the comments below.
105
  STATIC_ASSERT(5 == kNumberOfSpaces);
106 107

  // First 32 root array items.
108
  static const int kRootArrayConstantsCount = 0x20;
109 110

  // 32 common raw data lengths.
111
  static const int kFixedRawDataCount = 0x20;
112
  // 16 repeats lengths.
113
  static const int kFixedRepeatCount = 0x10;
114

115
  // 8 hot (recently seen or back-referenced) objects with optional skip.
116 117
  static const int kHotObjectCount = 8;
  STATIC_ASSERT(kHotObjectCount == HotObjectsList::kSize);
118

119 120 121 122
  // 3 alignment prefixes
  static const int kAlignmentPrefixCount = 3;

  enum Bytecode : byte {
123 124 125 126
    //
    // ---------- byte code range 0x00..0x0f ----------
    //

127
    // 0x00..0x04  Allocate new object, in specified space.
128
    kNewObject = 0x00,
129
    // 0x08..0x0c  Reference to previous object from specified space.
130 131 132
    kBackref = 0x08,

    //
133
    // ---------- byte code range 0x10..0x27 ----------
134 135
    //

136 137
    // Object in the startup object cache.
    kStartupObjectCache = 0x10,
138 139 140 141 142 143 144 145 146 147
    // Root array item.
    kRootArray,
    // Object provided in the attached list.
    kAttachedReference,
    // Object in the read-only object cache.
    kReadOnlyObjectCache,
    // Do nothing, used for padding.
    kNop,
    // Move to next reserved chunk.
    kNextChunk,
148 149
    // 3 alignment prefixes 0x16..0x18
    kAlignmentPrefix = 0x16,
150 151 152 153 154
    // A tag emitted at strategic points in the snapshot to delineate sections.
    // If the deserializer does not find these at the expected moments then it
    // is an indication that the snapshot and the VM do not fit together.
    // Examine the build process for architecture, version or configuration
    // mismatches.
155
    kSynchronize = 0x19,
156 157 158 159 160 161 162 163 164 165 166 167 168
    // Repeats of variable length.
    kVariableRepeat,
    // Used for embedder-allocated backing stores for TypedArrays.
    kOffHeapBackingStore,
    // Used for embedder-provided serialization data for embedder fields.
    kEmbedderFieldsData,
    // Raw data of variable length.
    kVariableRawCode,
    kVariableRawData,
    // Used to encode external references provided through the API.
    kApiReference,
    // External reference referenced by id.
    kExternalReference,
169 170 171 172 173 174
    // Same as two bytecodes above but for serializing sandboxed external
    // pointer values.
    // TODO(v8:10391): Remove them once all ExternalPointer usages are
    // sandbox-ready.
    kSandboxedApiReference,
    kSandboxedExternalReference,
175 176 177 178 179 180 181
    // Internal reference of a code objects in code stream.
    kInternalReference,
    // In-place weak references.
    kClearedWeakReference,
    kWeakPrefix,
    // Encodes an off-heap instruction stream target.
    kOffHeapTarget,
182 183 184 185 186 187 188 189 190 191 192 193 194
    // Registers the current slot as a "pending" forward reference, to be later
    // filled by a corresponding resolution bytecode.
    kRegisterPendingForwardRef,
    // Resolves an existing "pending" forward reference to point to the current
    // object.
    kResolvePendingForwardRef,
    // Special construction bytecode for the metamap. In theory we could re-use
    // forward-references for this, but then the forward reference would be
    // registered during object map deserialization, before the object is
    // allocated, so there wouldn't be a allocated object whose map field we can
    // register as the pending field. We could either hack around this, or
    // simply introduce this new bytecode.
    kNewMetaMap,
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216

    //
    // ---------- byte code range 0x40..0x7f ----------
    //

    // 0x40..0x5f
    kRootArrayConstants = 0x40,

    // 0x60..0x7f
    kFixedRawData = 0x60,

    //
    // ---------- byte code range 0x80..0x9f ----------
    //

    // 0x80..0x8f
    kFixedRepeat = 0x80,

    // 0x90..0x97
    kHotObject = 0x90,
  };

217
  // Helper class for encoding and decoding a value into and from a bytecode.
218 219 220 221 222 223 224 225
  //
  // The value is encoded by allocating an entire bytecode range, and encoding
  // the value as an index in that range, starting at kMinValue; thus the range
  // of values
  //   [kMinValue, kMinValue + 1, ... , kMaxValue]
  // is encoded as
  //   [kBytecode, kBytecode + 1, ... , kBytecode + (N - 1)]
  // where N is the number of values, i.e. kMaxValue - kMinValue + 1.
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
  template <Bytecode kBytecode, int kMinValue, int kMaxValue,
            typename TValue = int>
  struct BytecodeValueEncoder {
    STATIC_ASSERT((kBytecode + kMaxValue - kMinValue) <= kMaxUInt8);

    static constexpr bool IsEncodable(TValue value) {
      return base::IsInRange(static_cast<int>(value), kMinValue, kMaxValue);
    }

    static constexpr byte Encode(TValue value) {
      CONSTEXPR_DCHECK(IsEncodable(value));
      return static_cast<byte>(kBytecode + static_cast<int>(value) - kMinValue);
    }

    static constexpr TValue Decode(byte bytecode) {
      CONSTEXPR_DCHECK(base::IsInRange(bytecode,
                                       Encode(static_cast<TValue>(kMinValue)),
                                       Encode(static_cast<TValue>(kMaxValue))));
      return static_cast<TValue>(bytecode - kBytecode + kMinValue);
    }
  };

  template <Bytecode bytecode>
  using SpaceEncoder =
250
      BytecodeValueEncoder<bytecode, 0, kNumberOfSpaces - 1, SnapshotSpace>;
251 252 253

  using NewObject = SpaceEncoder<kNewObject>;
  using BackRef = SpaceEncoder<kBackref>;
254

255 256 257
  //
  // Some other constants.
  //
258
  static const SnapshotSpace kAnyOldSpace = SnapshotSpace::kNumberOfSpaces;
259 260 261 262

  // Sentinel after a new object to indicate that double alignment is needed.
  static const int kDoubleAlignmentSentinel = 0;

263 264 265 266 267
  // Raw data size encoding helpers.
  static const int kFirstEncodableFixedRawDataSize = 1;
  static const int kLastEncodableFixedRawDataSize =
      kFirstEncodableFixedRawDataSize + kFixedRawDataCount - 1;

268 269 270
  using FixedRawDataWithSize =
      BytecodeValueEncoder<kFixedRawData, kFirstEncodableFixedRawDataSize,
                           kLastEncodableFixedRawDataSize>;
271

272 273 274
  // Repeat count encoding helpers.
  static const int kFirstEncodableRepeatCount = 2;
  static const int kLastEncodableFixedRepeatCount =
275
      kFirstEncodableRepeatCount + kFixedRepeatCount - 1;
276 277 278
  static const int kFirstEncodableVariableRepeatCount =
      kLastEncodableFixedRepeatCount + 1;

279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
  using FixedRepeatWithCount =
      BytecodeValueEncoder<kFixedRepeat, kFirstEncodableRepeatCount,
                           kLastEncodableFixedRepeatCount>;

  // Encodes/decodes repeat count into a serialized variable repeat count
  // value.
  struct VariableRepeatCount {
    static constexpr bool IsEncodable(int repeat_count) {
      return repeat_count >= kFirstEncodableVariableRepeatCount;
    }

    static constexpr int Encode(int repeat_count) {
      CONSTEXPR_DCHECK(IsEncodable(repeat_count));
      return repeat_count - kFirstEncodableVariableRepeatCount;
    }

    static constexpr int Decode(int value) {
      return value + kFirstEncodableVariableRepeatCount;
    }
  };

  using RootArrayConstant =
      BytecodeValueEncoder<kRootArrayConstants, 0, kRootArrayConstantsCount - 1,
                           RootIndex>;
  using HotObject = BytecodeValueEncoder<kHotObject, 0, kHotObjectCount - 1>;
304

305 306 307 308 309 310 311
  // ---------- member variable ----------
  HotObjectsList hot_objects_;
};

}  // namespace internal
}  // namespace v8

312
#endif  // V8_SNAPSHOT_SERIALIZER_DESERIALIZER_H_