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: Hash(Address key)26 static uint32_t Hash(Address key) { 27 return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key) >> 28 kPointerSizeLog2); 29 } 30 31 base::HashMap* map_; 32 33 DISALLOW_COPY_AND_ASSIGN(ExternalReferenceEncoder); 34 }; 35 36 class HotObjectsList { 37 public: HotObjectsList()38 HotObjectsList() : index_(0) { 39 for (int i = 0; i < kSize; i++) circular_queue_[i] = NULL; 40 } 41 Add(HeapObject * object)42 void Add(HeapObject* object) { 43 DCHECK(!AllowHeapAllocation::IsAllowed()); 44 circular_queue_[index_] = object; 45 index_ = (index_ + 1) & kSizeMask; 46 } 47 Get(int index)48 HeapObject* Get(int index) { 49 DCHECK(!AllowHeapAllocation::IsAllowed()); 50 DCHECK_NOT_NULL(circular_queue_[index]); 51 return circular_queue_[index]; 52 } 53 54 static const int kNotFound = -1; 55 Find(HeapObject * object)56 int Find(HeapObject* object) { 57 DCHECK(!AllowHeapAllocation::IsAllowed()); 58 for (int i = 0; i < kSize; i++) { 59 if (circular_queue_[i] == object) return i; 60 } 61 return kNotFound; 62 } 63 64 static const int kSize = 8; 65 66 private: 67 STATIC_ASSERT(IS_POWER_OF_TWO(kSize)); 68 static const int kSizeMask = kSize - 1; 69 HeapObject* circular_queue_[kSize]; 70 int index_; 71 72 DISALLOW_COPY_AND_ASSIGN(HotObjectsList); 73 }; 74 75 // The Serializer/Deserializer class is a common superclass for Serializer and 76 // Deserializer which is used to store common constants and methods used by 77 // both. 78 class SerializerDeserializer : public ObjectVisitor { 79 public: 80 static void Iterate(Isolate* isolate, ObjectVisitor* visitor); 81 82 // No reservation for large object space necessary. 83 static const int kNumberOfPreallocatedSpaces = LAST_PAGED_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 174 // 8 hot (recently seen or back-referenced) objects with optional skip. 175 static const int kNumberOfHotObjects = 8; 176 STATIC_ASSERT(kNumberOfHotObjects == HotObjectsList::kSize); 177 // 0x38..0x3f 178 static const int kHotObject = 0x38; 179 // 0x58..0x5f 180 static const int kHotObjectWithSkip = 0x58; 181 static const int kHotObjectMask = 0x07; 182 183 // 0x1f, 0x35..0x37, 0x55..0x57, 0x75..0x7f unused. 184 185 // ---------- byte code range 0x80..0xff ---------- 186 // First 32 root array items. 187 static const int kNumberOfRootArrayConstants = 0x20; 188 // 0x80..0x9f 189 static const int kRootArrayConstants = 0x80; 190 // 0xa0..0xbf 191 static const int kRootArrayConstantsWithSkip = 0xa0; 192 static const int kRootArrayConstantsMask = 0x1f; 193 194 // 32 common raw data lengths. 195 static const int kNumberOfFixedRawData = 0x20; 196 // 0xc0..0xdf 197 static const int kFixedRawData = 0xc0; 198 static const int kOnePointerRawData = kFixedRawData; 199 static const int kFixedRawDataStart = kFixedRawData - 1; 200 201 // 16 repeats lengths. 202 static const int kNumberOfFixedRepeat = 0x10; 203 // 0xe0..0xef 204 static const int kFixedRepeat = 0xe0; 205 static const int kFixedRepeatStart = kFixedRepeat - 1; 206 207 // 0xf0..0xff unused. 208 209 // ---------- special values ---------- 210 static const int kAnyOldSpace = -1; 211 212 // Sentinel after a new object to indicate that double alignment is needed. 213 static const int kDoubleAlignmentSentinel = 0; 214 215 // ---------- member variable ---------- 216 HotObjectsList hot_objects_; 217 }; 218 219 class SerializedData { 220 public: 221 class Reservation { 222 public: Reservation(uint32_t size)223 explicit Reservation(uint32_t size) 224 : reservation_(ChunkSizeBits::encode(size)) {} 225 chunk_size()226 uint32_t chunk_size() const { return ChunkSizeBits::decode(reservation_); } is_last()227 bool is_last() const { return IsLastChunkBits::decode(reservation_); } 228 mark_as_last()229 void mark_as_last() { reservation_ |= IsLastChunkBits::encode(true); } 230 231 private: 232 uint32_t reservation_; 233 }; 234 SerializedData(byte * data,int size)235 SerializedData(byte* data, int size) 236 : data_(data), size_(size), owns_data_(false) {} SerializedData()237 SerializedData() : data_(NULL), size_(0), owns_data_(false) {} 238 ~SerializedData()239 ~SerializedData() { 240 if (owns_data_) DeleteArray<byte>(data_); 241 } 242 GetMagicNumber()243 uint32_t GetMagicNumber() const { return GetHeaderValue(kMagicNumberOffset); } 244 245 class ChunkSizeBits : public BitField<uint32_t, 0, 31> {}; 246 class IsLastChunkBits : public BitField<bool, 31, 1> {}; 247 ComputeMagicNumber(ExternalReferenceTable * table)248 static uint32_t ComputeMagicNumber(ExternalReferenceTable* table) { 249 uint32_t external_refs = table->size(); 250 return 0xC0DE0000 ^ external_refs; 251 } 252 253 protected: SetHeaderValue(int offset,uint32_t value)254 void SetHeaderValue(int offset, uint32_t value) { 255 uint32_t* address = reinterpret_cast<uint32_t*>(data_ + offset); 256 memcpy(reinterpret_cast<uint32_t*>(address), &value, sizeof(value)); 257 } 258 GetHeaderValue(int offset)259 uint32_t GetHeaderValue(int offset) const { 260 uint32_t value; 261 memcpy(&value, reinterpret_cast<int*>(data_ + offset), sizeof(value)); 262 return value; 263 } 264 265 void AllocateData(int size); 266 ComputeMagicNumber(Isolate * isolate)267 static uint32_t ComputeMagicNumber(Isolate* isolate) { 268 return ComputeMagicNumber(ExternalReferenceTable::instance(isolate)); 269 } 270 SetMagicNumber(Isolate * isolate)271 void SetMagicNumber(Isolate* isolate) { 272 SetHeaderValue(kMagicNumberOffset, ComputeMagicNumber(isolate)); 273 } 274 275 static const int kMagicNumberOffset = 0; 276 277 byte* data_; 278 int size_; 279 bool owns_data_; 280 }; 281 282 } // namespace internal 283 } // namespace v8 284 285 #endif // V8_SNAPSHOT_SERIALIZER_COMMON_H_ 286