serializer-common.h 10.7 KB
Newer Older
1 2 3 4 5 6 7 8
// 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_SERIALIZER_COMMON_H_
#define V8_SNAPSHOT_SERIALIZER_COMMON_H_

#include "src/address-map.h"
9
#include "src/base/bits.h"
10
#include "src/external-reference-table.h"
11
#include "src/globals.h"
12
#include "src/utils.h"
13
#include "src/visitors.h"
14 15 16 17

namespace v8 {
namespace internal {

18
class CallHandlerInfo;
19 20 21 22
class Isolate;

class ExternalReferenceEncoder {
 public:
23 24 25
  class Value {
   public:
    explicit Value(uint32_t raw) : value_(raw) {}
26
    Value() : value_(0) {}
27 28 29 30 31 32 33 34 35 36 37 38 39
    static uint32_t Encode(uint32_t index, bool is_from_api) {
      return Index::encode(index) | IsFromAPI::encode(is_from_api);
    }

    bool is_from_api() const { return IsFromAPI::decode(value_); }
    uint32_t index() const { return Index::decode(value_); }

   private:
    class Index : public BitField<uint32_t, 0, 31> {};
    class IsFromAPI : public BitField<bool, 31, 1> {};
    uint32_t value_;
  };

40
  explicit ExternalReferenceEncoder(Isolate* isolate);
41
  ~ExternalReferenceEncoder();
42

43
  Value Encode(Address key);
44
  Maybe<Value> TryEncode(Address key);
45 46 47 48

  const char* NameOfAddress(Isolate* isolate, Address address) const;

 private:
49
  AddressToIndexHashMap* map_;
50

51
#ifdef DEBUG
52
  std::vector<int> count_;
53
  const intptr_t* api_references_;
54
#endif  // DEBUG
55 56 57 58 59 60 61

  DISALLOW_COPY_AND_ASSIGN(ExternalReferenceEncoder);
};

class HotObjectsList {
 public:
  HotObjectsList() : index_(0) {
62
    for (int i = 0; i < kSize; i++) circular_queue_[i] = nullptr;
63 64 65
  }

  void Add(HeapObject* object) {
66
    DCHECK(!AllowHeapAllocation::IsAllowed());
67 68 69 70 71
    circular_queue_[index_] = object;
    index_ = (index_ + 1) & kSizeMask;
  }

  HeapObject* Get(int index) {
72
    DCHECK(!AllowHeapAllocation::IsAllowed());
73 74 75 76 77 78 79
    DCHECK_NOT_NULL(circular_queue_[index]);
    return circular_queue_[index];
  }

  static const int kNotFound = -1;

  int Find(HeapObject* object) {
80
    DCHECK(!AllowHeapAllocation::IsAllowed());
81 82 83 84 85 86 87 88 89
    for (int i = 0; i < kSize; i++) {
      if (circular_queue_[i] == object) return i;
    }
    return kNotFound;
  }

  static const int kSize = 8;

 private:
90
  static_assert(base::bits::IsPowerOfTwo(kSize), "kSize must be power of two");
91 92 93 94 95 96 97 98 99 100
  static const int kSizeMask = kSize - 1;
  HeapObject* circular_queue_[kSize];
  int index_;

  DISALLOW_COPY_AND_ASSIGN(HotObjectsList);
};

// The Serializer/Deserializer class is a common superclass for Serializer and
// Deserializer which is used to store common constants and methods used by
// both.
101
class SerializerDeserializer : public RootVisitor {
102
 public:
103
  static void Iterate(Isolate* isolate, RootVisitor* visitor);
104 105

  // No reservation for large object space necessary.
106 107 108
  // We also handle map space differenly.
  STATIC_ASSERT(MAP_SPACE == CODE_SPACE + 1);
  static const int kNumberOfPreallocatedSpaces = CODE_SPACE + 1;
109 110 111 112 113
  static const int kNumberOfSpaces = LAST_SPACE + 1;

