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/utils.h"
12 
13 namespace v8 {
14 namespace internal {
15 
16 // Forward declarations.
17 class Isolate;
18 class PartialSerializer;
19 class SnapshotCompression;
20 class StartupSerializer;
21 
22 // Wrapper around reservation sizes and the serialization payload.
23 class V8_EXPORT_PRIVATE SnapshotData : public SerializedData {
24  public:
25   // Used when producing.
26   explicit SnapshotData(const Serializer* serializer);
27 
28   // Used when consuming.
SnapshotData(const Vector<const byte> snapshot)29   explicit SnapshotData(const Vector<const byte> snapshot)
30       : SerializedData(const_cast<byte*>(snapshot.begin()), snapshot.length()) {
31   }
32 
33   std::vector<Reservation> Reservations() const;
34   virtual Vector<const byte> Payload() const;
35 
RawData()36   Vector<const byte> RawData() const {
37     return Vector<const byte>(data_, size_);
38   }
39 
40  protected:
41   // Empty constructor used by SnapshotCompression so it can manually allocate
42   // memory.
SnapshotData()43   SnapshotData() : SerializedData() {}
44   friend class SnapshotCompression;
45 
46   // Resize used by SnapshotCompression so it can shrink the compressed
47   // SnapshotData.
Resize(uint32_t size)48   void Resize(uint32_t size) { size_ = size; }
49 
50   // The data header consists of uint32_t-sized entries:
51   // [0] magic number and (internal) external reference count
52   // [1] number of reservation size entries
53   // [2] payload length
54   // ... reservations
55   // ... serialized payload
56   static const uint32_t kNumReservationsOffset =
57       kMagicNumberOffset + kUInt32Size;
58   static const uint32_t kPayloadLengthOffset =
59       kNumReservationsOffset + kUInt32Size;
60   static const uint32_t kHeaderSize = kPayloadLengthOffset + kUInt32Size;
61 };
62 
63 class Snapshot : public AllStatic {
64  public:
65   // ---------------- Deserialization ----------------
66 
67   // Initialize the Isolate from the internal snapshot. Returns false if no
68   // snapshot could be found.
69   static bool Initialize(Isolate* isolate);
70 
71   // Create a new context using the internal partial snapshot.
72   static MaybeHandle<Context> NewContextFromSnapshot(
73       Isolate* isolate, Handle<JSGlobalProxy> global_proxy,
74       size_t context_index,
75       v8::DeserializeEmbedderFieldsCallback embedder_fields_deserializer);
76 
77   // ---------------- Helper methods ----------------
78 
79   static bool HasContextSnapshot(Isolate* isolate, size_t index);
80   static bool EmbedsScript(Isolate* isolate);
81 
82   // To be implemented by the snapshot source.
83   static const v8::StartupData* DefaultSnapshotBlob();
84 
85   V8_EXPORT_PRIVATE static bool VerifyChecksum(const v8::StartupData* data);
86 
87   // ---------------- Serialization ----------------
88 
89   static v8::StartupData CreateSnapshotBlob(
90       const SnapshotData* startup_snapshot_in,
91       const SnapshotData* read_only_snapshot_in,
92       const std::vector<SnapshotData*>& context_snapshots_in,
93       bool can_be_rehashed);
94 
95 #ifdef DEBUG
96   static bool SnapshotIsValid(const v8::StartupData* snapshot_blob);
97 #endif  // DEBUG
98 
99   static bool ExtractRehashability(const v8::StartupData* data);
100 
101  private:
102   static uint32_t ExtractNumContexts(const v8::StartupData* data);
103   static uint32_t ExtractContextOffset(const v8::StartupData* data,
104                                        uint32_t index);
105   static Vector<const byte> ExtractStartupData(const v8::StartupData* data);
106   static Vector<const byte> ExtractReadOnlyData(const v8::StartupData* data);
107   static Vector<const byte> ExtractContextData(const v8::StartupData* data,
108                                                uint32_t index);
109 
GetHeaderValue(const v8::StartupData * data,uint32_t offset)110   static uint32_t GetHeaderValue(const v8::StartupData* data, uint32_t offset) {
111     return base::ReadLittleEndianValue<uint32_t>(
112         reinterpret_cast<Address>(data->data) + offset);
113   }
SetHeaderValue(char * data,uint32_t offset,uint32_t value)114   static void SetHeaderValue(char* data, uint32_t offset, uint32_t value) {
115     base::WriteLittleEndianValue(reinterpret_cast<Address>(data) + offset,
116                                  value);
117   }
118 
119   static void CheckVersion(const v8::StartupData* data);
120 
121   // Snapshot blob layout:
122   // [0] number of contexts N
123   // [1] rehashability
124   // [2] checksum
125   // [3] (128 bytes) version string
126   // [4] offset to readonly
127   // [5] offset to context 0
128   // [6] offset to context 1
129   // ...
130   // ... offset to context N - 1
131   // ... startup snapshot data
132   // ... read-only snapshot data
133   // ... context 0 snapshot data
134   // ... context 1 snapshot data
135 
136   static const uint32_t kNumberOfContextsOffset = 0;
137   // TODO(yangguo): generalize rehashing, and remove this flag.
138   static const uint32_t kRehashabilityOffset =
139       kNumberOfContextsOffset + kUInt32Size;
140   static const uint32_t kChecksumOffset = kRehashabilityOffset + kUInt32Size;
141   static const uint32_t kVersionStringOffset = kChecksumOffset + kUInt32Size;
142   static const uint32_t kVersionStringLength = 64;
143   static const uint32_t kReadOnlyOffsetOffset =
144       kVersionStringOffset + kVersionStringLength;
145   static const uint32_t kFirstContextOffsetOffset =
146       kReadOnlyOffsetOffset + kUInt32Size;
147 
ChecksummedContent(const v8::StartupData * data)148   static Vector<const byte> ChecksummedContent(const v8::StartupData* data) {
149     STATIC_ASSERT(kVersionStringOffset == kChecksumOffset + kUInt32Size);
150     const uint32_t kChecksumStart = kVersionStringOffset;
151     return Vector<const byte>(
152         reinterpret_cast<const byte*>(data->data + kChecksumStart),
153         data->raw_size - kChecksumStart);
154   }
155 
StartupSnapshotOffset(int num_contexts)156   static uint32_t StartupSnapshotOffset(int num_contexts) {
157     return POINTER_SIZE_ALIGN(kFirstContextOffsetOffset +
158                               num_contexts * kInt32Size);
159   }
160 
ContextSnapshotOffsetOffset(int index)161   static uint32_t ContextSnapshotOffsetOffset(int index) {
162     return kFirstContextOffsetOffset + index * kInt32Size;
163   }
164 
165   DISALLOW_IMPLICIT_CONSTRUCTORS(Snapshot);
166 };
167 
168 // Convenience wrapper around snapshot data blob creation used e.g. by tests and
169 // mksnapshot.
170 V8_EXPORT_PRIVATE v8::StartupData CreateSnapshotDataBlobInternal(
171     v8::SnapshotCreator::FunctionCodeHandling function_code_handling,
172     const char* embedded_source, v8::Isolate* isolate = nullptr);
173 
174 // Convenience wrapper around snapshot data blob warmup used e.g. by tests and
175 // mksnapshot.
176 V8_EXPORT_PRIVATE v8::StartupData WarmUpSnapshotDataBlobInternal(
177     v8::StartupData cold_snapshot_blob, const char* warmup_source);
178 
179 #ifdef V8_USE_EXTERNAL_STARTUP_DATA
180 void SetSnapshotFromFile(StartupData* snapshot_blob);
181 #endif
182 
183 }  // namespace internal
184 }  // namespace v8
185 
186 #endif  // V8_SNAPSHOT_SNAPSHOT_H_
187