| Index: runtime/bin/snapshot_utils.cc
|
| diff --git a/runtime/bin/snapshot_utils.cc b/runtime/bin/snapshot_utils.cc
|
| index 741d7978bb64e671b11b5f9d06df8a1534693e0c..98c342d413238c3f21f0484ce52fe32e29404082 100644
|
| --- a/runtime/bin/snapshot_utils.cc
|
| +++ b/runtime/bin/snapshot_utils.cc
|
| @@ -24,28 +24,72 @@ static const int64_t kAppSnapshotHeaderSize = 5 * kInt64Size;
|
| static const int64_t kAppSnapshotMagicNumber = 0xf6f6dcdc;
|
| static const int64_t kAppSnapshotPageSize = 4 * KB;
|
|
|
| -static bool ReadAppSnapshotBlobs(const char* script_name,
|
| - const uint8_t** vm_data_buffer,
|
| - const uint8_t** vm_instructions_buffer,
|
| - const uint8_t** isolate_data_buffer,
|
| - const uint8_t** isolate_instructions_buffer) {
|
| +class MappedAppSnapshot : public AppSnapshot {
|
| + public:
|
| + MappedAppSnapshot(MappedMemory* vm_snapshot_data,
|
| + MappedMemory* vm_snapshot_instructions,
|
| + MappedMemory* isolate_snapshot_data,
|
| + MappedMemory* isolate_snapshot_instructions)
|
| + : vm_data_mapping_(vm_snapshot_data),
|
| + vm_instructions_mapping_(vm_snapshot_instructions),
|
| + isolate_data_mapping_(isolate_snapshot_data),
|
| + isolate_instructions_mapping_(isolate_snapshot_instructions) {}
|
| +
|
| + ~MappedAppSnapshot() {
|
| + delete vm_data_mapping_;
|
| + delete vm_instructions_mapping_;
|
| + delete isolate_data_mapping_;
|
| + delete isolate_instructions_mapping_;
|
| + }
|
| +
|
| + void SetBuffers(const uint8_t** vm_data_buffer,
|
| + const uint8_t** vm_instructions_buffer,
|
| + const uint8_t** isolate_data_buffer,
|
| + const uint8_t** isolate_instructions_buffer) {
|
| + if (vm_data_mapping_ != NULL) {
|
| + *vm_data_buffer =
|
| + reinterpret_cast<const uint8_t*>(vm_data_mapping_->address());
|
| + }
|
| + if (vm_instructions_mapping_ != NULL) {
|
| + *vm_instructions_buffer =
|
| + reinterpret_cast<const uint8_t*>(vm_instructions_mapping_->address());
|
| + }
|
| + if (isolate_data_mapping_ != NULL) {
|
| + *isolate_data_buffer =
|
| + reinterpret_cast<const uint8_t*>(isolate_data_mapping_->address());
|
| + }
|
| + if (isolate_instructions_mapping_ != NULL) {
|
| + *isolate_instructions_buffer = reinterpret_cast<const uint8_t*>(
|
| + isolate_instructions_mapping_->address());
|
| + }
|
| + }
|
| +
|
| + private:
|
| + MappedMemory* vm_data_mapping_;
|
| + MappedMemory* vm_instructions_mapping_;
|
| + MappedMemory* isolate_data_mapping_;
|
| + MappedMemory* isolate_instructions_mapping_;
|
| +};
|
| +
|
| +
|
| +static AppSnapshot* TryReadAppSnapshotBlobs(const char* script_name) {
|
| File* file = File::Open(script_name, File::kRead);
|
| if (file == NULL) {
|
| - return false;
|
| + return NULL;
|
| }
|
| if (file->Length() < kAppSnapshotHeaderSize) {
|
| file->Release();
|
| - return false;
|
| + return NULL;
|
| }
|
| int64_t header[5];
|
| ASSERT(sizeof(header) == kAppSnapshotHeaderSize);
|
| if (!file->ReadFully(&header, kAppSnapshotHeaderSize)) {
|
| file->Release();
|
| - return false;
|
| + return NULL;
|
| }
|
| if (header[0] != kAppSnapshotMagicNumber) {
|
| file->Release();
|
| - return false;
|
| + return NULL;
|
| }
|
|
|
| int64_t vm_data_size = header[1];
|
| @@ -68,121 +112,143 @@ static bool ReadAppSnapshotBlobs(const char* script_name,
|
| Utils::RoundUp(isolate_instructions_position, kAppSnapshotPageSize);
|
| }
|
|
|
| + MappedMemory* vm_data_mapping = NULL;
|
| if (vm_data_size != 0) {
|
| - *vm_data_buffer = reinterpret_cast<const uint8_t*>(
|
| - file->Map(File::kReadOnly, vm_data_position, vm_data_size));
|
| - if (vm_data_buffer == NULL) {
|
| - Log::PrintErr("Failed to memory map snapshot\n");
|
| - Platform::Exit(kErrorExitCode);
|
| + vm_data_mapping =
|
| + file->Map(File::kReadOnly, vm_data_position, vm_data_size);
|
| + if (vm_data_mapping == NULL) {
|
| + FATAL1("Failed to memory map snapshot: %s\n", script_name);
|
| }
|
| }
|
|
|
| + MappedMemory* vm_instr_mapping = NULL;
|
| if (vm_instructions_size != 0) {
|
| - *vm_instructions_buffer = reinterpret_cast<const uint8_t*>(file->Map(
|
| - File::kReadExecute, vm_instructions_position, vm_instructions_size));
|
| - if (*vm_instructions_buffer == NULL) {
|
| - Log::PrintErr("Failed to memory map snapshot\n");
|
| - Platform::Exit(kErrorExitCode);
|
| + vm_instr_mapping = file->Map(File::kReadExecute, vm_instructions_position,
|
| + vm_instructions_size);
|
| + if (vm_instr_mapping == NULL) {
|
| + FATAL1("Failed to memory map snapshot: %s\n", script_name);
|
| }
|
| }
|
|
|
| - *isolate_data_buffer = reinterpret_cast<const uint8_t*>(
|
| - file->Map(File::kReadOnly, isolate_data_position, isolate_data_size));
|
| - if (isolate_data_buffer == NULL) {
|
| - Log::PrintErr("Failed to memory map snapshot\n");
|
| - Platform::Exit(kErrorExitCode);
|
| + MappedMemory* isolate_data_mapping = NULL;
|
| + if (isolate_data_size != 0) {
|
| + isolate_data_mapping =
|
| + file->Map(File::kReadOnly, isolate_data_position, isolate_data_size);
|
| + if (isolate_data_mapping == NULL) {
|
| + FATAL1("Failed to memory map snapshot: %s\n", script_name);
|
| + }
|
| }
|
|
|
| - if (isolate_instructions_size == 0) {
|
| - *isolate_instructions_buffer = NULL;
|
| - } else {
|
| - *isolate_instructions_buffer = reinterpret_cast<const uint8_t*>(
|
| + MappedMemory* isolate_instr_mapping = NULL;
|
| + if (isolate_instructions_size != 0) {
|
| + isolate_instr_mapping =
|
| file->Map(File::kReadExecute, isolate_instructions_position,
|
| - isolate_instructions_size));
|
| - if (*isolate_instructions_buffer == NULL) {
|
| - Log::PrintErr("Failed to memory map snapshot\n");
|
| - Platform::Exit(kErrorExitCode);
|
| + isolate_instructions_size);
|
| + if (isolate_instr_mapping == NULL) {
|
| + FATAL1("Failed to memory map snapshot: %s\n", script_name);
|
| }
|
| }
|
|
|
| file->Release();
|
| - return true;
|
| + return new MappedAppSnapshot(vm_data_mapping, vm_instr_mapping,
|
| + isolate_data_mapping, isolate_instr_mapping);
|
| }
|
|
|
|
|
| #if defined(DART_PRECOMPILED_RUNTIME)
|
| -static bool ReadAppSnapshotDynamicLibrary(
|
| - const char* script_name,
|
| - const uint8_t** vm_data_buffer,
|
| - const uint8_t** vm_instructions_buffer,
|
| - const uint8_t** isolate_data_buffer,
|
| - const uint8_t** isolate_instructions_buffer) {
|
| - void* library = Extensions::LoadExtensionLibrary(script_name);
|
| +class DylibAppSnapshot : public AppSnapshot {
|
| + public:
|
| + DylibAppSnapshot(void* library,
|
| + const uint8_t* vm_snapshot_data,
|
| + const uint8_t* vm_snapshot_instructions,
|
| + const uint8_t* isolate_snapshot_data,
|
| + const uint8_t* isolate_snapshot_instructions)
|
| + : library_(library),
|
| + vm_snapshot_data_(vm_snapshot_data),
|
| + vm_snapshot_instructions_(vm_snapshot_instructions),
|
| + isolate_snapshot_data_(isolate_snapshot_data),
|
| + isolate_snapshot_instructions_(isolate_snapshot_instructions) {}
|
| +
|
| + ~DylibAppSnapshot() { Extensions::UnloadLibrary(library_); }
|
| +
|
| + void SetBuffers(const uint8_t** vm_data_buffer,
|
| + const uint8_t** vm_instructions_buffer,
|
| + const uint8_t** isolate_data_buffer,
|
| + const uint8_t** isolate_instructions_buffer) {
|
| + *vm_data_buffer = vm_snapshot_data_;
|
| + *vm_instructions_buffer = vm_snapshot_instructions_;
|
| + *isolate_data_buffer = isolate_snapshot_data_;
|
| + *isolate_instructions_buffer = isolate_snapshot_instructions_;
|
| + }
|
| +
|
| + private:
|
| + void* library_;
|
| + const uint8_t* vm_snapshot_data_;
|
| + const uint8_t* vm_snapshot_instructions_;
|
| + const uint8_t* isolate_snapshot_data_;
|
| + const uint8_t* isolate_snapshot_instructions_;
|
| +};
|
| +
|
| +
|
| +static AppSnapshot* TryReadAppSnapshotDynamicLibrary(const char* script_name) {
|
| + void* library = Extensions::LoadLibrary(script_name);
|
| if (library == NULL) {
|
| - return false;
|
| + return NULL;
|
| }
|
|
|
| - *vm_data_buffer = reinterpret_cast<const uint8_t*>(
|
| + const uint8_t* vm_data_buffer = reinterpret_cast<const uint8_t*>(
|
| Extensions::ResolveSymbol(library, kVmSnapshotDataSymbolName));
|
| - if (*vm_data_buffer == NULL) {
|
| - Log::PrintErr("Failed to resolve symbol '%s'\n", kVmSnapshotDataSymbolName);
|
| - Platform::Exit(kErrorExitCode);
|
| + if (vm_data_buffer == NULL) {
|
| + FATAL1("Failed to resolve symbol '%s'\n", kVmSnapshotDataSymbolName);
|
| }
|
|
|
| - *vm_instructions_buffer = reinterpret_cast<const uint8_t*>(
|
| + const uint8_t* vm_instructions_buffer = reinterpret_cast<const uint8_t*>(
|
| Extensions::ResolveSymbol(library, kVmSnapshotInstructionsSymbolName));
|
| - if (*vm_instructions_buffer == NULL) {
|
| - Log::PrintErr("Failed to resolve symbol '%s'\n",
|
| - kVmSnapshotInstructionsSymbolName);
|
| - Platform::Exit(kErrorExitCode);
|
| + if (vm_instructions_buffer == NULL) {
|
| + FATAL1("Failed to resolve symbol '%s'\n",
|
| + kVmSnapshotInstructionsSymbolName);
|
| }
|
|
|
| - *isolate_data_buffer = reinterpret_cast<const uint8_t*>(
|
| + const uint8_t* isolate_data_buffer = reinterpret_cast<const uint8_t*>(
|
| Extensions::ResolveSymbol(library, kIsolateSnapshotDataSymbolName));
|
| - if (*isolate_data_buffer == NULL) {
|
| - Log::PrintErr("Failed to resolve symbol '%s'\n",
|
| - kIsolateSnapshotDataSymbolName);
|
| - Platform::Exit(kErrorExitCode);
|
| + if (isolate_data_buffer == NULL) {
|
| + FATAL1("Failed to resolve symbol '%s'\n", kIsolateSnapshotDataSymbolName);
|
| }
|
|
|
| - *isolate_instructions_buffer =
|
| + const uint8_t* isolate_instructions_buffer =
|
| reinterpret_cast<const uint8_t*>(Extensions::ResolveSymbol(
|
| library, kIsolateSnapshotInstructionsSymbolName));
|
| - if (*isolate_instructions_buffer == NULL) {
|
| - Log::PrintErr("Failed to resolve symbol '%s'\n",
|
| - kIsolateSnapshotInstructionsSymbolName);
|
| - Platform::Exit(kErrorExitCode);
|
| + if (isolate_instructions_buffer == NULL) {
|
| + FATAL1("Failed to resolve symbol '%s'\n",
|
| + kIsolateSnapshotInstructionsSymbolName);
|
| }
|
|
|
| - return true;
|
| + return new DylibAppSnapshot(library, vm_data_buffer, vm_instructions_buffer,
|
| + isolate_data_buffer, isolate_instructions_buffer);
|
| }
|
| #endif // defined(DART_PRECOMPILED_RUNTIME)
|
|
|
|
|
| -bool Snapshot::ReadAppSnapshot(const char* script_name,
|
| - const uint8_t** vm_data_buffer,
|
| - const uint8_t** vm_instructions_buffer,
|
| - const uint8_t** isolate_data_buffer,
|
| - const uint8_t** isolate_instructions_buffer) {
|
| +AppSnapshot* Snapshot::TryReadAppSnapshot(const char* script_name) {
|
| if (File::GetType(script_name, true) != File::kIsFile) {
|
| // 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;
|
| + return NULL;
|
| }
|
| - if (ReadAppSnapshotBlobs(script_name, vm_data_buffer, vm_instructions_buffer,
|
| - isolate_data_buffer, isolate_instructions_buffer)) {
|
| - return true;
|
| + AppSnapshot* snapshot = TryReadAppSnapshotBlobs(script_name);
|
| + if (snapshot != NULL) {
|
| + return snapshot;
|
| }
|
| #if defined(DART_PRECOMPILED_RUNTIME)
|
| // For testing AOT with the standalone embedder, we also support loading
|
| // from a dynamic library to simulate what happens on iOS.
|
| - return ReadAppSnapshotDynamicLibrary(
|
| - script_name, vm_data_buffer, vm_instructions_buffer, isolate_data_buffer,
|
| - isolate_instructions_buffer);
|
| -#else
|
| - return false;
|
| + snapshot = TryReadAppSnapshotDynamicLibrary(script_name);
|
| + if (snapshot != NULL) {
|
| + return snapshot;
|
| + }
|
| #endif // defined(DART_PRECOMPILED_RUNTIME)
|
| + return NULL;
|
| }
|
|
|
|
|
|
|