 protected:
  static bool CanBeDeferred(HeapObject* o);

114 115
  void RestoreExternalReferenceRedirectors(
      const std::vector<AccessorInfo*>& accessor_infos);
116 117
  void RestoreExternalReferenceRedirectors(
      const std::vector<CallHandlerInfo*>& call_handler_infos);
118

119
#define UNUSED_SERIALIZER_BYTE_CODES(V) \
120 121 122 123 124 125 126 127 128 129 130 131 132
  V(0x18)                               \
  V(0x3d)                               \
  V(0x3e)                               \
  V(0x3f)                               \
  V(0x58)                               \
  V(0x59)                               \
  V(0x5a)                               \
  V(0x5b)                               \
  V(0x5c)                               \
  V(0x5d)                               \
  V(0x5e)                               \
  V(0x5f)                               \
  V(0x67)                               \
133 134 135 136 137 138
  V(0x76)                               \
  V(0x78)                               \
  V(0x79)                               \
  V(0x7a)                               \
  V(0x7b)                               \
  V(0x7c)                               \
139
  V(0x7d)
140

141 142 143 144 145
  // ---------- byte code range 0x00..0x7f ----------
  // Byte codes in this range represent Where, HowToCode and WhereToPoint.
  // Where the pointed-to object can be found:
  // The static assert below will trigger when the number of preallocated spaces
  // changed. If that happens, update the bytecode ranges in the comments below.
146
  STATIC_ASSERT(6 == kNumberOfSpaces);
147
  enum Where {
148
    // 0x00..0x05  Allocate new object, in specified space.
149
    kNewObject = 0x00,
150
    // 0x08..0x0d  Reference to previous object from space.
151
    kBackref = 0x08,
152
    // 0x10..0x15  Reference to previous object from space after skip.
153
    kBackrefWithSkip = 0x10,
154 155 156 157 158 159 160 161

    // 0x06        Object in the partial snapshot cache.
    kPartialSnapshotCache = 0x06,
    // 0x07        External reference referenced by id.
    kExternalReference = 0x07,

    // 0x0e        Builtin code referenced by index.
    kBuiltin = 0x0e,
162 163 164 165
    // 0x16       Root array item.
    kRootArray = 0x16,
    // 0x17        Object provided in the attached list.
    kAttachedReference = 0x17,
166 167

    // 0x0f        Misc, see below (incl. 0x2f, 0x4f, 0x6f).
168
    // 0x18..0x1f  Misc, see below (incl. 0x38..0x3f, 0x58..0x5f, 0x78..0x7f).
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
  };

  static const int kWhereMask = 0x1f;
  static const int kSpaceMask = 7;
  STATIC_ASSERT(kNumberOfSpaces <= kSpaceMask + 1);

  // How to code the pointer to the object.
  enum HowToCode {
    // Straight pointer.
    kPlain = 0,
    // A pointer inlined in code. What this means depends on the architecture.
    kFromCode = 0x20
  };

  static const int kHowToCodeMask = 0x20;

  // Where to point within the object.
  enum WhereToPoint {
    // Points to start of object
    kStartOfObject = 0,
    // Points to instruction in code object or payload of cell.
    kInnerPointer = 0x40
  };

  static const int kWhereToPointMask = 0x40;

  // ---------- Misc ----------
  // Skip.
197
  static const int kSkip = 0x0f;
198
  // Do nothing, used for padding.
199
  static const int kNop = 0x2f;
200
  // Move to next reserved chunk.
201
  static const int kNextChunk = 0x4f;
202
  // Deferring object content.
203
  static const int kDeferred = 0x6f;
204 205
  // Alignment prefixes 0x19..0x1b
  static const int kAlignmentPrefix = 0x19;
206 207 208 209 210
  // 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.
211
  static const int kSynchronize = 0x1c;
212
  // Repeats of variable length.
213
  static const int kVariableRepeat = 0x1d;
214
  // Raw data of variable length.
215 216

  // Used for embedder-allocated backing stores for TypedArrays.
217
  static const int kOffHeapBackingStore = 0x1e;
218

219 220
  // Used for embedder-provided serialization data for embedder fields.
  static const int kEmbedderFieldsData = 0x1f;
221

222
  // Used to encode external referenced provided through the API.
223 224 225 226 227 228 229 230 231 232
  static const int kApiReference = 0x38;

  static const int kVariableRawCode = 0x39;
  static const int kVariableRawData = 0x3a;

  static const int kInternalReference = 0x3b;
  static const int kInternalReferenceEncoded = 0x3c;

  // In-place weak references
  static const int kWeakPrefix = 0x7e;
233

234 235 236
  // Encodes an off-heap instruction stream target.
  static const int kOffHeapTarget = 0x7f;

237 238 239 240 241 242 243 244 245 246 247
  // ---------- byte code range 0x80..0xff ----------
  // First 32 root array items.
  static const int kNumberOfRootArrayConstants = 0x20;
  // 0x80..0x9f
  static const int kRootArrayConstants = 0x80;
  // 0xa0..0xbf
  static const int kRootArrayConstantsWithSkip = 0xa0;
  static const int kRootArrayConstantsMask = 0x1f;

