Line data Source code
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 : // The common functionality when building with or without snapshots.
6 :
7 : #include "src/snapshot/snapshot.h"
8 :
9 : #include "src/api.h"
10 : #include "src/base/platform/platform.h"
11 : #include "src/full-codegen/full-codegen.h"
12 : #include "src/objects-inl.h"
13 : #include "src/snapshot/deserializer.h"
14 : #include "src/snapshot/snapshot-source-sink.h"
15 : #include "src/version.h"
16 :
17 : namespace v8 {
18 : namespace internal {
19 :
20 : #ifdef DEBUG
21 : bool Snapshot::SnapshotIsValid(v8::StartupData* snapshot_blob) {
22 : return Snapshot::ExtractNumContexts(snapshot_blob) > 0;
23 : }
24 : #endif // DEBUG
25 :
26 45 : bool Snapshot::HasContextSnapshot(Isolate* isolate, size_t index) {
27 : // Do not use snapshots if the isolate is used to create snapshots.
28 : const v8::StartupData* blob = isolate->snapshot_blob();
29 45 : if (blob == nullptr) return false;
30 45 : if (blob->data == nullptr) return false;
31 45 : size_t num_contexts = static_cast<size_t>(ExtractNumContexts(blob));
32 45 : return index < num_contexts;
33 : }
34 :
35 121394 : bool Snapshot::Initialize(Isolate* isolate) {
36 60697 : if (!isolate->snapshot_available()) return false;
37 : base::ElapsedTimer timer;
38 60697 : if (FLAG_profile_deserialization) timer.Start();
39 :
40 : const v8::StartupData* blob = isolate->snapshot_blob();
41 60697 : Vector<const byte> startup_data = ExtractStartupData(blob);
42 60697 : SnapshotData snapshot_data(startup_data);
43 121394 : Deserializer deserializer(&snapshot_data);
44 60697 : bool success = isolate->Init(&deserializer);
45 60697 : if (FLAG_profile_deserialization) {
46 6 : double ms = timer.Elapsed().InMillisecondsF();
47 6 : int bytes = startup_data.length();
48 6 : PrintF("[Deserializing isolate (%d bytes) took %0.3f ms]\n", bytes, ms);
49 : }
50 : return success;
51 : }
52 :
53 106872 : MaybeHandle<Context> Snapshot::NewContextFromSnapshot(
54 213720 : Isolate* isolate, Handle<JSGlobalProxy> global_proxy, size_t context_index,
55 : v8::DeserializeEmbedderFieldsCallback embedder_fields_deserializer) {
56 106872 : if (!isolate->snapshot_available()) return Handle<Context>();
57 : base::ElapsedTimer timer;
58 106848 : if (FLAG_profile_deserialization) timer.Start();
59 :
60 : const v8::StartupData* blob = isolate->snapshot_blob();
61 : Vector<const byte> context_data =
62 106848 : ExtractContextData(blob, static_cast<int>(context_index));
63 106848 : SnapshotData snapshot_data(context_data);
64 213696 : Deserializer deserializer(&snapshot_data);
65 :
66 : MaybeHandle<Object> maybe_context = deserializer.DeserializePartial(
67 106848 : isolate, global_proxy, embedder_fields_deserializer);
68 : Handle<Object> result;
69 106848 : if (!maybe_context.ToHandle(&result)) return MaybeHandle<Context>();
70 106848 : CHECK(result->IsContext());
71 106848 : if (FLAG_profile_deserialization) {
72 6 : double ms = timer.Elapsed().InMillisecondsF();
73 6 : int bytes = context_data.length();
74 : PrintF("[Deserializing context #%zu (%d bytes) took %0.3f ms]\n",
75 6 : context_index, bytes, ms);
76 : }
77 : return Handle<Context>::cast(result);
78 : }
79 :
80 97 : void ProfileDeserialization(const SnapshotData* startup_snapshot,
81 12 : const List<SnapshotData*>* context_snapshots) {
82 97 : if (FLAG_profile_deserialization) {
83 : int startup_total = 0;
84 6 : PrintF("Deserialization will reserve:\n");
85 48 : for (const auto& reservation : startup_snapshot->Reservations()) {
86 42 : startup_total += reservation.chunk_size();
87 : }
88 6 : PrintF("%10d bytes per isolate\n", startup_total);
89 24 : for (int i = 0; i < context_snapshots->length(); i++) {
90 : int context_total = 0;
91 42 : for (const auto& reservation : context_snapshots->at(i)->Reservations()) {
92 30 : context_total += reservation.chunk_size();
93 : }
94 6 : PrintF("%10d bytes per context #%d\n", context_total, i);
95 : }
96 : }
97 97 : }
98 :
99 97 : v8::StartupData Snapshot::CreateSnapshotBlob(
100 194 : const SnapshotData* startup_snapshot,
101 97 : const List<SnapshotData*>* context_snapshots) {
102 97 : int num_contexts = context_snapshots->length();
103 : int startup_snapshot_offset = StartupSnapshotOffset(num_contexts);
104 : int total_length = startup_snapshot_offset;
105 97 : total_length += startup_snapshot->RawData().length();
106 315 : for (const auto& context_snapshot : *context_snapshots) {
107 121 : total_length += context_snapshot->RawData().length();
108 : }
109 :
110 97 : ProfileDeserialization(startup_snapshot, context_snapshots);
111 :
112 97 : char* data = new char[total_length];
113 : memcpy(data + kNumberOfContextsOffset, &num_contexts, kInt32Size);
114 97 : int payload_offset = StartupSnapshotOffset(num_contexts);
115 : int payload_length = startup_snapshot->RawData().length();
116 97 : memcpy(data + payload_offset, startup_snapshot->RawData().start(),
117 97 : payload_length);
118 97 : if (FLAG_profile_deserialization) {
119 : PrintF("Snapshot blob consists of:\n%10d bytes for startup\n",
120 6 : payload_length);
121 : }
122 97 : payload_offset += payload_length;
123 315 : for (int i = 0; i < num_contexts; i++) {
124 121 : memcpy(data + ContextSnapshotOffsetOffset(i), &payload_offset, kInt32Size);
125 121 : SnapshotData* context_snapshot = context_snapshots->at(i);
126 : payload_length = context_snapshot->RawData().length();
127 121 : memcpy(data + payload_offset, context_snapshot->RawData().start(),
128 121 : payload_length);
129 121 : if (FLAG_profile_deserialization) {
130 6 : PrintF("%10d bytes for context #%d\n", payload_length, i);
131 : }
132 121 : payload_offset += payload_length;
133 : }
134 :
135 : v8::StartupData result = {data, total_length};
136 97 : return result;
137 : }
138 :
139 167590 : int Snapshot::ExtractNumContexts(const v8::StartupData* data) {
140 167590 : CHECK_LT(kNumberOfContextsOffset, data->raw_size);
141 : int num_contexts;
142 167590 : memcpy(&num_contexts, data->data + kNumberOfContextsOffset, kInt32Size);
143 167590 : return num_contexts;
144 : }
145 :
146 60697 : Vector<const byte> Snapshot::ExtractStartupData(const v8::StartupData* data) {
147 60697 : int num_contexts = ExtractNumContexts(data);
148 : int startup_offset = StartupSnapshotOffset(num_contexts);
149 60697 : CHECK_LT(startup_offset, data->raw_size);
150 : int first_context_offset;
151 : memcpy(&first_context_offset, data->data + ContextSnapshotOffsetOffset(0),
152 60697 : kInt32Size);
153 60697 : CHECK_LT(first_context_offset, data->raw_size);
154 60697 : int startup_length = first_context_offset - startup_offset;
155 : const byte* startup_data =
156 60697 : reinterpret_cast<const byte*>(data->data + startup_offset);
157 60697 : return Vector<const byte>(startup_data, startup_length);
158 : }
159 :
160 106848 : Vector<const byte> Snapshot::ExtractContextData(const v8::StartupData* data,
161 : int index) {
162 106848 : int num_contexts = ExtractNumContexts(data);
163 106848 : CHECK_LT(index, num_contexts);
164 :
165 : int context_offset;
166 106848 : memcpy(&context_offset, data->data + ContextSnapshotOffsetOffset(index),
167 213696 : kInt32Size);
168 : int next_context_offset;
169 106848 : if (index == num_contexts - 1) {
170 106830 : next_context_offset = data->raw_size;
171 : } else {
172 : memcpy(&next_context_offset,
173 18 : data->data + ContextSnapshotOffsetOffset(index + 1), kInt32Size);
174 18 : CHECK_LT(next_context_offset, data->raw_size);
175 : }
176 :
177 : const byte* context_data =
178 106848 : reinterpret_cast<const byte*>(data->data + context_offset);
179 106848 : int context_length = next_context_offset - context_offset;
180 106848 : return Vector<const byte>(context_data, context_length);
181 : }
182 :
183 1450 : SnapshotData::SnapshotData(const Serializer* serializer) {
184 : DisallowHeapAllocation no_gc;
185 : List<Reservation> reservations;
186 290 : serializer->EncodeReservations(&reservations);
187 1160 : const List<byte>* payload = serializer->sink()->data();
188 :
189 : // Calculate sizes.
190 290 : int reservation_size = reservations.length() * kInt32Size;
191 580 : int size = kHeaderSize + reservation_size + payload->length();
192 :
193 : // Allocate backing store and create result data.
194 290 : AllocateData(size);
195 :
196 : // Set header values.
197 290 : SetMagicNumber(serializer->isolate());
198 290 : SetHeaderValue(kVersionHashOffset, Version::Hash());
199 290 : SetHeaderValue(kNumReservationsOffset, reservations.length());
200 290 : SetHeaderValue(kPayloadLengthOffset, payload->length());
201 :
202 : // Copy reservation chunk sizes.
203 290 : CopyBytes(data_ + kHeaderSize, reinterpret_cast<byte*>(reservations.begin()),
204 580 : reservation_size);
205 :
206 : // Copy serialized data.
207 290 : CopyBytes(data_ + kHeaderSize + reservation_size, payload->begin(),
208 870 : static_cast<size_t>(payload->length()));
209 290 : }
210 :
211 72 : bool SnapshotData::IsSane() {
212 167689 : return GetHeaderValue(kVersionHashOffset) == Version::Hash();
213 : }
214 :
215 72 : Vector<const SerializedData::Reservation> SnapshotData::Reservations() const {
216 : return Vector<const Reservation>(
217 : reinterpret_cast<const Reservation*>(data_ + kHeaderSize),
218 167713 : GetHeaderValue(kNumReservationsOffset));
219 : }
220 :
221 72 : Vector<const byte> SnapshotData::Payload() const {
222 335234 : int reservations_size = GetHeaderValue(kNumReservationsOffset) * kInt32Size;
223 167617 : const byte* payload = data_ + kHeaderSize + reservations_size;
224 167617 : int length = GetHeaderValue(kPayloadLengthOffset);
225 : DCHECK_EQ(data_ + size_, payload + length);
226 72 : return Vector<const byte>(payload, length);
227 : }
228 :
229 : } // namespace internal
230 : } // namespace v8
|