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/external-reference-table.h" 10 #include "src/globals.h" 11 12 namespace v8 { 13 namespace internal { 14 15 class Isolate; 16 17 class ExternalReferenceEncoder { 18 public: 19 explicit ExternalReferenceEncoder(Isolate* isolate); 20 21 uint32_t Encode(Address key) const; 22 23 const char* NameOfAddress(Isolate* isolate, Address address) const; 24 25 private: 26 AddressToIndexHashMap* map_; 27 #ifdef DEBUG 28 ExternalReferenceTable* table_; 29 #endif // DEBUG 30 31 DISALLOW_COPY_AND_ASSIGN(ExternalReferenceEncoder); 32 }; 33 34 class HotObjectsList { 35 public: 36 HotObjectsList() : index_(0) { 37 for (int i = 0; i < kSize; i++) circular_queue_[i] = NULL; 38 } 39 40 void Add(HeapObject* object) { 41 DCHECK(!AllowHeapAllocation::IsAllowed()); 42 circular_queue_[index_] = object; 43 index_ = (index_ + 1) & kSizeMask; 44 } 45 46 HeapObject* Get(int index) { 47 DCHECK(!AllowHeapAllocation::IsAllowed()); 48 DCHECK_NOT_NULL(circular_queue_[index]); 49 return circular_queue_[index]; 50 } 51 52 static const int kNotFound = -1; 53 54 int Find(HeapObject* object) { 55 DCHECK(!AllowHeapAllocation::IsAllowed()); 56 for (int i = 0; i < kSize; i++) { 57 if (circular_queue_[i] == object) return i; 58 } 59 return kNotFound; 60 } 61 62 static const int kSize = 8; 63 64 private: 65 STATIC_ASSERT(IS_POWER_OF_TWO(kSize)); 66 static const int kSizeMask = kSize - 1; 67 HeapObject* circular_queue_[kSize]; 68 int index_; 69 70 DISALLOW_COPY_AND_ASSIGN(HotObjectsList); 71 }; 72 73 // The Serializer/Deserializer class is a common superclass for Serializer and 74 // Deserializer which is used to store common constants and methods used by 75 // both. 76 class SerializerDeserializer : public ObjectVisitor { 77 public: 78 static void Iterate(Isolate* isolate, ObjectVisitor* visitor); 79 80 // No reservation for large object space necessary. 81 // We also handle map space differenly. 82 STATIC_ASSERT(MAP_SPACE == CODE_SPACE + 1); 83 static const int kNumberOfPreallocatedSpaces = CODE_SPACE + 1; 84 static const int kNumberOfSpaces = LAST_SPACE + 1; 85 86 protected: 87 static bool CanBeDeferred(HeapObject* o); 88 89 // ---------- byte code range 0x00..0x7f ---------- 90 // Byte codes in this range represent Where, HowToCode and WhereToPoint. 91 // Where the pointed-to object can be found: 92 // The static assert below will trigger when the number of preallocated spaces 93 // changed. If that happens, update the bytecode ranges in the comments below. 94 STATIC_ASSERT(5 == kNumberOfSpaces); 95 enum Where { 96 // 0x00..0x04 Allocate new object, in specified space. 97 kNewObject = 0x00, 98 // 0x08..0x0c Reference to previous object from space. 99 kBackref = 0x08, 100 // 0x10..0x14 Reference to previous object from space after skip. 101 kBackrefWithSkip = 0x10, 102 103 // 0x05 Root array item. 104 kRootArray = 0x05, 105 // 0x06 Object in the partial snapshot cache. 106 kPartialSnapshotCache = 0x06, 107 // 0x07 External reference referenced by id. 108 kExternalReference = 0x07, 109 110 // 0x0d Object provided in the attached list. 111 kAttachedReference = 0x0d, 112 // 0x0e Builtin code referenced by index. 113 kBuiltin = 0x0e, 114 115 // 0x0f Misc, see below (incl. 0x2f, 0x4f, 0x6f). 116 // 0x15..0x1f Misc, see below (incl. 0x35..0x3f, 0x55..0x5f, 0x75..0x7f). 117 }; 118 119 static const int kWhereMask = 0x1f; 120 static const int kSpaceMask = 7; 121 STATIC_ASSERT(kNumberOfSpaces <= kSpaceMask + 1); 122 123 // How to code the pointer to the object. 124 enum HowToCode { 125 // Straight pointer. 126 kPlain = 0, 127 // A pointer inlined in code. What this means depends on the architecture. 128 kFromCode = 0x20 129 }; 130 131 static const int kHowToCodeMask = 0x20; 132 133 // Where to point within the object. 134 enum WhereToPoint { 135 // Points to start of object 136 kStartOfObject = 0, 137 // Points to instruction in code object or payload of cell. 138 kInnerPointer = 0x40 139 }; 140 141 static const int kWhereToPointMask = 0x40; 142 143 // ---------- Misc ---------- 144 // Skip. 145 static const int kSkip = 0x0f; 146 // Do nothing, used for padding. 147 static const int kNop = 0x2f; 148 // Move to next reserved chunk. 149 static const int kNextChunk = 0x4f; 150 // Deferring object content. 151 static const int kDeferred = 0x6f; 152 // Alignment prefixes 0x15..0x17 153 static const int kAlignmentPrefix = 0x15; 154 // A tag emitted at strategic points in the snapshot to delineate sections. 155 // If the deserializer does not find these at the expected moments then it 156 // is an indication that the snapshot and the VM do not fit together. 157 // Examine the build process for architecture, version or configuration 158 // mismatches. 159 static const int kSynchronize = 0x18; 160 // Repeats of variable length. 161 static const int kVariableRepeat = 0x19; 162 // Raw data of variable length. 163 static const int kVariableRawData = 0x1a; 164 // Internal reference encoded as offsets of pc and target from code entry. 165 static const int kInternalReference = 0x1b; 166 static const int kInternalReferenceEncoded = 0x1c; 167 // Used for the source code of the natives, which is in the executable, but 168 // is referred to from external strings in the snapshot. 169 static const int kNativesStringResource = 0x1d; 170 // Used for the source code for compiled stubs, which is in the executable, 171 // but is referred to from external strings in the snapshot. 172 static const int kExtraNativesStringResource = 0x1e; 173 // Used for embedder-provided serialization data for internal fields. 174 static const int kInternalFieldsData = 0x1f; 175 176 // 8 hot (recently seen or back-referenced) objects with optional skip. 177 static const int kNumberOfHotObjects = 8; 178 STATIC_ASSERT(kNumberOfHotObjects == HotObjectsList::kSize); 179 // 0x38..0x3f 180 static const int kHotObject = 0x38; 181 // 0x58..0x5f 182 static const int kHotObjectWithSkip = 0x58; 183 static const int kHotObjectMask = 0x07; 184 185 // 0x35..0x37, 0x55..0x57, 0x75..0x7f unused. 186 187 // ---------- byte code range 0x80..0xff ---------- 188 // First 32 root array items. 189 static const int kNumberOfRootArrayConstants = 0x20; 190 // 0x80..0x9f 191 static const int kRootArrayConstants = 0x80; 192 // 0xa0..0xbf 193 static const int kRootArrayConstantsWithSkip = 0xa0; 194 static const int kRootArrayConstantsMask = 0x1f; 195 196 // 32 common raw data lengths. 197 static const int kNumberOfFixedRawData = 0x20; 198 // 0xc0..0xdf 199 static const int kFixedRawData = 0xc0; 200 static const int kOnePointerRawData = kFixedRawData; 201 static const int kFixedRawDataStart = kFixedRawData - 1; 202 203 // 16 repeats lengths. 204 static const int kNumberOfFixedRepeat = 0x10; 205 // 0xe0..0xef 206 static const int kFixedRepeat = 0xe0; 207 static const int kFixedRepeatStart = kFixedRepeat - 1; 208 209 // 0xf0..0xff unused. 210 211 // ---------- special values ---------- 212 static const int kAnyOldSpace = -1; 213 214 // Sentinel after a new object to indicate that double alignment is needed. 215 static const int kDoubleAlignmentSentinel = 0; 216 217 // ---------- member variable ---------- 218 HotObjectsList hot_objects_; 219 }; 220 221 class SerializedData { 222 public: 223 class Reservation { 224 public: 225 explicit Reservation(uint32_t size) 226 : reservation_(ChunkSizeBits::encode(size)) {} 227 228 uint32_t chunk_size() const { return ChunkSizeBits::decode(reservation_); } 229 bool is_last() const { return IsLastChunkBits::decode(reservation_); } 230 231 void mark_as_last() { reservation_ |= IsLastChunkBits::encode(true); } 232 233 private: 234 uint32_t reservation_; 235 }; 236 237 SerializedData(byte* data, int size) 238 : data_(data), size_(size), owns_data_(false) {} 239 SerializedData() : data_(NULL), size_(0), owns_data_(false) {} 240 241 ~SerializedData() { 242 if (owns_data_) DeleteArray<byte>(data_); 243 } 244 245 uint32_t GetMagicNumber() const { return GetHeaderValue(kMagicNumberOffset); } 246 247 class ChunkSizeBits : public BitField<uint32_t, 0, 31> {}; 248 class IsLastChunkBits : public BitField<bool, 31, 1> {}; 249 250 static uint32_t ComputeMagicNumber(ExternalReferenceTable* table) { 251 uint32_t external_refs = table->size(); 252 return 0xC0DE0000 ^ external_refs; 253 } 254 255 protected: 256 void SetHeaderValue(int offset, uint32_t value) { 257 uint32_t* address = reinterpret_cast<uint32_t*>(data_ + offset); 258 memcpy(reinterpret_cast<uint32_t*>(address), &value, sizeof(value)); 259 } 260 261 uint32_t GetHeaderValue(int offset) const { 262 uint32_t value; 263 memcpy(&value, reinterpret_cast<int*>(data_ + offset), sizeof(value)); 264 return value; 265 } 266 267 void AllocateData(int size); 268 269 static uint32_t ComputeMagicNumber(Isolate* isolate) { 270 return ComputeMagicNumber(ExternalReferenceTable::instance(isolate)); 271 } 272 273 void SetMagicNumber(Isolate* isolate) { 274 SetHeaderValue(kMagicNumberOffset, ComputeMagicNumber(isolate)); 275 } 276 277 static const int kMagicNumberOffset = 0; 278 279 byte* data_; 280 int size_; 281 bool owns_data_; 282 }; 283 284 } // namespace internal 285 } // namespace v8 286 287 #endif // V8_SNAPSHOT_SERIALIZER_COMMON_H_ 288