OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 // Generate a snapshot file after loading all the scripts specified on the | 5 // Generate a snapshot file after loading all the scripts specified on the |
6 // command line. | 6 // command line. |
7 | 7 |
8 #include <stdio.h> | 8 #include <stdio.h> |
9 #include <stdlib.h> | 9 #include <stdlib.h> |
10 #include <string.h> | 10 #include <string.h> |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
53 Dart_ExitScope(); \ | 53 Dart_ExitScope(); \ |
54 Dart_ShutdownIsolate(); \ | 54 Dart_ShutdownIsolate(); \ |
55 exit(exit_code); \ | 55 exit(exit_code); \ |
56 } | 56 } |
57 | 57 |
58 | 58 |
59 // Global state that indicates whether a snapshot is to be created and | 59 // Global state that indicates whether a snapshot is to be created and |
60 // if so which file to write the snapshot into. | 60 // if so which file to write the snapshot into. |
61 static const char* vm_isolate_snapshot_filename = NULL; | 61 static const char* vm_isolate_snapshot_filename = NULL; |
62 static const char* isolate_snapshot_filename = NULL; | 62 static const char* isolate_snapshot_filename = NULL; |
63 static const char* instructions_snapshot_filename = NULL; | 63 static const char* assembly_filename = NULL; |
| 64 static const char* instructions_blob_filename = NULL; |
| 65 static const char* rodata_blob_filename = NULL; |
64 static const char* package_root = NULL; | 66 static const char* package_root = NULL; |
65 | 67 |
66 | 68 |
67 // Global state which contains a pointer to the script name for which | 69 // Global state which contains a pointer to the script name for which |
68 // a snapshot needs to be created (NULL would result in the creation | 70 // a snapshot needs to be created (NULL would result in the creation |
69 // of a generic snapshot that contains only the corelibs). | 71 // of a generic snapshot that contains only the corelibs). |
70 static char* app_script_name = NULL; | 72 static char* app_script_name = NULL; |
71 | 73 |
72 | 74 |
73 // Global state that captures the URL mappings specified on the command line. | 75 // Global state that captures the URL mappings specified on the command line. |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 static bool ProcessIsolateSnapshotOption(const char* option) { | 197 static bool ProcessIsolateSnapshotOption(const char* option) { |
196 const char* name = ProcessOption(option, "--isolate_snapshot="); | 198 const char* name = ProcessOption(option, "--isolate_snapshot="); |
197 if (name != NULL) { | 199 if (name != NULL) { |
198 isolate_snapshot_filename = name; | 200 isolate_snapshot_filename = name; |
199 return true; | 201 return true; |
200 } | 202 } |
201 return false; | 203 return false; |
202 } | 204 } |
203 | 205 |
204 | 206 |
205 static bool ProcessInstructionsSnapshotOption(const char* option) { | 207 static bool ProcessAssemblyOption(const char* option) { |
206 const char* name = ProcessOption(option, "--instructions_snapshot="); | 208 const char* name = ProcessOption(option, "--assembly="); |
207 if (name != NULL) { | 209 if (name != NULL) { |
208 instructions_snapshot_filename = name; | 210 assembly_filename = name; |
209 return true; | 211 return true; |
210 } | 212 } |
211 return false; | 213 return false; |
| 214 } |
| 215 |
| 216 |
| 217 static bool ProcessInstructionsBlobOption(const char* option) { |
| 218 const char* name = ProcessOption(option, "--instructions_blob="); |
| 219 if (name != NULL) { |
| 220 instructions_blob_filename = name; |
| 221 return true; |
| 222 } |
| 223 return false; |
| 224 } |
| 225 |
| 226 |
| 227 static bool ProcessRodataBlobOption(const char* option) { |
| 228 const char* name = ProcessOption(option, "--rodata_blob="); |
| 229 if (name != NULL) { |
| 230 rodata_blob_filename = name; |
| 231 return true; |
| 232 } |
| 233 return false; |
212 } | 234 } |
213 | 235 |
214 | 236 |
215 static bool ProcessEmbedderEntryPointsManifestOption(const char* option) { | 237 static bool ProcessEmbedderEntryPointsManifestOption(const char* option) { |
216 const char* name = ProcessOption(option, "--embedder_entry_points_manifest="); | 238 const char* name = ProcessOption(option, "--embedder_entry_points_manifest="); |
217 if (name != NULL) { | 239 if (name != NULL) { |
218 entry_points_files->AddArgument(name); | 240 entry_points_files->AddArgument(name); |
219 return true; | 241 return true; |
220 } | 242 } |
221 return false; | 243 return false; |
(...skipping 19 matching lines...) Expand all Loading... |
241 mapping = ProcessOption(option, "--url-mapping="); | 263 mapping = ProcessOption(option, "--url-mapping="); |
242 } | 264 } |
243 if (mapping != NULL) { | 265 if (mapping != NULL) { |
244 url_mapping->AddArgument(mapping); | 266 url_mapping->AddArgument(mapping); |
245 return true; | 267 return true; |
246 } | 268 } |
247 return false; | 269 return false; |
248 } | 270 } |
249 | 271 |
250 | 272 |
| 273 static bool IsSnapshottingForPrecompilation() { |
| 274 return (assembly_filename != NULL) || (instructions_blob_filename != NULL); |
| 275 } |
| 276 |
| 277 |
251 // Parse out the command line arguments. Returns -1 if the arguments | 278 // Parse out the command line arguments. Returns -1 if the arguments |
252 // are incorrect, 0 otherwise. | 279 // are incorrect, 0 otherwise. |
253 static int ParseArguments(int argc, | 280 static int ParseArguments(int argc, |
254 char** argv, | 281 char** argv, |
255 CommandLineOptions* vm_options, | 282 CommandLineOptions* vm_options, |
256 char** script_name) { | 283 char** script_name) { |
257 const char* kPrefix = "-"; | 284 const char* kPrefix = "-"; |
258 const intptr_t kPrefixLen = strlen(kPrefix); | 285 const intptr_t kPrefixLen = strlen(kPrefix); |
259 | 286 |
260 // Skip the binary name. | 287 // Skip the binary name. |
261 int i = 1; | 288 int i = 1; |
262 | 289 |
263 // Parse out the vm options. | 290 // Parse out the vm options. |
264 while ((i < argc) && IsValidFlag(argv[i], kPrefix, kPrefixLen)) { | 291 while ((i < argc) && IsValidFlag(argv[i], kPrefix, kPrefixLen)) { |
265 if (ProcessVmIsolateSnapshotOption(argv[i]) || | 292 if (ProcessVmIsolateSnapshotOption(argv[i]) || |
266 ProcessIsolateSnapshotOption(argv[i]) || | 293 ProcessIsolateSnapshotOption(argv[i]) || |
267 ProcessInstructionsSnapshotOption(argv[i]) || | 294 ProcessAssemblyOption(argv[i]) || |
| 295 ProcessInstructionsBlobOption(argv[i]) || |
| 296 ProcessRodataBlobOption(argv[i]) || |
268 ProcessEmbedderEntryPointsManifestOption(argv[i]) || | 297 ProcessEmbedderEntryPointsManifestOption(argv[i]) || |
269 ProcessURLmappingOption(argv[i]) || | 298 ProcessURLmappingOption(argv[i]) || |
270 ProcessPackageRootOption(argv[i]) || | 299 ProcessPackageRootOption(argv[i]) || |
271 ProcessEnvironmentOption(argv[i])) { | 300 ProcessEnvironmentOption(argv[i])) { |
272 i += 1; | 301 i += 1; |
273 continue; | 302 continue; |
274 } | 303 } |
275 vm_options->AddArgument(argv[i]); | 304 vm_options->AddArgument(argv[i]); |
276 i += 1; | 305 i += 1; |
277 } | 306 } |
278 | 307 |
279 // Get the script name. | 308 // Get the script name. |
280 if (i < argc) { | 309 if (i < argc) { |
281 *script_name = argv[i]; | 310 *script_name = argv[i]; |
282 i += 1; | 311 i += 1; |
283 } else { | 312 } else { |
284 *script_name = NULL; | 313 *script_name = NULL; |
285 } | 314 } |
286 | 315 |
287 if (vm_isolate_snapshot_filename == NULL) { | 316 if (vm_isolate_snapshot_filename == NULL) { |
288 Log::PrintErr("No vm isolate snapshot output file specified.\n\n"); | 317 Log::PrintErr("No vm isolate snapshot output file specified.\n\n"); |
289 return -1; | 318 return -1; |
290 } | 319 } |
291 | 320 |
292 if (isolate_snapshot_filename == NULL) { | 321 if (isolate_snapshot_filename == NULL) { |
293 Log::PrintErr("No isolate snapshot output file specified.\n\n"); | 322 Log::PrintErr("No isolate snapshot output file specified.\n\n"); |
294 return -1; | 323 return -1; |
295 } | 324 } |
296 | 325 |
297 if ((instructions_snapshot_filename != NULL) && | 326 bool precompiled_as_assembly = assembly_filename != NULL; |
| 327 bool precompiled_as_blobs = (instructions_blob_filename != NULL) || |
| 328 (rodata_blob_filename != NULL); |
| 329 if (precompiled_as_assembly && precompiled_as_blobs) { |
| 330 Log::PrintErr( |
| 331 "Cannot request a precompiled snapshot simultaneously as " |
| 332 "assembly (--assembly=<output.file>) and as blobs " |
| 333 "(--instructions-blob=<output.file> and " |
| 334 "--rodata-blob=<output.file>)\n\n"); |
| 335 return -1; |
| 336 } |
| 337 if ((instructions_blob_filename != NULL) != (rodata_blob_filename != NULL)) { |
| 338 Log::PrintErr( |
| 339 "Requesting a precompiled snapshot as blobs requires both " |
| 340 "(--instructions-blob=<output.file> and " |
| 341 "--rodata-blob=<output.file>)\n\n"); |
| 342 return -1; |
| 343 } |
| 344 if (IsSnapshottingForPrecompilation() && |
298 (entry_points_files->count() == 0)) { | 345 (entry_points_files->count() == 0)) { |
299 Log::PrintErr( | 346 Log::PrintErr( |
300 "Specifying an instructions snapshot filename indicates precompilation" | 347 "Specifying an instructions snapshot filename indicates precompilation" |
301 ". But no embedder entry points manifest was specified.\n\n"); | 348 ". But no embedder entry points manifest was specified.\n\n"); |
302 return -1; | 349 return -1; |
303 } | 350 } |
304 | 351 |
305 if ((entry_points_files->count() > 0) && | |
306 (instructions_snapshot_filename == NULL)) { | |
307 Log::PrintErr( | |
308 "Specifying the embedder entry points manifest indicates " | |
309 "precompilation. But no instuctions snapshot was specified.\n\n"); | |
310 return -1; | |
311 } | |
312 | |
313 return 0; | 352 return 0; |
314 } | 353 } |
315 | 354 |
316 | 355 |
317 static bool IsSnapshottingForPrecompilation(void) { | |
318 return (entry_points_files->count() > 0) && | |
319 (instructions_snapshot_filename != NULL); | |
320 } | |
321 | |
322 | |
323 static void WriteSnapshotFile(const char* filename, | 356 static void WriteSnapshotFile(const char* filename, |
324 const uint8_t* buffer, | 357 const uint8_t* buffer, |
325 const intptr_t size) { | 358 const intptr_t size) { |
326 File* file = File::Open(filename, File::kWriteTruncate); | 359 File* file = File::Open(filename, File::kWriteTruncate); |
327 ASSERT(file != NULL); | 360 ASSERT(file != NULL); |
328 if (!file->WriteFully(buffer, size)) { | 361 if (!file->WriteFully(buffer, size)) { |
329 Log::PrintErr("Error: Failed to write snapshot file.\n\n"); | 362 Log::PrintErr("Error: Failed to write snapshot file.\n\n"); |
330 } | 363 } |
331 file->Release(); | 364 file->Release(); |
332 } | 365 } |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
576 "Usage: \n" | 609 "Usage: \n" |
577 " gen_snapshot [<vm-flags>] [<options>] [<dart-script-file>] \n" | 610 " gen_snapshot [<vm-flags>] [<options>] [<dart-script-file>] \n" |
578 " \n" | 611 " \n" |
579 " Writes a snapshot of <dart-script-file> to the specified snapshot files. \n" | 612 " Writes a snapshot of <dart-script-file> to the specified snapshot files. \n" |
580 " If no <dart-script-file> is passed, a generic snapshot of all the corelibs\n" | 613 " If no <dart-script-file> is passed, a generic snapshot of all the corelibs\n" |
581 " is created. It is required to specify the VM isolate snapshot and the \n" | 614 " is created. It is required to specify the VM isolate snapshot and the \n" |
582 " isolate snapshot. The other flags are related to precompilation and are \n" | 615 " isolate snapshot. The other flags are related to precompilation and are \n" |
583 " optional. \n" | 616 " optional. \n" |
584 " \n" | 617 " \n" |
585 " Precompilation: \n" | 618 " Precompilation: \n" |
586 " In order to configure the snapshotter for precompilation, both the \n" | 619 " In order to configure the snapshotter for precompilation, either \n" |
587 " instructions snapshot and embedder entry points manifest must be \n" | 620 " --assembly=outputfile or --instructions_blob=outputfile1 and \n" |
588 " specified. Assembly for the target architecture will be dumped into the \n" | 621 " --rodata_blob=outputfile2 must be specified. If the former is choosen, \n" |
589 " instructions snapshot. This must be linked into the target binary in a \n" | 622 " assembly for the target architecture will be output into the given file, \n" |
590 " separate step. The embedder entry points manifest lists the standalone \n" | 623 " which must be compiled separately and either statically linked or \n" |
591 " entry points into the VM. Not specifying these will cause the tree shaker \n" | 624 " dynamically loaded in the target executable. The symbols \n" |
592 " to disregard the same as being used. The format of this manifest is as \n" | 625 " kInstructionsSnapshot and kDataSnapshot must be passed to Dart_Initialize.\n" |
593 " follows. Each line in the manifest is a comma separated list of three \n" | 626 " If the latter is choosen, binary data is output into the given files, \n" |
594 " elements. The first entry is the library URI, the second entry is the \n" | 627 " which should be mmapped and passed to Dart_Initialize, with the \n" |
595 " class name and the final entry the function name. The file must be \n" | 628 " instruction blob being mapped as executable. \n" |
596 " terminated with a newline charater. \n" | 629 " In both cases, a entry points manifest must be given to list the places \n" |
| 630 " in the Dart program the embedder calls from the C API (Dart_Invoke, etc). \n" |
| 631 " Not specifying these may cause the tree shaker to remove them from the \n" |
| 632 " program. The format of this manifest is as follows. Each line in the \n" |
| 633 " manifest is a comma separated list of three elements. The first entry is \n" |
| 634 " the library URI, the second entry is the class name and the final entry \n" |
| 635 " the function name. The file must be terminated with a newline charater. \n" |
597 " \n" | 636 " \n" |
598 " Example: \n" | 637 " Example: \n" |
599 " dart:something,SomeClass,doSomething \n" | 638 " dart:something,SomeClass,doSomething \n" |
600 " \n" | 639 " \n" |
601 " Supported options: \n" | 640 " Supported options: \n" |
602 " --vm_isolate_snapshot=<file> A full snapshot is a compact \n" | 641 " --vm_isolate_snapshot=<file> A full snapshot is a compact \n" |
603 " --isolate_snapshot=<file> representation of the dart vm isolate \n" | 642 " --isolate_snapshot=<file> representation of the dart vm isolate \n" |
604 " heap and dart isolate heap states. \n" | 643 " heap and dart isolate heap states. \n" |
605 " Both these options are required \n" | 644 " Both these options are required \n" |
606 " \n" | 645 " \n" |
607 " --package_root=<path> Where to find packages, that is, \n" | 646 " --package_root=<path> Where to find packages, that is, \n" |
608 " package:... imports. \n" | 647 " package:... imports. \n" |
609 " \n" | 648 " \n" |
610 " --url_mapping=<mapping> Uses the URL mapping(s) specified on \n" | 649 " --url_mapping=<mapping> Uses the URL mapping(s) specified on \n" |
611 " the command line to load the \n" | 650 " the command line to load the \n" |
612 " libraries. \n" | 651 " libraries. \n" |
613 " \n" | 652 " \n" |
614 " --instructions_snapshot=<file> (Precompilation only) Contains the \n" | 653 " --assembly=<file> (Precompilation only) Contains the \n" |
615 " assembly that must be linked into \n" | 654 " assembly that must be linked into \n" |
616 " the target binary \n" | 655 " the target binary \n" |
617 " \n" | 656 " \n" |
618 " --embedder_entry_points_manifest=<file> (Precompilation only) Contains \n" | 657 " --instructions_blob=<file> (Precompilation only) Contains the \n" |
619 " the stanalone embedder entry points\n"); | 658 " --rodata_blob=<file> instructions and read-only data that \n" |
| 659 " must be mapped into the target binary \n" |
| 660 " \n" |
| 661 " --embedder_entry_points_manifest=<file> (Precompilation or app \n" |
| 662 " snapshots) Contains embedder's entry \n" |
| 663 " points into Dart code from the C API. \n" |
| 664 "\n"); |
620 } | 665 } |
621 | 666 |
622 | 667 |
623 static void VerifyLoaded(Dart_Handle library) { | 668 static void VerifyLoaded(Dart_Handle library) { |
624 if (Dart_IsError(library)) { | 669 if (Dart_IsError(library)) { |
625 const char* err_msg = Dart_GetError(library); | 670 const char* err_msg = Dart_GetError(library); |
626 Log::PrintErr("Errors encountered while loading: %s\n", err_msg); | 671 Log::PrintErr("Errors encountered while loading: %s\n", err_msg); |
627 CHECK_RESULT(library); | 672 CHECK_RESULT(library); |
628 } | 673 } |
629 ASSERT(Dart_IsLibrary(library)); | 674 ASSERT(Dart_IsLibrary(library)); |
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
987 | 1032 |
988 | 1033 |
989 static void CreateAndWritePrecompiledSnapshot( | 1034 static void CreateAndWritePrecompiledSnapshot( |
990 Dart_QualifiedFunctionName* standalone_entry_points) { | 1035 Dart_QualifiedFunctionName* standalone_entry_points) { |
991 ASSERT(IsSnapshottingForPrecompilation()); | 1036 ASSERT(IsSnapshottingForPrecompilation()); |
992 Dart_Handle result; | 1037 Dart_Handle result; |
993 uint8_t* vm_isolate_buffer = NULL; | 1038 uint8_t* vm_isolate_buffer = NULL; |
994 intptr_t vm_isolate_size = 0; | 1039 intptr_t vm_isolate_size = 0; |
995 uint8_t* isolate_buffer = NULL; | 1040 uint8_t* isolate_buffer = NULL; |
996 intptr_t isolate_size = 0; | 1041 intptr_t isolate_size = 0; |
997 uint8_t* instructions_buffer = NULL; | 1042 uint8_t* assembly_buffer = NULL; |
998 intptr_t instructions_size = 0; | 1043 intptr_t assembly_size = 0; |
| 1044 uint8_t* instructions_blob_buffer = NULL; |
| 1045 intptr_t instructions_blob_size = 0; |
| 1046 uint8_t* rodata_blob_buffer = NULL; |
| 1047 intptr_t rodata_blob_size = 0; |
999 | 1048 |
1000 // Precompile with specified embedder entry points | 1049 // Precompile with specified embedder entry points |
1001 result = Dart_Precompile(standalone_entry_points, true); | 1050 result = Dart_Precompile(standalone_entry_points, true); |
1002 CHECK_RESULT(result); | 1051 CHECK_RESULT(result); |
1003 | 1052 |
1004 // Create a precompiled snapshot. This gives us an instruction buffer with | 1053 // Create a precompiled snapshot. |
1005 // machine code | 1054 bool as_assembly = assembly_filename != NULL; |
1006 result = Dart_CreatePrecompiledSnapshot(&vm_isolate_buffer, | 1055 if (as_assembly) { |
1007 &vm_isolate_size, | 1056 result = Dart_CreatePrecompiledSnapshotAssembly(&vm_isolate_buffer, |
1008 &isolate_buffer, | 1057 &vm_isolate_size, |
1009 &isolate_size, | 1058 &isolate_buffer, |
1010 &instructions_buffer, | 1059 &isolate_size, |
1011 &instructions_size); | 1060 &assembly_buffer, |
1012 CHECK_RESULT(result); | 1061 &assembly_size); |
| 1062 CHECK_RESULT(result); |
| 1063 } else { |
| 1064 result = Dart_CreatePrecompiledSnapshotBlob(&vm_isolate_buffer, |
| 1065 &vm_isolate_size, |
| 1066 &isolate_buffer, |
| 1067 &isolate_size, |
| 1068 &instructions_blob_buffer, |
| 1069 &instructions_blob_size, |
| 1070 &rodata_blob_buffer, |
| 1071 &rodata_blob_size); |
| 1072 CHECK_RESULT(result); |
| 1073 } |
1013 | 1074 |
1014 // Now write the vm isolate, isolate and instructions snapshots out to the | 1075 // Now write the snapshot pieces out to the specified files and exit. |
1015 // specified files and exit. | |
1016 WriteSnapshotFile(vm_isolate_snapshot_filename, | 1076 WriteSnapshotFile(vm_isolate_snapshot_filename, |
1017 vm_isolate_buffer, | 1077 vm_isolate_buffer, |
1018 vm_isolate_size); | 1078 vm_isolate_size); |
1019 WriteSnapshotFile(isolate_snapshot_filename, | 1079 WriteSnapshotFile(isolate_snapshot_filename, |
1020 isolate_buffer, | 1080 isolate_buffer, |
1021 isolate_size); | 1081 isolate_size); |
1022 WriteSnapshotFile(instructions_snapshot_filename, | 1082 if (as_assembly) { |
1023 instructions_buffer, | 1083 WriteSnapshotFile(assembly_filename, |
1024 instructions_size); | 1084 assembly_buffer, |
| 1085 assembly_size); |
| 1086 } else { |
| 1087 WriteSnapshotFile(instructions_blob_filename, |
| 1088 instructions_blob_buffer, |
| 1089 instructions_blob_size); |
| 1090 WriteSnapshotFile(rodata_blob_filename, |
| 1091 rodata_blob_buffer, |
| 1092 rodata_blob_size); |
| 1093 } |
1025 Dart_ExitScope(); | 1094 Dart_ExitScope(); |
1026 | 1095 |
1027 // Shutdown the isolate. | 1096 // Shutdown the isolate. |
1028 Dart_ShutdownIsolate(); | 1097 Dart_ShutdownIsolate(); |
1029 } | 1098 } |
1030 | 1099 |
1031 | 1100 |
1032 static void SetupForUriResolution() { | 1101 static void SetupForUriResolution() { |
1033 // Set up the library tag handler for this isolate. | 1102 // Set up the library tag handler for this isolate. |
1034 Dart_Handle result = Dart_SetLibraryTagHandler(DartUtils::LibraryTagHandler); | 1103 Dart_Handle result = Dart_SetLibraryTagHandler(DartUtils::LibraryTagHandler); |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1280 EventHandler::Stop(); | 1349 EventHandler::Stop(); |
1281 return 0; | 1350 return 0; |
1282 } | 1351 } |
1283 | 1352 |
1284 } // namespace bin | 1353 } // namespace bin |
1285 } // namespace dart | 1354 } // namespace dart |
1286 | 1355 |
1287 int main(int argc, char** argv) { | 1356 int main(int argc, char** argv) { |
1288 return dart::bin::main(argc, argv); | 1357 return dart::bin::main(argc, argv); |
1289 } | 1358 } |
OLD | NEW |