Chromium Code Reviews| 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)); |