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