  // 32 common raw data lengths.
  static const int kNumberOfFixedRawData = 0x20;
248 249
  // 0xc0..0xdf
  static const int kFixedRawData = 0xc0;
250 251 252 253 254
  static const int kOnePointerRawData = kFixedRawData;
  static const int kFixedRawDataStart = kFixedRawData - 1;

  // 16 repeats lengths.
  static const int kNumberOfFixedRepeat = 0x10;
255 256
  // 0xe0..0xef
  static const int kFixedRepeat = 0xe0;
257 258
  static const int kFixedRepeatStart = kFixedRepeat - 1;

259 260 261 262 263 264 265 266
  // 8 hot (recently seen or back-referenced) objects with optional skip.
  static const int kNumberOfHotObjects = 8;
  STATIC_ASSERT(kNumberOfHotObjects == HotObjectsList::kSize);
  // 0xf0..0xf7
  static const int kHotObject = 0xf0;
  // 0xf8..0xff
  static const int kHotObjectWithSkip = 0xf8;
  static const int kHotObjectMask = 0x07;
267

268 269 270 271 272 273 274 275 276 277 278 279 280 281
  // ---------- special values ----------
  static const int kAnyOldSpace = -1;

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

  // ---------- member variable ----------
  HotObjectsList hot_objects_;
};

class SerializedData {
 public:
  class Reservation {
   public:
282
    Reservation() : reservation_(0) {}
283 284 285 286 287 288 289 290 291 292 293 294 295 296
    explicit Reservation(uint32_t size)
        : reservation_(ChunkSizeBits::encode(size)) {}

    uint32_t chunk_size() const { return ChunkSizeBits::decode(reservation_); }
    bool is_last() const { return IsLastChunkBits::decode(reservation_); }

    void mark_as_last() { reservation_ |= IsLastChunkBits::encode(true); }

   private:
    uint32_t reservation_;
  };

  SerializedData(byte* data, int size)
      : data_(data), size_(size), owns_data_(false) {}
297
  SerializedData() : data_(nullptr), size_(0), owns_data_(false) {}
298 299 300 301 302
  SerializedData(SerializedData&& other)
      : data_(other.data_), size_(other.size_), owns_data_(other.owns_data_) {
    // Ensure |other| will not attempt to destroy our data in destructor.
    other.owns_data_ = false;
  }
303

304
  virtual ~SerializedData() {
305 306 307 308 309 310 311 312 313
    if (owns_data_) DeleteArray<byte>(data_);
  }

  uint32_t GetMagicNumber() const { return GetHeaderValue(kMagicNumberOffset); }

  class ChunkSizeBits : public BitField<uint32_t, 0, 31> {};
  class IsLastChunkBits : public BitField<bool, 31, 1> {};

  static uint32_t ComputeMagicNumber(ExternalReferenceTable* table) {
314
    uint32_t external_refs = table->size();
315 316
    return 0xC0DE0000 ^ external_refs;
  }
317

318
  static const uint32_t kMagicNumberOffset = 0;
319 320

 protected:
321
  void SetHeaderValue(uint32_t offset, uint32_t value) {
322
    WriteLittleEndianValue(reinterpret_cast<Address>(data_) + offset, value);
323 324
  }

325
  uint32_t GetHeaderValue(uint32_t offset) const {
326 327
    return ReadLittleEndianValue<uint32_t>(reinterpret_cast<Address>(data_) +
                                           offset);
328 329
  }

330
  void AllocateData(uint32_t size);
331

332
  static uint32_t ComputeMagicNumber(Isolate* isolate);
333 334 335 336 337 338

  void SetMagicNumber(Isolate* isolate) {
    SetHeaderValue(kMagicNumberOffset, ComputeMagicNumber(isolate));
  }

  byte* data_;
339
  uint32_t size_;
340
  bool owns_data_;
341 342 343

 private:
  DISALLOW_COPY_AND_ASSIGN(SerializedData);
344 345 346 347 348 349
};

}  // namespace internal
}  // namespace v8

#endif  // V8_SNAPSHOT_SERIALIZER_COMMON_H_