serializer-common.h revision bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8
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 12namespace v8 { 13namespace internal { 14 15class Isolate; 16 17class 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 static uint32_t Hash(Address key) { 27 return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key) >> 28 kPointerSizeLog2); 29 } 30 31 HashMap* map_; 32 33 DISALLOW_COPY_AND_ASSIGN(ExternalReferenceEncoder); 34}; 35 36class HotObjectsList { 37 public: 38 HotObjectsList() : index_(0) { 39 for (int i = 0; i < kSize; i++) circular_queue_[i] = NULL; 40 } 41 42 void Add(HeapObject* object) { 43 DCHECK(!AllowHeapAllocation::IsAllowed()); 44 circular_queue_[index_] = object; 45 index_ = (index_ + 1) & kSizeMask; 46 } 47 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 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. 78class 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 = 0, 98 // 0x05 Unused (including 0x25, 0x45, 0x65). 99 // 0x06 Unused (including 0x26, 0x46, 0x66). 100 // 0x07 Unused (including 0x27, 0x47, 0x67). 101 // 0x08..0x0c Reference to previous object from space. 102 kBackref = 0x08, 103 // 0x0d Unused (including 0x2d, 0x4d, 0x6d). 104 // 0x0e Unused (including 0x2e, 0x4e, 0x6e). 105 // 0x0f Unused (including 0x2f, 0x4f, 0x6f). 106 // 0x10..0x14 Reference to previous object from space after skip. 107 kBackrefWithSkip = 0x10, 108 // 0x15 Unused (including 0x35, 0x55, 0x75). 109 // 0x16 Unused (including 0x36, 0x56, 0x76). 110 // 0x17 Misc (including 0x37, 0x57, 0x77). 111 // 0x18 Root array item. 112 kRootArray = 0x18, 113 // 0x19 Object in the partial snapshot cache. 114 kPartialSnapshotCache = 0x19, 115 // 0x1a External reference referenced by id. 116 kExternalReference = 0x1a, 117 // 0x1b Object provided in the attached list. 118 kAttachedReference = 0x1b, 119 // 0x1c Builtin code referenced by index. 120 kBuiltin = 0x1c 121 // 0x1d..0x1f Misc (including 0x3d..0x3f, 0x5d..0x5f, 0x7d..0x7f) 122 }; 123 124 static const int kWhereMask = 0x1f; 125 static const int kSpaceMask = 7; 126 STATIC_ASSERT(kNumberOfSpaces <= kSpaceMask + 1); 127 128 // How to code the pointer to the object. 129 enum HowToCode { 130 // Straight pointer. 131 kPlain = 0, 132 // A pointer inlined in code. What this means depends on the architecture. 133 kFromCode = 0x20 134 }; 135 136 static const int kHowToCodeMask = 0x20; 137 138 // Where to point within the object. 139 enum WhereToPoint { 140 // Points to start of object 141 kStartOfObject = 0, 142 // Points to instruction in code object or payload of cell. 143 kInnerPointer = 0x40 144 }; 145 146 static const int kWhereToPointMask = 0x40; 147 148 // ---------- Misc ---------- 149 // Skip. 150 static const int kSkip = 0x1d; 151 // Internal reference encoded as offsets of pc and target from code entry. 152 static const int kInternalReference = 0x1e; 153 static const int kInternalReferenceEncoded = 0x1f; 154 // Do nothing, used for padding. 155 static const int kNop = 0x3d; 156 // Move to next reserved chunk. 157 static const int kNextChunk = 0x3e; 158 // Deferring object content. 159 static const int kDeferred = 0x3f; 160 // Used for the source code of the natives, which is in the executable, but 161 // is referred to from external strings in the snapshot. 162 static const int kNativesStringResource = 0x5d; 163 // Used for the source code for compiled stubs, which is in the executable, 164 // but is referred to from external strings in the snapshot. 165 static const int kExtraNativesStringResource = 0x5e; 166 // A tag emitted at strategic points in the snapshot to delineate sections. 167 // If the deserializer does not find these at the expected moments then it 168 // is an indication that the snapshot and the VM do not fit together. 169 // Examine the build process for architecture, version or configuration 170 // mismatches. 171 static const int kSynchronize = 0x17; 172 // Repeats of variable length. 173 static const int kVariableRepeat = 0x37; 174 // Raw data of variable length. 175 static const int kVariableRawData = 0x57; 176 // Alignment prefixes 0x7d..0x7f 177 static const int kAlignmentPrefix = 0x7d; 178 179 // 0x77 unused 180 181 // ---------- byte code range 0x80..0xff ---------- 182 // First 32 root array items. 183 static const int kNumberOfRootArrayConstants = 0x20; 184 // 0x80..0x9f 185 static const int kRootArrayConstants = 0x80; 186 // 0xa0..0xbf 187 static const int kRootArrayConstantsWithSkip = 0xa0; 188 static const int kRootArrayConstantsMask = 0x1f; 189 190 // 8 hot (recently seen or back-referenced) objects with optional skip. 191 static const int kNumberOfHotObjects = 0x08; 192 // 0xc0..0xc7 193 static const int kHotObject = 0xc0; 194 // 0xc8..0xcf 195 static const int kHotObjectWithSkip = 0xc8; 196 static const int kHotObjectMask = 0x07; 197 198 // 32 common raw data lengths. 199 static const int kNumberOfFixedRawData = 0x20; 200 // 0xd0..0xef 201 static const int kFixedRawData = 0xd0; 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 // 0xf0..0xff 208 static const int kFixedRepeat = 0xf0; 209 static const int kFixedRepeatStart = kFixedRepeat - 1; 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 221class 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