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)); |