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