1// Copyright 2020 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_DESERIALIZER_H_
6#define V8_SNAPSHOT_SERIALIZER_DESERIALIZER_H_
7
8#include "src/common/assert-scope.h"
9#include "src/objects/visitors.h"
10#include "src/snapshot/references.h"
11
12namespace v8 {
13namespace internal {
14
15class CallHandlerInfo;
16class Isolate;
17
18// The Serializer/Deserializer class is a common superclass for Serializer and
19// Deserializer which is used to store common constants and methods used by
20// both.
21class SerializerDeserializer : public RootVisitor {
22 public:
23  static void IterateStartupObjectCache(Isolate* isolate, RootVisitor* visitor);
24
25  static void IterateSharedHeapObjectCache(Isolate* isolate,
26                                           RootVisitor* visitor);
27
28 protected:
29  static bool CanBeDeferred(HeapObject o);
30
31  void RestoreExternalReferenceRedirector(Isolate* isolate,
32                                          AccessorInfo accessor_info);
33  void RestoreExternalReferenceRedirector(Isolate* isolate,
34                                          CallHandlerInfo call_handler_info);
35
36// clang-format off
37#define UNUSED_SERIALIZER_BYTE_CODES(V)                           \
38  /* Free range 0x1e..0x1f */                                     \
39  V(0x1e) V(0x1f)                                         \
40  /* Free range 0x20..0x2f */                                     \
41  V(0x20) V(0x21) V(0x22) V(0x23) V(0x24) V(0x25) V(0x26) V(0x27) \
42  V(0x28) V(0x29) V(0x2a) V(0x2b) V(0x2c) V(0x2d) V(0x2e) V(0x2f) \
43  /* Free range 0x30..0x3f */                                     \
44  V(0x30) V(0x31) V(0x32) V(0x33) V(0x34) V(0x35) V(0x36) V(0x37) \
45  V(0x38) V(0x39) V(0x3a) V(0x3b) V(0x3c) V(0x3d) V(0x3e) V(0x3f) \
46  /* Free range 0x97..0x9f */                                     \
47  V(0x98) V(0x99) V(0x9a) V(0x9b) V(0x9c) V(0x9d) V(0x9e) V(0x9f) \
48  /* Free range 0xa0..0xaf */                                     \
49  V(0xa0) V(0xa1) V(0xa2) V(0xa3) V(0xa4) V(0xa5) V(0xa6) V(0xa7) \
50  V(0xa8) V(0xa9) V(0xaa) V(0xab) V(0xac) V(0xad) V(0xae) V(0xaf) \
51  /* Free range 0xb0..0xbf */                                     \
52  V(0xb0) V(0xb1) V(0xb2) V(0xb3) V(0xb4) V(0xb5) V(0xb6) V(0xb7) \
53  V(0xb8) V(0xb9) V(0xba) V(0xbb) V(0xbc) V(0xbd) V(0xbe) V(0xbf) \
54  /* Free range 0xc0..0xcf */                                     \
55  V(0xc0) V(0xc1) V(0xc2) V(0xc3) V(0xc4) V(0xc5) V(0xc6) V(0xc7) \
56  V(0xc8) V(0xc9) V(0xca) V(0xcb) V(0xcc) V(0xcd) V(0xce) V(0xcf) \
57  /* Free range 0xd0..0xdf */                                     \
58  V(0xd0) V(0xd1) V(0xd2) V(0xd3) V(0xd4) V(0xd5) V(0xd6) V(0xd7) \
59  V(0xd8) V(0xd9) V(0xda) V(0xdb) V(0xdc) V(0xdd) V(0xde) V(0xdf) \
60  /* Free range 0xe0..0xef */                                     \
61  V(0xe0) V(0xe1) V(0xe2) V(0xe3) V(0xe4) V(0xe5) V(0xe6) V(0xe7) \
62  V(0xe8) V(0xe9) V(0xea) V(0xeb) V(0xec) V(0xed) V(0xee) V(0xef) \
63  /* Free range 0xf0..0xff */                                     \
64  V(0xf0) V(0xf1) V(0xf2) V(0xf3) V(0xf4) V(0xf5) V(0xf6) V(0xf7) \
65  V(0xf8) V(0xf9) V(0xfa) V(0xfb) V(0xfc) V(0xfd) V(0xfe) V(0xff)
66  // clang-format on
67
68  // The static assert below will trigger when the number of preallocated spaces
69  // changed. If that happens, update the kNewObject and kBackref bytecode
70  // ranges in the comments below.
71  STATIC_ASSERT(4 == kNumberOfSnapshotSpaces);
72
73  // First 32 root array items.
74  static const int kRootArrayConstantsCount = 0x20;
75
76  // 32 common raw data lengths.
77  static const int kFixedRawDataCount = 0x20;
78  // 16 repeats lengths.
79  static const int kFixedRepeatCount = 0x10;
80
81  // 8 hot (recently seen or back-referenced) objects with optional skip.
82  static const int kHotObjectCount = 8;
83
84  enum Bytecode : byte {
85    //
86    // ---------- byte code range 0x00..0x1d ----------
87    //
88
89    // 0x00..0x03  Allocate new object, in specified space.
90    kNewObject = 0x00,
91    // Reference to previously allocated object.
92    kBackref = 0x04,
93    // Reference to an object in the read only heap.
94    kReadOnlyHeapRef,
95    // Object in the startup object cache.
96    kStartupObjectCache,
97    // Root array item.
98    kRootArray,
99    // Object provided in the attached list.
100    kAttachedReference,
101    // Object in the read-only object cache.
102    kReadOnlyObjectCache,
103    // Object in the shared heap object cache.
104    kSharedHeapObjectCache,
105    // Do nothing, used for padding.
106    kNop,
107    // A tag emitted at strategic points in the snapshot to delineate sections.
108    // If the deserializer does not find these at the expected moments then it
109    // is an indication that the snapshot and the VM do not fit together.
110    // Examine the build process for architecture, version or configuration
111    // mismatches.
112    kSynchronize,
113    // Repeats of variable length.
114    kVariableRepeat,
115    // Used for embedder-allocated backing stores for TypedArrays.
116    kOffHeapBackingStore,
117    kOffHeapResizableBackingStore,
118    // Used for embedder-provided serialization data for embedder fields.
119    kEmbedderFieldsData,
120    // Raw data of variable length.
121    kVariableRawData,
122    // Used to encode external references provided through the API.
123    kApiReference,
124    // External reference referenced by id.
125    kExternalReference,
126    // Same as two bytecodes above but for serializing sandboxed external
127    // pointer values.
128    // TODO(v8:10391): Remove them once all ExternalPointer usages are
129    // sandbox-ready.
130    kSandboxedApiReference,
131    kSandboxedExternalReference,
132    // Internal reference of a code objects in code stream.
133    kInternalReference,
134    // In-place weak references.
135    kClearedWeakReference,
136    kWeakPrefix,
137    // Encodes an off-heap instruction stream target.
138    kOffHeapTarget,
139    // Registers the current slot as a "pending" forward reference, to be later
140    // filled by a corresponding resolution bytecode.
141    kRegisterPendingForwardRef,
142    // Resolves an existing "pending" forward reference to point to the current
143    // object.
144    kResolvePendingForwardRef,
145    // Special construction bytecode for the metamap. In theory we could re-use
146    // forward-references for this, but then the forward reference would be
147    // registered during object map deserialization, before the object is
148    // allocated, so there wouldn't be a allocated object whose map field we can
149    // register as the pending field. We could either hack around this, or
150    // simply introduce this new bytecode.
151    kNewMetaMap,
152    // Special construction bytecode for Code object bodies, which have a more
153    // complex deserialization ordering and RelocInfo processing.
154    kCodeBody,
155
156    //
157    // ---------- byte code range 0x40..0x7f ----------
158    //
159
160    // 0x40..0x5f
161    kRootArrayConstants = 0x40,
162
163    // 0x60..0x7f
164    kFixedRawData = 0x60,
165
166    //
167    // ---------- byte code range 0x80..0x9f ----------
168    //
169
170    // 0x80..0x8f
171    kFixedRepeat = 0x80,
172
173    // 0x90..0x97
174    kHotObject = 0x90,
175  };
176
177  // Helper class for encoding and decoding a value into and from a bytecode.
178  //
179  // The value is encoded by allocating an entire bytecode range, and encoding
180  // the value as an index in that range, starting at kMinValue; thus the range
181  // of values
182  //   [kMinValue, kMinValue + 1, ... , kMaxValue]
183  // is encoded as
184  //   [kBytecode, kBytecode + 1, ... , kBytecode + (N - 1)]
185  // where N is the number of values, i.e. kMaxValue - kMinValue + 1.
186  template <Bytecode kBytecode, int kMinValue, int kMaxValue,
187            typename TValue = int>
188  struct BytecodeValueEncoder {
189    STATIC_ASSERT((kBytecode + kMaxValue - kMinValue) <= kMaxUInt8);
190
191    static constexpr bool IsEncodable(TValue value) {
192      return base::IsInRange(static_cast<int>(value), kMinValue, kMaxValue);
193    }
194
195    static constexpr byte Encode(TValue value) {
196      DCHECK(IsEncodable(value));
197      return static_cast<byte>(kBytecode + static_cast<int>(value) - kMinValue);
198    }
199
200    static constexpr TValue Decode(byte bytecode) {
201      DCHECK(base::IsInRange(bytecode, Encode(static_cast<TValue>(kMinValue)),
202                             Encode(static_cast<TValue>(kMaxValue))));
203      return static_cast<TValue>(bytecode - kBytecode + kMinValue);
204    }
205  };
206
207  template <Bytecode bytecode>
208  using SpaceEncoder =
209      BytecodeValueEncoder<bytecode, 0, kNumberOfSnapshotSpaces - 1,
210                           SnapshotSpace>;
211
212  using NewObject = SpaceEncoder<kNewObject>;
213
214  //
215  // Some other constants.
216  //
217
218  // Sentinel after a new object to indicate that double alignment is needed.
219  static const int kDoubleAlignmentSentinel = 0;
220
221  // Raw data size encoding helpers.
222  static const int kFirstEncodableFixedRawDataSize = 1;
223  static const int kLastEncodableFixedRawDataSize =
224      kFirstEncodableFixedRawDataSize + kFixedRawDataCount - 1;
225
226  using FixedRawDataWithSize =
227      BytecodeValueEncoder<kFixedRawData, kFirstEncodableFixedRawDataSize,
228                           kLastEncodableFixedRawDataSize>;
229
230  // Repeat count encoding helpers.
231  static const int kFirstEncodableRepeatCount = 2;
232  static const int kLastEncodableFixedRepeatCount =
233      kFirstEncodableRepeatCount + kFixedRepeatCount - 1;
234  static const int kFirstEncodableVariableRepeatCount =
235      kLastEncodableFixedRepeatCount + 1;
236
237  using FixedRepeatWithCount =
238      BytecodeValueEncoder<kFixedRepeat, kFirstEncodableRepeatCount,
239                           kLastEncodableFixedRepeatCount>;
240
241  // Encodes/decodes repeat count into a serialized variable repeat count
242  // value.
243  struct VariableRepeatCount {
244    static constexpr bool IsEncodable(int repeat_count) {
245      return repeat_count >= kFirstEncodableVariableRepeatCount;
246    }
247
248    static constexpr int Encode(int repeat_count) {
249      DCHECK(IsEncodable(repeat_count));
250      return repeat_count - kFirstEncodableVariableRepeatCount;
251    }
252
253    static constexpr int Decode(int value) {
254      return value + kFirstEncodableVariableRepeatCount;
255    }
256  };
257
258  using RootArrayConstant =
259      BytecodeValueEncoder<kRootArrayConstants, 0, kRootArrayConstantsCount - 1,
260                           RootIndex>;
261  using HotObject = BytecodeValueEncoder<kHotObject, 0, kHotObjectCount - 1>;
262
263  // This backing store reference value represents empty backing stores during
264  // serialization/deserialization.
265  static const uint32_t kEmptyBackingStoreRefSentinel = 0;
266};
267
268}  // namespace internal
269}  // namespace v8
270
271#endif  // V8_SNAPSHOT_SERIALIZER_DESERIALIZER_H_
272