1 // Copyright 2006-2008 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_SNAPSHOT_H_ 6 #define V8_SNAPSHOT_SNAPSHOT_H_ 7 8 #include "src/snapshot/partial-serializer.h" 9 #include "src/snapshot/startup-serializer.h" 10 11 #include "src/utils.h" 12 13 namespace v8 { 14 namespace internal { 15 16 // Forward declarations. 17 class Isolate; 18 class BuiltinSerializer; 19 class PartialSerializer; 20 class StartupSerializer; 21 22 // Wrapper around reservation sizes and the serialization payload. 23 class SnapshotData : public SerializedData { 24 public: 25 // Used when producing. 26 template <class AllocatorT> 27 explicit SnapshotData(const Serializer<AllocatorT>* serializer); 28 29 // Used when consuming. SnapshotData(const Vector<const byte> snapshot)30 explicit SnapshotData(const Vector<const byte> snapshot) 31 : SerializedData(const_cast<byte*>(snapshot.begin()), snapshot.length()) { 32 } 33 34 std::vector<Reservation> Reservations() const; 35 virtual Vector<const byte> Payload() const; 36 RawData()37 Vector<const byte> RawData() const { 38 return Vector<const byte>(data_, size_); 39 } 40 41 protected: 42 // The data header consists of uint32_t-sized entries: 43 // [0] magic number and (internal) external reference count 44 // [1] number of reservation size entries 45 // [2] payload length 46 // ... reservations 47 // ... serialized payload 48 static const uint32_t kNumReservationsOffset = 49 kMagicNumberOffset + kUInt32Size; 50 static const uint32_t kPayloadLengthOffset = 51 kNumReservationsOffset + kUInt32Size; 52 static const uint32_t kHeaderSize = kPayloadLengthOffset + kUInt32Size; 53 }; 54 55 class BuiltinSnapshotData final : public SnapshotData { 56 public: 57 // Used when producing. 58 // This simply forwards to the SnapshotData constructor. 59 // The BuiltinSerializer appends the builtin offset table to the payload. 60 explicit BuiltinSnapshotData(const BuiltinSerializer* serializer); 61 62 // Used when consuming. BuiltinSnapshotData(const Vector<const byte> snapshot)63 explicit BuiltinSnapshotData(const Vector<const byte> snapshot) 64 : SnapshotData(snapshot) { 65 } 66 67 // Returns the serialized payload without the builtin offsets table. 68 Vector<const byte> Payload() const override; 69 70 // Returns only the builtin offsets table. 71 Vector<const uint32_t> BuiltinOffsets() const; 72 73 private: 74 // In addition to the format specified in SnapshotData, BuiltinsSnapshotData 75 // includes a list of builtin at the end of the serialized payload: 76 // 77 // ... 78 // ... serialized payload 79 // ... list of builtins offsets 80 }; 81 82 class EmbeddedData final { 83 public: 84 static EmbeddedData FromIsolate(Isolate* isolate); 85 static EmbeddedData FromBlob(); 86 data()87 const uint8_t* data() const { return data_; } size()88 uint32_t size() const { return size_; } 89 Dispose()90 void Dispose() { delete[] data_; } 91 92 Address InstructionStartOfBuiltin(int i) const; 93 uint32_t InstructionSizeOfBuiltin(int i) const; 94 ContainsBuiltin(int i)95 bool ContainsBuiltin(int i) const { return InstructionSizeOfBuiltin(i) > 0; } 96 97 // Padded with kCodeAlignment. PaddedInstructionSizeOfBuiltin(int i)98 uint32_t PaddedInstructionSizeOfBuiltin(int i) const { 99 return PadAndAlign(InstructionSizeOfBuiltin(i)); 100 } 101 102 size_t CreateHash() const; Hash()103 size_t Hash() const { 104 return *reinterpret_cast<const size_t*>(data_ + HashOffset()); 105 } 106 107 struct Metadata { 108 // Blob layout information. 109 uint32_t instructions_offset; 110 uint32_t instructions_length; 111 }; 112 STATIC_ASSERT(offsetof(Metadata, instructions_offset) == 0); 113 STATIC_ASSERT(offsetof(Metadata, instructions_length) == kUInt32Size); 114 STATIC_ASSERT(sizeof(Metadata) == kUInt32Size + kUInt32Size); 115 116 // The layout of the blob is as follows: 117 // 118 // [0] hash of the remaining blob 119 // [1] metadata of instruction stream 0 120 // ... metadata 121 // ... instruction streams 122 123 static constexpr uint32_t kTableSize = Builtins::builtin_count; HashOffset()124 static constexpr uint32_t HashOffset() { return 0; } HashSize()125 static constexpr uint32_t HashSize() { return kSizetSize; } MetadataOffset()126 static constexpr uint32_t MetadataOffset() { 127 return HashOffset() + HashSize(); 128 } MetadataSize()129 static constexpr uint32_t MetadataSize() { 130 return sizeof(struct Metadata) * kTableSize; 131 } RawDataOffset()132 static constexpr uint32_t RawDataOffset() { 133 return PadAndAlign(MetadataOffset() + MetadataSize()); 134 } 135 136 private: EmbeddedData(const uint8_t * data,uint32_t size)137 EmbeddedData(const uint8_t* data, uint32_t size) : data_(data), size_(size) {} 138 Metadata()139 const Metadata* Metadata() const { 140 return reinterpret_cast<const struct Metadata*>(data_ + MetadataOffset()); 141 } RawData()142 const uint8_t* RawData() const { return data_ + RawDataOffset(); } 143 PadAndAlign(int size)144 static constexpr int PadAndAlign(int size) { 145 // Ensure we have at least one byte trailing the actual builtin 146 // instructions which we can later fill with int3. 147 return RoundUp<kCodeAlignment>(size + 1); 148 } 149 150 void PrintStatistics() const; 151 152 const uint8_t* data_; 153 uint32_t size_; 154 }; 155 156 class Snapshot : public AllStatic { 157 public: 158 // ---------------- Deserialization ---------------- 159 160 // Initialize the Isolate from the internal snapshot. Returns false if no 161 // snapshot could be found. 162 static bool Initialize(Isolate* isolate); 163 164 // Create a new context using the internal partial snapshot. 165 static MaybeHandle<Context> NewContextFromSnapshot( 166 Isolate* isolate, Handle<JSGlobalProxy> global_proxy, 167 size_t context_index, 168 v8::DeserializeEmbedderFieldsCallback embedder_fields_deserializer); 169 170 // Deserializes a single given builtin code object. Intended to be called at 171 // runtime after the isolate (and the builtins table) has been fully 172 // initialized. 173 static Code* DeserializeBuiltin(Isolate* isolate, int builtin_id); 174 static void EnsureAllBuiltinsAreDeserialized(Isolate* isolate); 175 static Code* EnsureBuiltinIsDeserialized(Isolate* isolate, 176 Handle<SharedFunctionInfo> shared); 177 178 // Deserializes a single given handler code object. Intended to be called at 179 // runtime after the isolate has been fully initialized. 180 static Code* DeserializeHandler(Isolate* isolate, 181 interpreter::Bytecode bytecode, 182 interpreter::OperandScale operand_scale); 183 184 // ---------------- Helper methods ---------------- 185 186 static bool HasContextSnapshot(Isolate* isolate, size_t index); 187 static bool EmbedsScript(Isolate* isolate); 188 189 // To be implemented by the snapshot source. 190 static const v8::StartupData* DefaultSnapshotBlob(); 191 192 // ---------------- Serialization ---------------- 193 194 static v8::StartupData CreateSnapshotBlob( 195 const SnapshotData* startup_snapshot, 196 const BuiltinSnapshotData* builtin_snapshot, 197 const std::vector<SnapshotData*>& context_snapshots, 198 bool can_be_rehashed); 199 200 #ifdef DEBUG 201 static bool SnapshotIsValid(const v8::StartupData* snapshot_blob); 202 #endif // DEBUG 203 204 private: 205 static uint32_t ExtractNumContexts(const v8::StartupData* data); 206 static uint32_t ExtractContextOffset(const v8::StartupData* data, 207 uint32_t index); 208 static bool ExtractRehashability(const v8::StartupData* data); 209 static Vector<const byte> ExtractStartupData(const v8::StartupData* data); 210 static Vector<const byte> ExtractBuiltinData(const v8::StartupData* data); 211 static Vector<const byte> ExtractContextData(const v8::StartupData* data, 212 uint32_t index); 213 GetHeaderValue(const v8::StartupData * data,uint32_t offset)214 static uint32_t GetHeaderValue(const v8::StartupData* data, uint32_t offset) { 215 return ReadLittleEndianValue<uint32_t>( 216 reinterpret_cast<Address>(data->data) + offset); 217 } SetHeaderValue(char * data,uint32_t offset,uint32_t value)218 static void SetHeaderValue(char* data, uint32_t offset, uint32_t value) { 219 WriteLittleEndianValue(reinterpret_cast<Address>(data) + offset, value); 220 } 221 222 static void CheckVersion(const v8::StartupData* data); 223 224 // Snapshot blob layout: 225 // [0] number of contexts N 226 // [1] rehashability 227 // [2] (128 bytes) version string 228 // [3] offset to builtins 229 // [4] offset to context 0 230 // [5] offset to context 1 231 // ... 232 // ... offset to context N - 1 233 // ... startup snapshot data 234 // ... builtin snapshot data 235 // ... context 0 snapshot data 236 // ... context 1 snapshot data 237 238 static const uint32_t kNumberOfContextsOffset = 0; 239 // TODO(yangguo): generalize rehashing, and remove this flag. 240 static const uint32_t kRehashabilityOffset = 241 kNumberOfContextsOffset + kUInt32Size; 242 static const uint32_t kVersionStringOffset = 243 kRehashabilityOffset + kUInt32Size; 244 static const uint32_t kVersionStringLength = 64; 245 static const uint32_t kBuiltinOffsetOffset = 246 kVersionStringOffset + kVersionStringLength; 247 static const uint32_t kFirstContextOffsetOffset = 248 kBuiltinOffsetOffset + kUInt32Size; 249 StartupSnapshotOffset(int num_contexts)250 static uint32_t StartupSnapshotOffset(int num_contexts) { 251 return kFirstContextOffsetOffset + num_contexts * kInt32Size; 252 } 253 ContextSnapshotOffsetOffset(int index)254 static uint32_t ContextSnapshotOffsetOffset(int index) { 255 return kFirstContextOffsetOffset + index * kInt32Size; 256 } 257 258 DISALLOW_IMPLICIT_CONSTRUCTORS(Snapshot); 259 }; 260 261 #ifdef V8_USE_EXTERNAL_STARTUP_DATA 262 void SetSnapshotFromFile(StartupData* snapshot_blob); 263 #endif 264 265 } // namespace internal 266 } // namespace v8 267 268 #endif // V8_SNAPSHOT_SNAPSHOT_H_ 269