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