V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
serializer-common.h
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_SERIALIZER_COMMON_H_
6 #define V8_SNAPSHOT_SERIALIZER_COMMON_H_
7 
8 #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/msan.h"
13 #include "src/snapshot/references.h"
14 #include "src/v8memory.h"
15 #include "src/visitors.h"
16 
17 namespace v8 {
18 namespace internal {
19 
20 class CallHandlerInfo;
21 class Isolate;
22 
24  public:
25  class Value {
26  public:
27  explicit Value(uint32_t raw) : value_(raw) {}
28  Value() : value_(0) {}
29  static uint32_t Encode(uint32_t index, bool is_from_api) {
30  return Index::encode(index) | IsFromAPI::encode(is_from_api);
31  }
32 
33  bool is_from_api() const { return IsFromAPI::decode(value_); }
34  uint32_t index() const { return Index::decode(value_); }
35 
36  private:
37  class Index : public BitField<uint32_t, 0, 31> {};
38  class IsFromAPI : public BitField<bool, 31, 1> {};
39  uint32_t value_;
40  };
41 
42  explicit ExternalReferenceEncoder(Isolate* isolate);
43  ~ExternalReferenceEncoder(); // NOLINT (modernize-use-equals-default)
44 
45  Value Encode(Address key);
46  Maybe<Value> TryEncode(Address key);
47 
48  const char* NameOfAddress(Isolate* isolate, Address address) const;
49 
50  private:
52 
53 #ifdef DEBUG
54  std::vector<int> count_;
55  const intptr_t* api_references_;
56 #endif // DEBUG
57 
58  DISALLOW_COPY_AND_ASSIGN(ExternalReferenceEncoder);
59 };
60 
62  public:
63  HotObjectsList() : index_(0) {
64  for (int i = 0; i < kSize; i++) circular_queue_[i] = nullptr;
65  }
66 
67  void Add(HeapObject* object) {
68  DCHECK(!AllowHeapAllocation::IsAllowed());
69  circular_queue_[index_] = object;
70  index_ = (index_ + 1) & kSizeMask;
71  }
72 
73  HeapObject* Get(int index) {
74  DCHECK(!AllowHeapAllocation::IsAllowed());
75  DCHECK_NOT_NULL(circular_queue_[index]);
76  return circular_queue_[index];
77  }
78 
79  static const int kNotFound = -1;
80 
81  int Find(HeapObject* object) {
82  DCHECK(!AllowHeapAllocation::IsAllowed());
83  for (int i = 0; i < kSize; i++) {
84  if (circular_queue_[i] == object) return i;
85  }
86  return kNotFound;
87  }
88 
89  static const int kSize = 8;
90 
91  private:
92  static_assert(base::bits::IsPowerOfTwo(kSize), "kSize must be power of two");
93  static const int kSizeMask = kSize - 1;
94  HeapObject* circular_queue_[kSize];
95  int index_;
96 
97  DISALLOW_COPY_AND_ASSIGN(HotObjectsList);
98 };
99 
100 // The Serializer/Deserializer class is a common superclass for Serializer and
101 // Deserializer which is used to store common constants and methods used by
102 // both.
104  public:
105  static void Iterate(Isolate* isolate, RootVisitor* visitor);
106 
107  // No reservation for large object space necessary.
108  // We also handle map space differenly.
109  STATIC_ASSERT(MAP_SPACE == CODE_SPACE + 1);
110 
111  // We do not support young generation large objects and large code objects.
112  STATIC_ASSERT(LAST_SPACE == NEW_LO_SPACE);
113  STATIC_ASSERT(LAST_SPACE - 2 == LO_SPACE);
114  static const int kNumberOfPreallocatedSpaces = CODE_SPACE + 1;
115 
116  // The number of spaces supported by the serializer. Spaces after LO_SPACE
117  // (NEW_LO_SPACE and CODE_LO_SPACE) are not supported.
118  static const int kNumberOfSpaces = LO_SPACE + 1;
119 
120  protected:
121  static bool CanBeDeferred(HeapObject* o);
122 
123  void RestoreExternalReferenceRedirectors(
124  const std::vector<AccessorInfo*>& accessor_infos);
125  void RestoreExternalReferenceRedirectors(
126  const std::vector<CallHandlerInfo*>& call_handler_infos);
127 
128 #define UNUSED_SERIALIZER_BYTE_CODES(V) \
129  V(0x0e) \
130  V(0x2e) \
131  V(0x3e) \
132  V(0x3f) \
133  V(0x4e) \
134  V(0x58) \
135  V(0x59) \
136  V(0x5a) \
137  V(0x5b) \
138  V(0x5c) \
139  V(0x5d) \
140  V(0x5e) \
141  V(0x5f) \
142  V(0x67) \
143  V(0x6e) \
144  V(0x76) \
145  V(0x79) \
146  V(0x7a) \
147  V(0x7b) \
148  V(0x7c)
149 
150  // ---------- byte code range 0x00..0x7f ----------
151  // Byte codes in this range represent Where, HowToCode and WhereToPoint.
152  // Where the pointed-to object can be found:
153  // The static assert below will trigger when the number of preallocated spaces
154  // changed. If that happens, update the bytecode ranges in the comments below.
155  STATIC_ASSERT(6 == kNumberOfSpaces);
156  enum Where {
157  // 0x00..0x05 Allocate new object, in specified space.
158  kNewObject = 0x00,
159  // 0x08..0x0d Reference to previous object from space.
160  kBackref = 0x08,
161  // 0x10..0x15 Reference to previous object from space after skip.
162  kBackrefWithSkip = 0x10,
163 
164  // 0x06 Object in the partial snapshot cache.
165  kPartialSnapshotCache = 0x06,
166  // 0x07 External reference referenced by id.
167  kExternalReference = 0x07,
168 
169  // 0x16 Root array item.
170  kRootArray = 0x16,
171  // 0x17 Object provided in the attached list.
172  kAttachedReference = 0x17,
173  // 0x18 Object in the read-only object cache.
174  kReadOnlyObjectCache = 0x18,
175 
176  // 0x0f Misc, see below (incl. 0x2f, 0x4f, 0x6f).
177  // 0x18..0x1f Misc, see below (incl. 0x38..0x3f, 0x58..0x5f, 0x78..0x7f).
178  };
179 
180  static const int kWhereMask = 0x1f;
181  static const int kSpaceMask = 7;
182  STATIC_ASSERT(kNumberOfSpaces <= kSpaceMask + 1);
183 
184  // How to code the pointer to the object.
185  enum HowToCode {
186  // Straight pointer.
187  kPlain = 0,
188  // A pointer inlined in code. What this means depends on the architecture.
189  kFromCode = 0x20
190  };
191 
192  static const int kHowToCodeMask = 0x20;
193 
194  // Where to point within the object.
195  enum WhereToPoint {
196  // Points to start of object
197  kStartOfObject = 0,
198  // Points to instruction in code object or payload of cell.
199  kInnerPointer = 0x40
200  };
201 
202  static const int kWhereToPointMask = 0x40;
203 
204  // ---------- Misc ----------
205  // Skip.
206  static const int kSkip = 0x0f;
207  // Do nothing, used for padding.
208  static const int kNop = 0x2f;
209  // Move to next reserved chunk.
210  static const int kNextChunk = 0x4f;
211  // Deferring object content.
212  static const int kDeferred = 0x6f;
213  // Alignment prefixes 0x19..0x1b
214  static const int kAlignmentPrefix = 0x19;
215  // A tag emitted at strategic points in the snapshot to delineate sections.
216  // If the deserializer does not find these at the expected moments then it
217  // is an indication that the snapshot and the VM do not fit together.
218  // Examine the build process for architecture, version or configuration
219  // mismatches.
220  static const int kSynchronize = 0x1c;
221  // Repeats of variable length.
222  static const int kVariableRepeat = 0x1d;
223  // Raw data of variable length.
224 
225  // Used for embedder-allocated backing stores for TypedArrays.
226  static const int kOffHeapBackingStore = 0x1e;
227 
228  // Used for embedder-provided serialization data for embedder fields.
229  static const int kEmbedderFieldsData = 0x1f;
230 
231  static const int kVariableRawCode = 0x39;
232  static const int kVariableRawData = 0x3a;
233 
234  static const int kInternalReference = 0x3b;
235  static const int kInternalReferenceEncoded = 0x3c;
236 
237  // Used to encode external references provided through the API.
238  static const int kApiReference = 0x3d;
239 
240  // In-place weak references
241  static const int kClearedWeakReference = 0x7d;
242  static const int kWeakPrefix = 0x7e;
243 
244  // Encodes an off-heap instruction stream target.
245  static const int kOffHeapTarget = 0x7f;
246 
247  // ---------- byte code range 0x80..0xff ----------
248  // First 32 root array items.
249  static const int kNumberOfRootArrayConstants = 0x20;
250  // 0x80..0x9f
251  static const int kRootArrayConstants = 0x80;
252  // 0xa0..0xbf
253  static const int kRootArrayConstantsWithSkip = 0xa0;
254  static const int kRootArrayConstantsMask = 0x1f;
255 
256  // 32 common raw data lengths.
257  static const int kNumberOfFixedRawData = 0x20;
258  // 0xc0..0xdf
259  static const int kFixedRawData = 0xc0;
260  static const int kOnePointerRawData = kFixedRawData;
261  static const int kFixedRawDataStart = kFixedRawData - 1;
262 
263  // 16 repeats lengths.
264  static const int kNumberOfFixedRepeat = 0x10;
265  // 0xe0..0xef
266  static const int kFixedRepeat = 0xe0;
267  static const int kFixedRepeatStart = kFixedRepeat - 1;
268 
269  // 8 hot (recently seen or back-referenced) objects with optional skip.
270  static const int kNumberOfHotObjects = 8;
271  STATIC_ASSERT(kNumberOfHotObjects == HotObjectsList::kSize);
272  // 0xf0..0xf7
273  static const int kHotObject = 0xf0;
274  // 0xf8..0xff
275  static const int kHotObjectWithSkip = 0xf8;
276  static const int kHotObjectMask = 0x07;
277 
278  // ---------- special values ----------
279  static const int kAnyOldSpace = -1;
280 
281  // Sentinel after a new object to indicate that double alignment is needed.
282  static const int kDoubleAlignmentSentinel = 0;
283 
284  // ---------- member variable ----------
285  HotObjectsList hot_objects_;
286 };
287 
289  public:
290  class Reservation {
291  public:
292  Reservation() : reservation_(0) {}
293  explicit Reservation(uint32_t size)
294  : reservation_(ChunkSizeBits::encode(size)) {}
295 
296  uint32_t chunk_size() const { return ChunkSizeBits::decode(reservation_); }
297  bool is_last() const { return IsLastChunkBits::decode(reservation_); }
298 
299  void mark_as_last() { reservation_ |= IsLastChunkBits::encode(true); }
300 
301  private:
302  uint32_t reservation_;
303  };
304 
305  SerializedData(byte* data, int size)
306  : data_(data), size_(size), owns_data_(false) {}
307  SerializedData() : data_(nullptr), size_(0), owns_data_(false) {}
308  SerializedData(SerializedData&& other) V8_NOEXCEPT
309  : data_(other.data_),
310  size_(other.size_),
311  owns_data_(other.owns_data_) {
312  // Ensure |other| will not attempt to destroy our data in destructor.
313  other.owns_data_ = false;
314  }
315 
316  virtual ~SerializedData() {
317  if (owns_data_) DeleteArray<byte>(data_);
318  }
319 
320  uint32_t GetMagicNumber() const { return GetHeaderValue(kMagicNumberOffset); }
321 
322  class ChunkSizeBits : public BitField<uint32_t, 0, 31> {};
323  class IsLastChunkBits : public BitField<bool, 31, 1> {};
324 
325  static uint32_t ComputeMagicNumber(ExternalReferenceTable* table) {
326  uint32_t external_refs = table->size();
327  return 0xC0DE0000 ^ external_refs;
328  }
329 
330  static const uint32_t kMagicNumberOffset = 0;
331 
332  protected:
333  void SetHeaderValue(uint32_t offset, uint32_t value) {
334  WriteLittleEndianValue(reinterpret_cast<Address>(data_) + offset, value);
335  }
336 
337  uint32_t GetHeaderValue(uint32_t offset) const {
338  return ReadLittleEndianValue<uint32_t>(reinterpret_cast<Address>(data_) +
339  offset);
340  }
341 
342  void AllocateData(uint32_t size);
343 
344  static uint32_t ComputeMagicNumber(Isolate* isolate);
345 
346  void SetMagicNumber(Isolate* isolate) {
347  SetHeaderValue(kMagicNumberOffset, ComputeMagicNumber(isolate));
348  }
349 
350  byte* data_;
351  uint32_t size_;
352  bool owns_data_;
353 
354  private:
355  DISALLOW_COPY_AND_ASSIGN(SerializedData);
356 };
357 
358 class Checksum {
359  public:
360  explicit Checksum(Vector<const byte> payload) {
361 #ifdef MEMORY_SANITIZER
362  // Computing the checksum includes padding bytes for objects like strings.
363  // Mark every object as initialized in the code serializer.
364  MSAN_MEMORY_IS_INITIALIZED(payload.start(), payload.length());
365 #endif // MEMORY_SANITIZER
366  // Fletcher's checksum. Modified to reduce 64-bit sums to 32-bit.
367  uintptr_t a = 1;
368  uintptr_t b = 0;
369  const uintptr_t* cur = reinterpret_cast<const uintptr_t*>(payload.start());
370  DCHECK(IsAligned(payload.length(), kIntptrSize));
371  const uintptr_t* end = cur + payload.length() / kIntptrSize;
372  while (cur < end) {
373  // Unsigned overflow expected and intended.
374  a += *cur++;
375  b += a;
376  }
377 #if V8_HOST_ARCH_64_BIT
378  a ^= a >> 32;
379  b ^= b >> 32;
380 #endif // V8_HOST_ARCH_64_BIT
381  a_ = static_cast<uint32_t>(a);
382  b_ = static_cast<uint32_t>(b);
383  }
384 
385  bool Check(uint32_t a, uint32_t b) const { return a == a_ && b == b_; }
386 
387  uint32_t a() const { return a_; }
388  uint32_t b() const { return b_; }
389 
390  private:
391  uint32_t a_;
392  uint32_t b_;
393 
394  DISALLOW_COPY_AND_ASSIGN(Checksum);
395 };
396 
397 } // namespace internal
398 } // namespace v8
399 
400 #endif // V8_SNAPSHOT_SERIALIZER_COMMON_H_
Definition: v8.h:56
Definition: libplatform.h:13