Index: runtime/bin/gen_snapshot.cc |
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc |
index 44b09a65ef1278d1c0416dbe081e40d82927d3af..7783422e95be92d2a8933b94a2da35d2a4022c62 100644 |
--- a/runtime/bin/gen_snapshot.cc |
+++ b/runtime/bin/gen_snapshot.cc |
@@ -60,7 +60,9 @@ static const int kRestartRequestExitCode = 1000; |
// if so which file to write the snapshot into. |
static const char* vm_isolate_snapshot_filename = NULL; |
static const char* isolate_snapshot_filename = NULL; |
-static const char* instructions_snapshot_filename = NULL; |
+static const char* assembly_filename = NULL; |
+static const char* instructions_blob_filename = NULL; |
+static const char* rodata_blob_filename = NULL; |
static const char* package_root = NULL; |
@@ -202,10 +204,30 @@ static bool ProcessIsolateSnapshotOption(const char* option) { |
} |
-static bool ProcessInstructionsSnapshotOption(const char* option) { |
- const char* name = ProcessOption(option, "--instructions_snapshot="); |
+static bool ProcessAssemblyOption(const char* option) { |
+ const char* name = ProcessOption(option, "--assembly="); |
if (name != NULL) { |
- instructions_snapshot_filename = name; |
+ assembly_filename = name; |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+ |
+static bool ProcessInstructionsBlobOption(const char* option) { |
+ const char* name = ProcessOption(option, "--instructions_blob="); |
+ if (name != NULL) { |
+ instructions_blob_filename = name; |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+ |
+static bool ProcessRodataBlobOption(const char* option) { |
+ const char* name = ProcessOption(option, "--rodata_blob="); |
+ if (name != NULL) { |
+ rodata_blob_filename = name; |
return true; |
} |
return false; |
@@ -248,6 +270,11 @@ static bool ProcessURLmappingOption(const char* option) { |
} |
+static bool IsSnapshottingForPrecompilation() { |
+ return (assembly_filename != NULL) || (instructions_blob_filename != NULL); |
+} |
+ |
+ |
// Parse out the command line arguments. Returns -1 if the arguments |
// are incorrect, 0 otherwise. |
static int ParseArguments(int argc, |
@@ -264,7 +291,9 @@ static int ParseArguments(int argc, |
while ((i < argc) && IsValidFlag(argv[i], kPrefix, kPrefixLen)) { |
if (ProcessVmIsolateSnapshotOption(argv[i]) || |
ProcessIsolateSnapshotOption(argv[i]) || |
- ProcessInstructionsSnapshotOption(argv[i]) || |
+ ProcessAssemblyOption(argv[i]) || |
+ ProcessInstructionsBlobOption(argv[i]) || |
+ ProcessRodataBlobOption(argv[i]) || |
ProcessEmbedderEntryPointsManifestOption(argv[i]) || |
ProcessURLmappingOption(argv[i]) || |
ProcessPackageRootOption(argv[i]) || |
@@ -294,19 +323,29 @@ static int ParseArguments(int argc, |
return -1; |
} |
- if ((instructions_snapshot_filename != NULL) && |
- (entry_points_files->count() == 0)) { |
+ bool precompiled_as_assembly = assembly_filename != NULL; |
+ bool precompiled_as_blobs = (instructions_blob_filename != NULL) || |
+ (rodata_blob_filename != NULL); |
+ if (precompiled_as_assembly && precompiled_as_blobs) { |
Log::PrintErr( |
- "Specifying an instructions snapshot filename indicates precompilation" |
- ". But no embedder entry points manifest was specified.\n\n"); |
+ "Cannot request a precompiled snapshot simultaneously as " |
+ "assembly (--assembly=<output.file>) and as blobs " |
+ "(--instructions-blob=<output.file> and " |
+ "--rodata-blob=<output.file>)\n\n"); |
return -1; |
} |
- |
- if ((entry_points_files->count() > 0) && |
- (instructions_snapshot_filename == NULL)) { |
+ if ((instructions_blob_filename != NULL) != (rodata_blob_filename != NULL)) { |
+ Log::PrintErr( |
+ "Requesting a precompiled snapshot as blobs requires both " |
+ "(--instructions-blob=<output.file> and " |
+ "--rodata-blob=<output.file>)\n\n"); |
+ return -1; |
+ } |
+ if (IsSnapshottingForPrecompilation() && |
+ (entry_points_files->count() == 0)) { |
Log::PrintErr( |
- "Specifying the embedder entry points manifest indicates " |
- "precompilation. But no instuctions snapshot was specified.\n\n"); |
+ "Specifying an instructions snapshot filename indicates precompilation" |
+ ". But no embedder entry points manifest was specified.\n\n"); |
return -1; |
} |
@@ -314,12 +353,6 @@ static int ParseArguments(int argc, |
} |
-static bool IsSnapshottingForPrecompilation(void) { |
- return (entry_points_files->count() > 0) && |
- (instructions_snapshot_filename != NULL); |
-} |
- |
- |
static void WriteSnapshotFile(const char* filename, |
const uint8_t* buffer, |
const intptr_t size) { |
@@ -583,17 +616,23 @@ static void PrintUsage() { |
" optional. \n" |
" \n" |
" Precompilation: \n" |
-" In order to configure the snapshotter for precompilation, both the \n" |
-" instructions snapshot and embedder entry points manifest must be \n" |
-" specified. Assembly for the target architecture will be dumped into the \n" |
-" instructions snapshot. This must be linked into the target binary in a \n" |
-" separate step. The embedder entry points manifest lists the standalone \n" |
-" entry points into the VM. Not specifying these will cause the tree shaker \n" |
-" to disregard the same as being used. The format of this manifest is as \n" |
-" follows. Each line in the manifest is a comma separated list of three \n" |
-" elements. The first entry is the library URI, the second entry is the \n" |
-" class name and the final entry the function name. The file must be \n" |
-" terminated with a newline charater. \n" |
+" In order to configure the snapshotter for precompilation, either \n" |
+" --assembly=outputfile or --instructions_blob=outputfile1 and \n" |
+" --rodata_blob=outputfile2 must be specified. If the former is choosen, \n" |
+" assembly for the target architecture will be output into the given file, \n" |
+" which must be compiled separately and either statically linked or \n" |
+" dynamically loaded in the target executable. The symbols \n" |
+" kInstructionsSnapshot and kDataSnapshot must be passed to Dart_Initialize.\n" |
+" If the latter is choosen, binary data is output into the given files, \n" |
+" which should be mmapped and passed to Dart_Initialize, with the \n" |
+" instruction blob being mapped as executable. \n" |
+" In both cases, a entry points manifest must be given to list the places \n" |
+" in the Dart program the embedder calls from the C API (Dart_Invoke, etc). \n" |
+" Not specifying these may cause the tree shaker to remove them from the \n" |
+" program. The format of this manifest is as follows. Each line in the \n" |
+" manifest is a comma separated list of three elements. The first entry is \n" |
+" the library URI, the second entry is the class name and the final entry \n" |
+" the function name. The file must be terminated with a newline charater. \n" |
" \n" |
" Example: \n" |
" dart:something,SomeClass,doSomething \n" |
@@ -611,12 +650,18 @@ static void PrintUsage() { |
" the command line to load the \n" |
" libraries. \n" |
" \n" |
-" --instructions_snapshot=<file> (Precompilation only) Contains the \n" |
+" --assembly=<file> (Precompilation only) Contains the \n" |
" assembly that must be linked into \n" |
" the target binary \n" |
" \n" |
-" --embedder_entry_points_manifest=<file> (Precompilation only) Contains \n" |
-" the stanalone embedder entry points\n"); |
+" --instructions_blob=<file> (Precompilation only) Contains the \n" |
+" --rodata_blob=<file> instructions and read-only data that \n" |
+" must be mapped into the target binary \n" |
+" \n" |
+" --embedder_entry_points_manifest=<file> (Precompilation or app \n" |
+" snapshots) Contains embedder's entry \n" |
+" points into Dart code from the C API. \n" |
+"\n"); |
} |
@@ -994,34 +1039,58 @@ static void CreateAndWritePrecompiledSnapshot( |
intptr_t vm_isolate_size = 0; |
uint8_t* isolate_buffer = NULL; |
intptr_t isolate_size = 0; |
- uint8_t* instructions_buffer = NULL; |
- intptr_t instructions_size = 0; |
+ uint8_t* assembly_buffer = NULL; |
+ intptr_t assembly_size = 0; |
+ uint8_t* instructions_blob_buffer = NULL; |
+ intptr_t instructions_blob_size = 0; |
+ uint8_t* rodata_blob_buffer = NULL; |
+ intptr_t rodata_blob_size = 0; |
// Precompile with specified embedder entry points |
result = Dart_Precompile(standalone_entry_points, true); |
CHECK_RESULT(result); |
- // Create a precompiled snapshot. This gives us an instruction buffer with |
- // machine code |
- result = Dart_CreatePrecompiledSnapshot(&vm_isolate_buffer, |
- &vm_isolate_size, |
- &isolate_buffer, |
- &isolate_size, |
- &instructions_buffer, |
- &instructions_size); |
- CHECK_RESULT(result); |
+ // Create a precompiled snapshot. |
+ bool as_assembly = assembly_filename != NULL; |
+ if (as_assembly) { |
+ result = Dart_CreatePrecompiledSnapshotAssembly(&vm_isolate_buffer, |
+ &vm_isolate_size, |
+ &isolate_buffer, |
+ &isolate_size, |
+ &assembly_buffer, |
+ &assembly_size); |
+ CHECK_RESULT(result); |
+ } else { |
+ result = Dart_CreatePrecompiledSnapshotBlob(&vm_isolate_buffer, |
+ &vm_isolate_size, |
+ &isolate_buffer, |
+ &isolate_size, |
+ &instructions_blob_buffer, |
+ &instructions_blob_size, |
+ &rodata_blob_buffer, |
+ &rodata_blob_size); |
+ CHECK_RESULT(result); |
+ } |
- // Now write the vm isolate, isolate and instructions snapshots out to the |
- // specified files and exit. |
+ // Now write the snapshot pieces out to the specified files and exit. |
WriteSnapshotFile(vm_isolate_snapshot_filename, |
vm_isolate_buffer, |
vm_isolate_size); |
WriteSnapshotFile(isolate_snapshot_filename, |
isolate_buffer, |
isolate_size); |
- WriteSnapshotFile(instructions_snapshot_filename, |
- instructions_buffer, |
- instructions_size); |
+ if (as_assembly) { |
+ WriteSnapshotFile(assembly_filename, |
+ assembly_buffer, |
+ assembly_size); |
+ } else { |
+ WriteSnapshotFile(instructions_blob_filename, |
+ instructions_blob_buffer, |
+ instructions_blob_size); |
+ WriteSnapshotFile(rodata_blob_filename, |
+ rodata_blob_buffer, |
+ rodata_blob_size); |
+ } |
Dart_ExitScope(); |
// Shutdown the isolate. |