• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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