Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(615)

Side by Side Diff: runtime/bin/snapshot_utils.cc

Issue 2681193002: Factor out snapshot helpers from main.cc. (Closed)
Patch Set: . Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/bin/snapshot_utils.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 #include "bin/snapshot_utils.h"
6
7 #include "bin/dartutils.h"
8 #include "bin/error_exit.h"
9 #include "bin/extensions.h"
10 #include "bin/file.h"
11 #include "bin/platform.h"
12 #include "include/dart_api.h"
13 #include "platform/utils.h"
14
15 namespace dart {
16 namespace bin {
17
18 extern const char* kVmSnapshotDataSymbolName;
19 extern const char* kVmSnapshotInstructionsSymbolName;
20 extern const char* kIsolateSnapshotDataSymbolName;
21 extern const char* kIsolateSnapshotInstructionsSymbolName;
22
23 static const int64_t kAppSnapshotHeaderSize = 5 * kInt64Size;
24 static const int64_t kAppSnapshotMagicNumber = 0xf6f6dcdc;
25 static const int64_t kAppSnapshotPageSize = 4 * KB;
26
27 static bool ReadAppSnapshotBlobs(const char* script_name,
28 const uint8_t** vm_data_buffer,
29 const uint8_t** vm_instructions_buffer,
30 const uint8_t** isolate_data_buffer,
31 const uint8_t** isolate_instructions_buffer) {
32 File* file = File::Open(script_name, File::kRead);
33 if (file == NULL) {
34 return false;
35 }
36 if (file->Length() < kAppSnapshotHeaderSize) {
37 file->Release();
38 return false;
39 }
40 int64_t header[5];
41 ASSERT(sizeof(header) == kAppSnapshotHeaderSize);
42 if (!file->ReadFully(&header, kAppSnapshotHeaderSize)) {
43 file->Release();
44 return false;
45 }
46 if (header[0] != kAppSnapshotMagicNumber) {
47 file->Release();
48 return false;
49 }
50
51 int64_t vm_data_size = header[1];
52 int64_t vm_data_position =
53 Utils::RoundUp(file->Position(), kAppSnapshotPageSize);
54 int64_t vm_instructions_size = header[2];
55 int64_t vm_instructions_position = vm_data_position + vm_data_size;
56 if (vm_instructions_size != 0) {
57 vm_instructions_position =
58 Utils::RoundUp(vm_instructions_position, kAppSnapshotPageSize);
59 }
60 int64_t isolate_data_size = header[3];
61 int64_t isolate_data_position = Utils::RoundUp(
62 vm_instructions_position + vm_instructions_size, kAppSnapshotPageSize);
63 int64_t isolate_instructions_size = header[4];
64 int64_t isolate_instructions_position =
65 isolate_data_position + isolate_data_size;
66 if (isolate_instructions_size != 0) {
67 isolate_instructions_position =
68 Utils::RoundUp(isolate_instructions_position, kAppSnapshotPageSize);
69 }
70
71 if (vm_data_size != 0) {
72 *vm_data_buffer = reinterpret_cast<const uint8_t*>(
73 file->Map(File::kReadOnly, vm_data_position, vm_data_size));
74 if (vm_data_buffer == NULL) {
75 Log::PrintErr("Failed to memory map snapshot\n");
76 Platform::Exit(kErrorExitCode);
77 }
78 }
79
80 if (vm_instructions_size != 0) {
81 *vm_instructions_buffer = reinterpret_cast<const uint8_t*>(file->Map(
82 File::kReadExecute, vm_instructions_position, vm_instructions_size));
83 if (*vm_instructions_buffer == NULL) {
84 Log::PrintErr("Failed to memory map snapshot\n");
85 Platform::Exit(kErrorExitCode);
86 }
87 }
88
89 *isolate_data_buffer = reinterpret_cast<const uint8_t*>(
90 file->Map(File::kReadOnly, isolate_data_position, isolate_data_size));
91 if (isolate_data_buffer == NULL) {
92 Log::PrintErr("Failed to memory map snapshot\n");
93 Platform::Exit(kErrorExitCode);
94 }
95
96 if (isolate_instructions_size == 0) {
97 *isolate_instructions_buffer = NULL;
98 } else {
99 *isolate_instructions_buffer = reinterpret_cast<const uint8_t*>(
100 file->Map(File::kReadExecute, isolate_instructions_position,
101 isolate_instructions_size));
102 if (*isolate_instructions_buffer == NULL) {
103 Log::PrintErr("Failed to memory map snapshot\n");
104 Platform::Exit(kErrorExitCode);
105 }
106 }
107
108 file->Release();
109 return true;
110 }
111
112
113 #if defined(DART_PRECOMPILED_RUNTIME)
114 static bool ReadAppSnapshotDynamicLibrary(
115 const char* script_name,
116 const uint8_t** vm_data_buffer,
117 const uint8_t** vm_instructions_buffer,
118 const uint8_t** isolate_data_buffer,
119 const uint8_t** isolate_instructions_buffer) {
120 void* library = Extensions::LoadExtensionLibrary(script_name);
121 if (library == NULL) {
122 return false;
123 }
124
125 *vm_data_buffer = reinterpret_cast<const uint8_t*>(
126 Extensions::ResolveSymbol(library, kVmSnapshotDataSymbolName));
127 if (*vm_data_buffer == NULL) {
128 Log::PrintErr("Failed to resolve symbol '%s'\n", kVmSnapshotDataSymbolName);
129 Platform::Exit(kErrorExitCode);
130 }
131
132 *vm_instructions_buffer = reinterpret_cast<const uint8_t*>(
133 Extensions::ResolveSymbol(library, kVmSnapshotInstructionsSymbolName));
134 if (*vm_instructions_buffer == NULL) {
135 Log::PrintErr("Failed to resolve symbol '%s'\n",
136 kVmSnapshotInstructionsSymbolName);
137 Platform::Exit(kErrorExitCode);
138 }
139
140 *isolate_data_buffer = reinterpret_cast<const uint8_t*>(
141 Extensions::ResolveSymbol(library, kIsolateSnapshotDataSymbolName));
142 if (*isolate_data_buffer == NULL) {
143 Log::PrintErr("Failed to resolve symbol '%s'\n",
144 kIsolateSnapshotDataSymbolName);
145 Platform::Exit(kErrorExitCode);
146 }
147
148 *isolate_instructions_buffer =
149 reinterpret_cast<const uint8_t*>(Extensions::ResolveSymbol(
150 library, kIsolateSnapshotInstructionsSymbolName));
151 if (*isolate_instructions_buffer == NULL) {
152 Log::PrintErr("Failed to resolve symbol '%s'\n",
153 kIsolateSnapshotInstructionsSymbolName);
154 Platform::Exit(kErrorExitCode);
155 }
156
157 return true;
158 }
159 #endif // defined(DART_PRECOMPILED_RUNTIME)
160
161
162 bool Snapshot::ReadAppSnapshot(const char* script_name,
163 const uint8_t** vm_data_buffer,
164 const uint8_t** vm_instructions_buffer,
165 const uint8_t** isolate_data_buffer,
166 const uint8_t** isolate_instructions_buffer) {
167 if (File::GetType(script_name, true) != File::kIsFile) {
168 // If 'script_name' refers to a pipe, don't read to check for an app
169 // snapshot since we cannot rewind if it isn't (and couldn't mmap it in
170 // anyway if it was).
171 return false;
172 }
173 if (ReadAppSnapshotBlobs(script_name, vm_data_buffer, vm_instructions_buffer,
174 isolate_data_buffer, isolate_instructions_buffer)) {
175 return true;
176 }
177 #if defined(DART_PRECOMPILED_RUNTIME)
178 // For testing AOT with the standalone embedder, we also support loading
179 // from a dynamic library to simulate what happens on iOS.
180 return ReadAppSnapshotDynamicLibrary(
181 script_name, vm_data_buffer, vm_instructions_buffer, isolate_data_buffer,
182 isolate_instructions_buffer);
183 #else
184 return false;
185 #endif // defined(DART_PRECOMPILED_RUNTIME)
186 }
187
188
189 static void WriteSnapshotFile(const char* filename,
190 bool write_magic_number,
191 const uint8_t* buffer,
192 const intptr_t size) {
193 File* file = File::Open(filename, File::kWriteTruncate);
194 if (file == NULL) {
195 ErrorExit(kErrorExitCode, "Unable to open file %s for writing snapshot\n",
196 filename);
197 }
198
199 if (write_magic_number) {
200 // Write the magic number to indicate file is a script snapshot.
201 DartUtils::WriteMagicNumber(file);
202 }
203
204 if (!file->WriteFully(buffer, size)) {
205 ErrorExit(kErrorExitCode, "Unable to write file %s for writing snapshot\n",
206 filename);
207 }
208 file->Release();
209 }
210
211
212 static bool WriteInt64(File* file, int64_t size) {
213 return file->WriteFully(&size, sizeof(size));
214 }
215
216
217 static void WriteAppSnapshot(const char* filename,
218 uint8_t* vm_data_buffer,
219 intptr_t vm_data_size,
220 uint8_t* vm_instructions_buffer,
221 intptr_t vm_instructions_size,
222 uint8_t* isolate_data_buffer,
223 intptr_t isolate_data_size,
224 uint8_t* isolate_instructions_buffer,
225 intptr_t isolate_instructions_size) {
226 File* file = File::Open(filename, File::kWriteTruncate);
227 if (file == NULL) {
228 ErrorExit(kErrorExitCode, "Unable to write snapshot file '%s'\n", filename);
229 }
230
231 file->WriteFully(&kAppSnapshotMagicNumber, sizeof(kAppSnapshotMagicNumber));
232 WriteInt64(file, vm_data_size);
233 WriteInt64(file, vm_instructions_size);
234 WriteInt64(file, isolate_data_size);
235 WriteInt64(file, isolate_instructions_size);
236 ASSERT(file->Position() == kAppSnapshotHeaderSize);
237
238 file->SetPosition(Utils::RoundUp(file->Position(), kAppSnapshotPageSize));
239 if (!file->WriteFully(vm_data_buffer, vm_data_size)) {
240 ErrorExit(kErrorExitCode, "Unable to write snapshot file '%s'\n", filename);
241 }
242
243 if (vm_instructions_size != 0) {
244 file->SetPosition(Utils::RoundUp(file->Position(), kAppSnapshotPageSize));
245 if (!file->WriteFully(vm_instructions_buffer, vm_instructions_size)) {
246 ErrorExit(kErrorExitCode, "Unable to write snapshot file '%s'\n",
247 filename);
248 }
249 }
250
251 file->SetPosition(Utils::RoundUp(file->Position(), kAppSnapshotPageSize));
252 if (!file->WriteFully(isolate_data_buffer, isolate_data_size)) {
253 ErrorExit(kErrorExitCode, "Unable to write snapshot file '%s'\n", filename);
254 }
255
256 if (isolate_instructions_size != 0) {
257 file->SetPosition(Utils::RoundUp(file->Position(), kAppSnapshotPageSize));
258 if (!file->WriteFully(isolate_instructions_buffer,
259 isolate_instructions_size)) {
260 ErrorExit(kErrorExitCode, "Unable to write snapshot file '%s'\n",
261 filename);
262 }
263 }
264
265 file->Flush();
266 file->Release();
267 }
268
269
270 void Snapshot::GenerateScript(const char* snapshot_filename) {
271 // First create a snapshot.
272 uint8_t* buffer = NULL;
273 intptr_t size = 0;
274 Dart_Handle result = Dart_CreateScriptSnapshot(&buffer, &size);
275 if (Dart_IsError(result)) {
276 ErrorExit(kErrorExitCode, "%s\n", Dart_GetError(result));
277 }
278
279 WriteSnapshotFile(snapshot_filename, true, buffer, size);
280 }
281
282
283 void Snapshot::GenerateAppJIT(const char* snapshot_filename) {
284 #if defined(TARGET_ARCH_X64)
285 uint8_t* isolate_data_buffer = NULL;
286 intptr_t isolate_data_size = 0;
287 uint8_t* isolate_instructions_buffer = NULL;
288 intptr_t isolate_instructions_size = 0;
289 Dart_Handle result = Dart_CreateAppJITSnapshotAsBlobs(
290 &isolate_data_buffer, &isolate_data_size, &isolate_instructions_buffer,
291 &isolate_instructions_size);
292 if (Dart_IsError(result)) {
293 ErrorExit(kErrorExitCode, "%s\n", Dart_GetError(result));
294 }
295 WriteAppSnapshot(snapshot_filename, NULL, 0, NULL, 0, isolate_data_buffer,
296 isolate_data_size, isolate_instructions_buffer,
297 isolate_instructions_size);
298 #else
299 uint8_t* isolate_buffer = NULL;
300 intptr_t isolate_size = 0;
301
302 Dart_Handle result =
303 Dart_CreateSnapshot(NULL, NULL, &isolate_buffer, &isolate_size);
304 if (Dart_IsError(result)) {
305 ErrorExit(kErrorExitCode, "%s\n", Dart_GetError(result));
306 }
307
308 WriteAppSnapshot(snapshot_filename, NULL, 0, NULL, 0, isolate_buffer,
309 isolate_size, NULL, 0);
310 #endif // defined(TARGET_ARCH_X64)
311 }
312
313
314 void Snapshot::GenerateAppAOTAsBlobs(const char* snapshot_filename) {
315 uint8_t* vm_data_buffer = NULL;
316 intptr_t vm_data_size = 0;
317 uint8_t* vm_instructions_buffer = NULL;
318 intptr_t vm_instructions_size = 0;
319 uint8_t* isolate_data_buffer = NULL;
320 intptr_t isolate_data_size = 0;
321 uint8_t* isolate_instructions_buffer = NULL;
322 intptr_t isolate_instructions_size = 0;
323 Dart_Handle result = Dart_CreateAppAOTSnapshotAsBlobs(
324 &vm_data_buffer, &vm_data_size, &vm_instructions_buffer,
325 &vm_instructions_size, &isolate_data_buffer, &isolate_data_size,
326 &isolate_instructions_buffer, &isolate_instructions_size);
327 if (Dart_IsError(result)) {
328 ErrorExit(kErrorExitCode, "%s\n", Dart_GetError(result));
329 }
330 WriteAppSnapshot(snapshot_filename, vm_data_buffer, vm_data_size,
331 vm_instructions_buffer, vm_instructions_size,
332 isolate_data_buffer, isolate_data_size,
333 isolate_instructions_buffer, isolate_instructions_size);
334 }
335
336
337 void Snapshot::GenerateAppAOTAsAssembly(const char* snapshot_filename) {
338 uint8_t* assembly_buffer = NULL;
339 intptr_t assembly_size = 0;
340 Dart_Handle result =
341 Dart_CreateAppAOTSnapshotAsAssembly(&assembly_buffer, &assembly_size);
342 if (Dart_IsError(result)) {
343 ErrorExit(kErrorExitCode, "%s\n", Dart_GetError(result));
344 }
345 WriteSnapshotFile(snapshot_filename, false, assembly_buffer, assembly_size);
346 }
347
348 } // namespace bin
349 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/bin/snapshot_utils.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698