• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
12 namespace v8 {
13 namespace internal {
14 
15 class CallHandlerInfo;
16 class 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.
21 class 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 
IsEncodableBytecodeValueEncoder191     static constexpr bool IsEncodable(TValue value) {
192       return base::IsInRange(static_cast<int>(value), kMinValue, kMaxValue);
193     }
194 
EncodeBytecodeValueEncoder195     static constexpr byte Encode(TValue value) {
196       DCHECK(IsEncodable(value));
197       return static_cast<byte>(kBytecode + static_cast<int>(value) - kMinValue);
198     }
199 
DecodeBytecodeValueEncoder200     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 {
IsEncodableVariableRepeatCount244     static constexpr bool IsEncodable(int repeat_count) {
245       return repeat_count >= kFirstEncodableVariableRepeatCount;
246     }
247 
EncodeVariableRepeatCount248     static constexpr int Encode(int repeat_count) {
249       DCHECK(IsEncodable(repeat_count));
250       return repeat_count - kFirstEncodableVariableRepeatCount;
251     }
252 
DecodeVariableRepeatCount253     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