Index: runtime/bin/main.cc |
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc |
index b5ef0870b9f687c4d8c31bef1b7420cd8393fb85..10861340c162816ac3e1d4c67d8264fb2068cce5 100644 |
--- a/runtime/bin/main.cc |
+++ b/runtime/bin/main.cc |
@@ -97,16 +97,11 @@ static const bool is_noopt = false; |
#endif |
-extern const char* kPrecompiledLibraryName; |
+extern const char* kPrecompiledVMIsolateSymbolName; |
+extern const char* kPrecompiledIsolateSymbolName; |
extern const char* kPrecompiledInstructionsSymbolName; |
extern const char* kPrecompiledDataSymbolName; |
-static const char* kVMIsolateSuffix = "snapshot.vmisolate"; |
-static const char* kIsolateSuffix = "snapshot.isolate"; |
-static const char* kAssemblySuffix = "snapshot.S"; |
-static const char* kInstructionsSuffix = "snapshot.instructions"; |
-static const char* kRODataSuffix = "snapshot.rodata"; |
- |
// Global flag that is used to indicate that we want to trace resolution of |
// URIs and the loading of libraries, parts and scripts. |
@@ -378,15 +373,6 @@ static bool ProcessSnapshotKindOption(const char* kind, |
} |
-static bool ProcessRunAppSnapshotOption( |
- const char* filename, CommandLineOptions* vm_options) { |
- ASSERT(filename != NULL); |
- snapshot_filename = filename; |
- run_app_snapshot = true; |
- return true; |
-} |
- |
- |
static bool ProcessEnableVmServiceOption(const char* option_value, |
CommandLineOptions* vm_options) { |
ASSERT(option_value != NULL); |
@@ -565,7 +551,6 @@ static struct { |
{ "--observe", ProcessObserveOption }, |
{ "--snapshot=", ProcessSnapshotFilenameOption }, |
{ "--snapshot-kind=", ProcessSnapshotKindOption }, |
- { "--run-app-snapshot=", ProcessRunAppSnapshotOption }, |
{ "--use-blobs", ProcessUseBlobsOption }, |
{ "--trace-loading", ProcessTraceLoadingOption }, |
{ "--hot-reload-test-mode", ProcessHotReloadTestModeOption }, |
@@ -1207,93 +1192,199 @@ static void WriteSnapshotFile(const char* snapshot_directory, |
} |
-static void ReadSnapshotFile(const char* snapshot_directory, |
- const char* filename, |
- const uint8_t** buffer) { |
- char* concat = NULL; |
- const char* qualified_filename; |
- if ((snapshot_directory != NULL) && (strlen(snapshot_directory) > 0)) { |
- intptr_t len = snprintf(NULL, 0, "%s/%s", snapshot_directory, filename); |
- concat = new char[len + 1]; |
- snprintf(concat, len + 1, "%s/%s", snapshot_directory, filename); |
- qualified_filename = concat; |
- } else { |
- qualified_filename = filename; |
- } |
+static const int64_t kAppSnapshotHeaderSize = 5 * sizeof(int64_t); // NOLINT |
+static const int64_t kAppSnapshotMagicNumber = 0xf6f6dcdc; |
+static const int64_t kAppSnapshotPageSize = 4 * KB; |
- void* file = DartUtils::OpenFile(qualified_filename, false); |
+ |
+static bool ReadAppSnapshotBlobs(const char* script_name, |
+ const uint8_t** vmisolate_buffer, |
+ const uint8_t** isolate_buffer, |
+ const uint8_t** instructions_buffer, |
+ const uint8_t** rodata_buffer) { |
+ File* file = File::Open(script_name, File::kRead); |
if (file == NULL) { |
- fprintf(stderr, |
- "Error: Unable to open file %s for reading snapshot\n", |
- qualified_filename); |
- fflush(stderr); |
- Platform::Exit(kErrorExitCode); |
+ return false; |
} |
- intptr_t len = -1; |
- DartUtils::ReadFile(buffer, &len, file); |
- if ((*buffer == NULL) || (len == -1)) { |
- fprintf(stderr, |
- "Error: Unable to read snapshot file %s\n", qualified_filename); |
- fflush(stderr); |
- Platform::Exit(kErrorExitCode); |
+ if (file->Length() < kAppSnapshotHeaderSize) { |
+ file->Release(); |
+ return false; |
} |
- DartUtils::CloseFile(file); |
- if (concat != NULL) { |
- delete[] concat; |
+ int64_t header[5]; |
+ ASSERT(sizeof(header) == kAppSnapshotHeaderSize); |
+ if (!file->ReadFully(&header, kAppSnapshotHeaderSize)) { |
+ file->Release(); |
+ return false; |
+ } |
+ if (header[0] != kAppSnapshotMagicNumber) { |
+ file->Release(); |
+ return false; |
} |
-} |
+ int64_t vmisolate_position = |
+ Utils::RoundUp(file->Position(), kAppSnapshotPageSize); |
+ int64_t isolate_position = |
+ Utils::RoundUp(vmisolate_position + header[1], kAppSnapshotPageSize); |
+ int64_t rodata_position = |
+ Utils::RoundUp(isolate_position + header[2], kAppSnapshotPageSize); |
+ int64_t instructions_position = |
+ Utils::RoundUp(rodata_position + header[3], kAppSnapshotPageSize); |
+ |
+ void* read_only_buffer = |
+ file->Map(File::kReadOnly, vmisolate_position, |
+ instructions_position - vmisolate_position); |
+ if (read_only_buffer == NULL) { |
+ ErrorExit(kErrorExitCode, "Failed to memory map snapshot\n"); |
+ } |
+ |
+ *vmisolate_buffer = reinterpret_cast<const uint8_t*>(read_only_buffer) |
+ + (vmisolate_position - vmisolate_position); |
+ *isolate_buffer = reinterpret_cast<const uint8_t*>(read_only_buffer) |
+ + (isolate_position - vmisolate_position); |
+ if (header[3] == 0) { |
+ *rodata_buffer = NULL; |
+ } else { |
+ *rodata_buffer = reinterpret_cast<const uint8_t*>(read_only_buffer) |
+ + (rodata_position - vmisolate_position); |
+ } |
-static void ReadExecutableSnapshotFile(const char* snapshot_directory, |
- const char* filename, |
- const uint8_t** buffer) { |
- char* concat = NULL; |
- const char* qualified_filename; |
- if ((snapshot_directory != NULL) && (strlen(snapshot_directory) > 0)) { |
- intptr_t len = snprintf(NULL, 0, "%s/%s", snapshot_directory, filename); |
- concat = new char[len + 1]; |
- snprintf(concat, len + 1, "%s/%s", snapshot_directory, filename); |
- qualified_filename = concat; |
+ if (header[4] == 0) { |
+ *instructions_buffer = NULL; |
} else { |
- qualified_filename = filename; |
+ *instructions_buffer = reinterpret_cast<const uint8_t*>( |
+ file->Map(File::kReadExecute, instructions_position, header[4])); |
+ if (*instructions_buffer == NULL) { |
+ ErrorExit(kErrorExitCode, "Failed to memory map snapshot2\n"); |
+ } |
} |
- intptr_t len = -1; |
- *buffer = reinterpret_cast<uint8_t*>( |
- DartUtils::MapExecutable(qualified_filename, &len)); |
- if ((*buffer == NULL) || (len == -1)) { |
- fprintf(stderr, |
- "Error: Unable to read snapshot file %s\n", qualified_filename); |
- fflush(stderr); |
- Platform::Exit(kErrorExitCode); |
+ file->Release(); |
+ return true; |
+} |
+ |
+ |
+static bool ReadAppSnapshotDynamicLibrary(const char* script_name, |
+ const uint8_t** vmisolate_buffer, |
+ const uint8_t** isolate_buffer, |
+ const uint8_t** instructions_buffer, |
+ const uint8_t** rodata_buffer) { |
+ void* library = Extensions::LoadExtensionLibrary(script_name); |
+ if (library == NULL) { |
+ return false; |
} |
- if (concat != NULL) { |
- delete[] concat; |
+ |
+ *vmisolate_buffer = reinterpret_cast<const uint8_t*>( |
+ Extensions::ResolveSymbol(library, kPrecompiledVMIsolateSymbolName)); |
+ if (*vmisolate_buffer == NULL) { |
+ ErrorExit(kErrorExitCode, "Failed to resolve symbol '%s'\n", |
+ kPrecompiledVMIsolateSymbolName); |
+ } |
+ |
+ *isolate_buffer = reinterpret_cast<const uint8_t*>( |
+ Extensions::ResolveSymbol(library, kPrecompiledIsolateSymbolName)); |
+ if (*isolate_buffer == NULL) { |
+ ErrorExit(kErrorExitCode, "Failed to resolve symbol '%s'\n", |
+ kPrecompiledIsolateSymbolName); |
+ } |
+ |
+ *instructions_buffer = reinterpret_cast<const uint8_t*>( |
+ Extensions::ResolveSymbol(library, kPrecompiledInstructionsSymbolName)); |
+ if (*instructions_buffer == NULL) { |
+ ErrorExit(kErrorExitCode, "Failed to resolve symbol '%s'\n", |
+ kPrecompiledInstructionsSymbolName); |
} |
+ |
+ *rodata_buffer = reinterpret_cast<const uint8_t*>( |
+ Extensions::ResolveSymbol(library, kPrecompiledDataSymbolName)); |
+ if (*rodata_buffer == NULL) { |
+ ErrorExit(kErrorExitCode, "Failed to resolve symbol '%s'\n", |
+ kPrecompiledDataSymbolName); |
+ } |
+ |
+ return true; |
} |
-static void* LoadLibrarySymbol(const char* snapshot_directory, |
- const char* libname, |
- const char* symname) { |
- char* concat = NULL; |
- const char* qualified_libname; |
- if ((snapshot_directory != NULL) && (strlen(snapshot_directory) > 0)) { |
- intptr_t len = snprintf(NULL, 0, "%s/%s", snapshot_directory, libname); |
- concat = new char[len + 1]; |
- snprintf(concat, len + 1, "%s/%s", snapshot_directory, libname); |
- qualified_libname = concat; |
- } else { |
- qualified_libname = libname; |
+static bool ReadAppSnapshot(const char* script_name, |
+ const uint8_t** vmisolate_buffer, |
+ const uint8_t** isolate_buffer, |
+ const uint8_t** instructions_buffer, |
+ const uint8_t** rodata_buffer) { |
+ if (File::GetType(script_name, true) != File::kIsFile) { |
zra
2016/10/18 16:16:46
On Windows, this calls Dart_ScopeAllocate, which f
|
+ // If 'script_name' refers to a pipe, don't read to check for an app |
+ // snapshot since we cannot rewind if it isn't (and couldn't mmap it in |
+ // anyway if it was). |
+ return false; |
} |
- void* library = Extensions::LoadExtensionLibrary(qualified_libname); |
- if (concat != NULL) { |
- delete concat; |
+ if (ReadAppSnapshotBlobs(script_name, |
+ vmisolate_buffer, |
+ isolate_buffer, |
+ instructions_buffer, |
+ rodata_buffer)) { |
+ return true; |
} |
- if (library == NULL) { |
- return NULL; |
+ return ReadAppSnapshotDynamicLibrary(script_name, |
+ vmisolate_buffer, |
+ isolate_buffer, |
+ instructions_buffer, |
+ rodata_buffer); |
+} |
+ |
+ |
+static bool WriteInt64(File* file, int64_t size) { |
+ return file->WriteFully(&size, sizeof(size)); |
+} |
+ |
+ |
+static void WriteAppSnapshot(const char* filename, |
+ uint8_t* vmisolate_buffer, |
+ intptr_t vmisolate_size, |
+ uint8_t* isolate_buffer, |
+ intptr_t isolate_size, |
+ uint8_t* instructions_buffer, |
+ intptr_t instructions_size, |
+ uint8_t* rodata_buffer, |
+ intptr_t rodata_size) { |
+ File* file = File::Open(filename, File::kWriteTruncate); |
+ if (file == NULL) { |
+ ErrorExit(kErrorExitCode, "Unable to write snapshot file '%s'\n", filename); |
+ } |
+ |
+ file->WriteFully(&kAppSnapshotMagicNumber, sizeof(kAppSnapshotMagicNumber)); |
+ WriteInt64(file, vmisolate_size); |
+ WriteInt64(file, isolate_size); |
+ WriteInt64(file, rodata_size); |
+ WriteInt64(file, instructions_size); |
+ ASSERT(file->Position() == kAppSnapshotHeaderSize); |
+ |
+ file->SetPosition(Utils::RoundUp(file->Position(), kAppSnapshotPageSize)); |
+ if (!file->WriteFully(vmisolate_buffer, vmisolate_size)) { |
+ ErrorExit(kErrorExitCode, "Unable to write snapshot file '%s'\n", filename); |
+ } |
+ |
+ file->SetPosition(Utils::RoundUp(file->Position(), kAppSnapshotPageSize)); |
+ if (!file->WriteFully(isolate_buffer, isolate_size)) { |
+ ErrorExit(kErrorExitCode, "Unable to write snapshot file '%s'\n", filename); |
+ } |
+ |
+ if (rodata_size != 0) { |
+ file->SetPosition(Utils::RoundUp(file->Position(), kAppSnapshotPageSize)); |
+ if (!file->WriteFully(rodata_buffer, rodata_size)) { |
+ ErrorExit(kErrorExitCode, "Unable to write snapshot file '%s'\n", |
+ filename); |
+ } |
} |
- return Extensions::ResolveSymbol(library, symname); |
+ |
+ if (instructions_size != 0) { |
+ file->SetPosition(Utils::RoundUp(file->Position(), kAppSnapshotPageSize)); |
+ if (!file->WriteFully(instructions_buffer, instructions_size)) { |
+ ErrorExit(kErrorExitCode, "Unable to write snapshot file '%s'\n", |
+ filename); |
+ } |
+ } |
+ |
+ file->Flush(); |
+ file->Release(); |
} |
@@ -1334,35 +1425,24 @@ static void GeneratePrecompiledSnapshot() { |
&rodata_blob_size); |
} else { |
result = Dart_CreatePrecompiledSnapshotAssembly( |
- &vm_isolate_buffer, |
- &vm_isolate_size, |
- &isolate_buffer, |
- &isolate_size, |
&assembly_buffer, |
&assembly_size); |
} |
if (Dart_IsError(result)) { |
ErrorExit(kErrorExitCode, "%s\n", Dart_GetError(result)); |
} |
- WriteSnapshotFile(snapshot_filename, kVMIsolateSuffix, |
- false, |
- vm_isolate_buffer, |
- vm_isolate_size); |
- WriteSnapshotFile(snapshot_filename, kIsolateSuffix, |
- false, |
- isolate_buffer, |
- isolate_size); |
if (use_blobs) { |
- WriteSnapshotFile(snapshot_filename, kInstructionsSuffix, |
- false, |
- instructions_blob_buffer, |
- instructions_blob_size); |
- WriteSnapshotFile(snapshot_filename, kRODataSuffix, |
- false, |
- rodata_blob_buffer, |
- rodata_blob_size); |
+ WriteAppSnapshot(snapshot_filename, |
+ vm_isolate_buffer, |
+ vm_isolate_size, |
+ isolate_buffer, |
+ isolate_size, |
+ instructions_blob_buffer, |
+ instructions_blob_size, |
+ rodata_blob_buffer, |
+ rodata_blob_size); |
} else { |
- WriteSnapshotFile(snapshot_filename, kAssemblySuffix, |
+ WriteSnapshotFile(NULL, snapshot_filename, |
false, |
assembly_buffer, |
assembly_size); |
@@ -1371,10 +1451,6 @@ static void GeneratePrecompiledSnapshot() { |
static void GeneratePrecompiledJITSnapshot() { |
- if (!use_blobs) { |
- ErrorExit(kErrorExitCode, |
- "Generating app JIT snapshots as assembly unimplemented\n"); |
- } |
uint8_t* vm_isolate_buffer = NULL; |
intptr_t vm_isolate_size = 0; |
uint8_t* isolate_buffer = NULL; |
@@ -1395,22 +1471,15 @@ static void GeneratePrecompiledJITSnapshot() { |
if (Dart_IsError(result)) { |
ErrorExit(kErrorExitCode, "%s\n", Dart_GetError(result)); |
} |
- WriteSnapshotFile(snapshot_filename, kVMIsolateSuffix, |
- false, |
- vm_isolate_buffer, |
- vm_isolate_size); |
- WriteSnapshotFile(snapshot_filename, kIsolateSuffix, |
- false, |
- isolate_buffer, |
- isolate_size); |
- WriteSnapshotFile(snapshot_filename, kInstructionsSuffix, |
- false, |
- instructions_blob_buffer, |
- instructions_blob_size); |
- WriteSnapshotFile(snapshot_filename, kRODataSuffix, |
- false, |
- rodata_blob_buffer, |
- rodata_blob_size); |
+ WriteAppSnapshot(snapshot_filename, |
+ vm_isolate_buffer, |
+ vm_isolate_size, |
+ isolate_buffer, |
+ isolate_size, |
+ instructions_blob_buffer, |
+ instructions_blob_size, |
+ rodata_blob_buffer, |
+ rodata_blob_size); |
} |
@@ -1430,16 +1499,12 @@ static void GenerateFullSnapshot() { |
ErrorExit(kErrorExitCode, "%s\n", Dart_GetError(result)); |
} |
- WriteSnapshotFile(snapshot_filename, |
- kVMIsolateSuffix, |
- false, |
- vm_isolate_buffer, |
- vm_isolate_size); |
- WriteSnapshotFile(snapshot_filename, |
- kIsolateSuffix, |
- false, |
- isolate_buffer, |
- isolate_size); |
+ WriteAppSnapshot(snapshot_filename, |
+ vm_isolate_buffer, |
+ vm_isolate_size, |
+ isolate_buffer, |
+ isolate_size, |
+ NULL, 0, NULL, 0); |
} |
@@ -1783,6 +1848,17 @@ void main(int argc, char** argv) { |
Platform::Exit(kErrorExitCode); |
} |
+ const uint8_t* instructions_snapshot = NULL; |
+ const uint8_t* data_snapshot = NULL; |
+ |
+ if (ReadAppSnapshot(script_name, |
+ &vm_isolate_snapshot_buffer, |
+ &isolate_snapshot_buffer, |
+ &instructions_snapshot, |
+ &data_snapshot)) { |
+ run_app_snapshot = true; |
+ } |
+ |
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) |
// Constant true if PRODUCT or DART_PRECOMPILED_RUNTIME. |
if ((gen_snapshot_kind != kNone) || run_app_snapshot) { |
@@ -1806,31 +1882,6 @@ void main(int argc, char** argv) { |
TimerUtils::InitOnce(); |
EventHandler::Start(); |
- const uint8_t* instructions_snapshot = NULL; |
- const uint8_t* data_snapshot = NULL; |
- if (run_app_snapshot) { |
- ReadSnapshotFile(snapshot_filename, kVMIsolateSuffix, |
- &vm_isolate_snapshot_buffer); |
- ReadSnapshotFile(snapshot_filename, kIsolateSuffix, |
- &isolate_snapshot_buffer); |
- if (use_blobs) { |
- ReadExecutableSnapshotFile(snapshot_filename, |
- kInstructionsSuffix, |
- &instructions_snapshot); |
- ReadSnapshotFile(snapshot_filename, kRODataSuffix, |
- &data_snapshot); |
- } else { |
- instructions_snapshot = reinterpret_cast<const uint8_t*>( |
- LoadLibrarySymbol(snapshot_filename, |
- kPrecompiledLibraryName, |
- kPrecompiledInstructionsSymbolName)); |
- data_snapshot = reinterpret_cast<const uint8_t*>( |
- LoadLibrarySymbol(snapshot_filename, |
- kPrecompiledLibraryName, |
- kPrecompiledDataSymbolName)); |
- } |
- } |
- |
// Initialize the Dart VM. |
Dart_InitializeParams init_params; |
memset(&init_params, 0, sizeof(init_params)); |