| OLD | NEW |
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "bin/snapshot_utils.h" | 5 #include "bin/snapshot_utils.h" |
| 6 | 6 |
| 7 #include "bin/dartutils.h" | 7 #include "bin/dartutils.h" |
| 8 #include "bin/error_exit.h" | 8 #include "bin/error_exit.h" |
| 9 #include "bin/extensions.h" | 9 #include "bin/extensions.h" |
| 10 #include "bin/file.h" | 10 #include "bin/file.h" |
| 11 #include "bin/platform.h" | 11 #include "bin/platform.h" |
| 12 #include "include/dart_api.h" | 12 #include "include/dart_api.h" |
| 13 #include "platform/utils.h" | 13 #include "platform/utils.h" |
| 14 | 14 |
| 15 namespace dart { | 15 namespace dart { |
| 16 namespace bin { | 16 namespace bin { |
| 17 | 17 |
| 18 extern const char* kVmSnapshotDataSymbolName; | 18 extern const char* kVmSnapshotDataSymbolName; |
| 19 extern const char* kVmSnapshotInstructionsSymbolName; | 19 extern const char* kVmSnapshotInstructionsSymbolName; |
| 20 extern const char* kIsolateSnapshotDataSymbolName; | 20 extern const char* kIsolateSnapshotDataSymbolName; |
| 21 extern const char* kIsolateSnapshotInstructionsSymbolName; | 21 extern const char* kIsolateSnapshotInstructionsSymbolName; |
| 22 | 22 |
| 23 static const int64_t kAppSnapshotHeaderSize = 5 * kInt64Size; | 23 static const int64_t kAppSnapshotHeaderSize = 5 * kInt64Size; |
| 24 static const int64_t kAppSnapshotMagicNumber = 0xf6f6dcdc; | 24 static const int64_t kAppSnapshotMagicNumber = 0xf6f6dcdc; |
| 25 static const int64_t kAppSnapshotPageSize = 4 * KB; | 25 static const int64_t kAppSnapshotPageSize = 4 * KB; |
| 26 | 26 |
| 27 static bool ReadAppSnapshotBlobs(const char* script_name, | 27 class MappedAppSnapshot : public AppSnapshot { |
| 28 const uint8_t** vm_data_buffer, | 28 public: |
| 29 const uint8_t** vm_instructions_buffer, | 29 MappedAppSnapshot(MappedMemory* vm_snapshot_data, |
| 30 const uint8_t** isolate_data_buffer, | 30 MappedMemory* vm_snapshot_instructions, |
| 31 const uint8_t** isolate_instructions_buffer) { | 31 MappedMemory* isolate_snapshot_data, |
| 32 MappedMemory* isolate_snapshot_instructions) |
| 33 : vm_data_mapping_(vm_snapshot_data), |
| 34 vm_instructions_mapping_(vm_snapshot_instructions), |
| 35 isolate_data_mapping_(isolate_snapshot_data), |
| 36 isolate_instructions_mapping_(isolate_snapshot_instructions) {} |
| 37 |
| 38 ~MappedAppSnapshot() { |
| 39 delete vm_data_mapping_; |
| 40 delete vm_instructions_mapping_; |
| 41 delete isolate_data_mapping_; |
| 42 delete isolate_instructions_mapping_; |
| 43 } |
| 44 |
| 45 void SetBuffers(const uint8_t** vm_data_buffer, |
| 46 const uint8_t** vm_instructions_buffer, |
| 47 const uint8_t** isolate_data_buffer, |
| 48 const uint8_t** isolate_instructions_buffer) { |
| 49 if (vm_data_mapping_ != NULL) { |
| 50 *vm_data_buffer = |
| 51 reinterpret_cast<const uint8_t*>(vm_data_mapping_->address()); |
| 52 } |
| 53 if (vm_instructions_mapping_ != NULL) { |
| 54 *vm_instructions_buffer = |
| 55 reinterpret_cast<const uint8_t*>(vm_instructions_mapping_->address()); |
| 56 } |
| 57 if (isolate_data_mapping_ != NULL) { |
| 58 *isolate_data_buffer = |
| 59 reinterpret_cast<const uint8_t*>(isolate_data_mapping_->address()); |
| 60 } |
| 61 if (isolate_instructions_mapping_ != NULL) { |
| 62 *isolate_instructions_buffer = reinterpret_cast<const uint8_t*>( |
| 63 isolate_instructions_mapping_->address()); |
| 64 } |
| 65 } |
| 66 |
| 67 private: |
| 68 MappedMemory* vm_data_mapping_; |
| 69 MappedMemory* vm_instructions_mapping_; |
| 70 MappedMemory* isolate_data_mapping_; |
| 71 MappedMemory* isolate_instructions_mapping_; |
| 72 }; |
| 73 |
| 74 |
| 75 static AppSnapshot* TryReadAppSnapshotBlobs(const char* script_name) { |
| 32 File* file = File::Open(script_name, File::kRead); | 76 File* file = File::Open(script_name, File::kRead); |
| 33 if (file == NULL) { | 77 if (file == NULL) { |
| 34 return false; | 78 return NULL; |
| 35 } | 79 } |
| 36 if (file->Length() < kAppSnapshotHeaderSize) { | 80 if (file->Length() < kAppSnapshotHeaderSize) { |
| 37 file->Release(); | 81 file->Release(); |
| 38 return false; | 82 return NULL; |
| 39 } | 83 } |
| 40 int64_t header[5]; | 84 int64_t header[5]; |
| 41 ASSERT(sizeof(header) == kAppSnapshotHeaderSize); | 85 ASSERT(sizeof(header) == kAppSnapshotHeaderSize); |
| 42 if (!file->ReadFully(&header, kAppSnapshotHeaderSize)) { | 86 if (!file->ReadFully(&header, kAppSnapshotHeaderSize)) { |
| 43 file->Release(); | 87 file->Release(); |
| 44 return false; | 88 return NULL; |
| 45 } | 89 } |
| 46 if (header[0] != kAppSnapshotMagicNumber) { | 90 if (header[0] != kAppSnapshotMagicNumber) { |
| 47 file->Release(); | 91 file->Release(); |
| 48 return false; | 92 return NULL; |
| 49 } | 93 } |
| 50 | 94 |
| 51 int64_t vm_data_size = header[1]; | 95 int64_t vm_data_size = header[1]; |
| 52 int64_t vm_data_position = | 96 int64_t vm_data_position = |
| 53 Utils::RoundUp(file->Position(), kAppSnapshotPageSize); | 97 Utils::RoundUp(file->Position(), kAppSnapshotPageSize); |
| 54 int64_t vm_instructions_size = header[2]; | 98 int64_t vm_instructions_size = header[2]; |
| 55 int64_t vm_instructions_position = vm_data_position + vm_data_size; | 99 int64_t vm_instructions_position = vm_data_position + vm_data_size; |
| 56 if (vm_instructions_size != 0) { | 100 if (vm_instructions_size != 0) { |
| 57 vm_instructions_position = | 101 vm_instructions_position = |
| 58 Utils::RoundUp(vm_instructions_position, kAppSnapshotPageSize); | 102 Utils::RoundUp(vm_instructions_position, kAppSnapshotPageSize); |
| 59 } | 103 } |
| 60 int64_t isolate_data_size = header[3]; | 104 int64_t isolate_data_size = header[3]; |
| 61 int64_t isolate_data_position = Utils::RoundUp( | 105 int64_t isolate_data_position = Utils::RoundUp( |
| 62 vm_instructions_position + vm_instructions_size, kAppSnapshotPageSize); | 106 vm_instructions_position + vm_instructions_size, kAppSnapshotPageSize); |
| 63 int64_t isolate_instructions_size = header[4]; | 107 int64_t isolate_instructions_size = header[4]; |
| 64 int64_t isolate_instructions_position = | 108 int64_t isolate_instructions_position = |
| 65 isolate_data_position + isolate_data_size; | 109 isolate_data_position + isolate_data_size; |
| 66 if (isolate_instructions_size != 0) { | 110 if (isolate_instructions_size != 0) { |
| 67 isolate_instructions_position = | 111 isolate_instructions_position = |
| 68 Utils::RoundUp(isolate_instructions_position, kAppSnapshotPageSize); | 112 Utils::RoundUp(isolate_instructions_position, kAppSnapshotPageSize); |
| 69 } | 113 } |
| 70 | 114 |
| 115 MappedMemory* vm_data_mapping = NULL; |
| 71 if (vm_data_size != 0) { | 116 if (vm_data_size != 0) { |
| 72 *vm_data_buffer = reinterpret_cast<const uint8_t*>( | 117 vm_data_mapping = |
| 73 file->Map(File::kReadOnly, vm_data_position, vm_data_size)); | 118 file->Map(File::kReadOnly, vm_data_position, vm_data_size); |
| 74 if (vm_data_buffer == NULL) { | 119 if (vm_data_mapping == NULL) { |
| 75 Log::PrintErr("Failed to memory map snapshot\n"); | 120 FATAL1("Failed to memory map snapshot: %s\n", script_name); |
| 76 Platform::Exit(kErrorExitCode); | |
| 77 } | 121 } |
| 78 } | 122 } |
| 79 | 123 |
| 124 MappedMemory* vm_instr_mapping = NULL; |
| 80 if (vm_instructions_size != 0) { | 125 if (vm_instructions_size != 0) { |
| 81 *vm_instructions_buffer = reinterpret_cast<const uint8_t*>(file->Map( | 126 vm_instr_mapping = file->Map(File::kReadExecute, vm_instructions_position, |
| 82 File::kReadExecute, vm_instructions_position, vm_instructions_size)); | 127 vm_instructions_size); |
| 83 if (*vm_instructions_buffer == NULL) { | 128 if (vm_instr_mapping == NULL) { |
| 84 Log::PrintErr("Failed to memory map snapshot\n"); | 129 FATAL1("Failed to memory map snapshot: %s\n", script_name); |
| 85 Platform::Exit(kErrorExitCode); | |
| 86 } | 130 } |
| 87 } | 131 } |
| 88 | 132 |
| 89 *isolate_data_buffer = reinterpret_cast<const uint8_t*>( | 133 MappedMemory* isolate_data_mapping = NULL; |
| 90 file->Map(File::kReadOnly, isolate_data_position, isolate_data_size)); | 134 if (isolate_data_size != 0) { |
| 91 if (isolate_data_buffer == NULL) { | 135 isolate_data_mapping = |
| 92 Log::PrintErr("Failed to memory map snapshot\n"); | 136 file->Map(File::kReadOnly, isolate_data_position, isolate_data_size); |
| 93 Platform::Exit(kErrorExitCode); | 137 if (isolate_data_mapping == NULL) { |
| 138 FATAL1("Failed to memory map snapshot: %s\n", script_name); |
| 139 } |
| 94 } | 140 } |
| 95 | 141 |
| 96 if (isolate_instructions_size == 0) { | 142 MappedMemory* isolate_instr_mapping = NULL; |
| 97 *isolate_instructions_buffer = NULL; | 143 if (isolate_instructions_size != 0) { |
| 98 } else { | 144 isolate_instr_mapping = |
| 99 *isolate_instructions_buffer = reinterpret_cast<const uint8_t*>( | |
| 100 file->Map(File::kReadExecute, isolate_instructions_position, | 145 file->Map(File::kReadExecute, isolate_instructions_position, |
| 101 isolate_instructions_size)); | 146 isolate_instructions_size); |
| 102 if (*isolate_instructions_buffer == NULL) { | 147 if (isolate_instr_mapping == NULL) { |
| 103 Log::PrintErr("Failed to memory map snapshot\n"); | 148 FATAL1("Failed to memory map snapshot: %s\n", script_name); |
| 104 Platform::Exit(kErrorExitCode); | |
| 105 } | 149 } |
| 106 } | 150 } |
| 107 | 151 |
| 108 file->Release(); | 152 file->Release(); |
| 109 return true; | 153 return new MappedAppSnapshot(vm_data_mapping, vm_instr_mapping, |
| 154 isolate_data_mapping, isolate_instr_mapping); |
| 110 } | 155 } |
| 111 | 156 |
| 112 | 157 |
| 113 #if defined(DART_PRECOMPILED_RUNTIME) | 158 #if defined(DART_PRECOMPILED_RUNTIME) |
| 114 static bool ReadAppSnapshotDynamicLibrary( | 159 class DylibAppSnapshot : public AppSnapshot { |
| 115 const char* script_name, | 160 public: |
| 116 const uint8_t** vm_data_buffer, | 161 DylibAppSnapshot(void* library, |
| 117 const uint8_t** vm_instructions_buffer, | 162 const uint8_t* vm_snapshot_data, |
| 118 const uint8_t** isolate_data_buffer, | 163 const uint8_t* vm_snapshot_instructions, |
| 119 const uint8_t** isolate_instructions_buffer) { | 164 const uint8_t* isolate_snapshot_data, |
| 120 void* library = Extensions::LoadExtensionLibrary(script_name); | 165 const uint8_t* isolate_snapshot_instructions) |
| 121 if (library == NULL) { | 166 : library_(library), |
| 122 return false; | 167 vm_snapshot_data_(vm_snapshot_data), |
| 168 vm_snapshot_instructions_(vm_snapshot_instructions), |
| 169 isolate_snapshot_data_(isolate_snapshot_data), |
| 170 isolate_snapshot_instructions_(isolate_snapshot_instructions) {} |
| 171 |
| 172 ~DylibAppSnapshot() { Extensions::UnloadLibrary(library_); } |
| 173 |
| 174 void SetBuffers(const uint8_t** vm_data_buffer, |
| 175 const uint8_t** vm_instructions_buffer, |
| 176 const uint8_t** isolate_data_buffer, |
| 177 const uint8_t** isolate_instructions_buffer) { |
| 178 *vm_data_buffer = vm_snapshot_data_; |
| 179 *vm_instructions_buffer = vm_snapshot_instructions_; |
| 180 *isolate_data_buffer = isolate_snapshot_data_; |
| 181 *isolate_instructions_buffer = isolate_snapshot_instructions_; |
| 123 } | 182 } |
| 124 | 183 |
| 125 *vm_data_buffer = reinterpret_cast<const uint8_t*>( | 184 private: |
| 126 Extensions::ResolveSymbol(library, kVmSnapshotDataSymbolName)); | 185 void* library_; |
| 127 if (*vm_data_buffer == NULL) { | 186 const uint8_t* vm_snapshot_data_; |
| 128 Log::PrintErr("Failed to resolve symbol '%s'\n", kVmSnapshotDataSymbolName); | 187 const uint8_t* vm_snapshot_instructions_; |
| 129 Platform::Exit(kErrorExitCode); | 188 const uint8_t* isolate_snapshot_data_; |
| 189 const uint8_t* isolate_snapshot_instructions_; |
| 190 }; |
| 191 |
| 192 |
| 193 static AppSnapshot* TryReadAppSnapshotDynamicLibrary(const char* script_name) { |
| 194 void* library = Extensions::LoadLibrary(script_name); |
| 195 if (library == NULL) { |
| 196 return NULL; |
| 130 } | 197 } |
| 131 | 198 |
| 132 *vm_instructions_buffer = reinterpret_cast<const uint8_t*>( | 199 const uint8_t* vm_data_buffer = reinterpret_cast<const uint8_t*>( |
| 133 Extensions::ResolveSymbol(library, kVmSnapshotInstructionsSymbolName)); | 200 Extensions::ResolveSymbol(library, kVmSnapshotDataSymbolName)); |
| 134 if (*vm_instructions_buffer == NULL) { | 201 if (vm_data_buffer == NULL) { |
| 135 Log::PrintErr("Failed to resolve symbol '%s'\n", | 202 FATAL1("Failed to resolve symbol '%s'\n", kVmSnapshotDataSymbolName); |
| 136 kVmSnapshotInstructionsSymbolName); | |
| 137 Platform::Exit(kErrorExitCode); | |
| 138 } | 203 } |
| 139 | 204 |
| 140 *isolate_data_buffer = reinterpret_cast<const uint8_t*>( | 205 const uint8_t* vm_instructions_buffer = reinterpret_cast<const uint8_t*>( |
| 141 Extensions::ResolveSymbol(library, kIsolateSnapshotDataSymbolName)); | 206 Extensions::ResolveSymbol(library, kVmSnapshotInstructionsSymbolName)); |
| 142 if (*isolate_data_buffer == NULL) { | 207 if (vm_instructions_buffer == NULL) { |
| 143 Log::PrintErr("Failed to resolve symbol '%s'\n", | 208 FATAL1("Failed to resolve symbol '%s'\n", |
| 144 kIsolateSnapshotDataSymbolName); | 209 kVmSnapshotInstructionsSymbolName); |
| 145 Platform::Exit(kErrorExitCode); | |
| 146 } | 210 } |
| 147 | 211 |
| 148 *isolate_instructions_buffer = | 212 const uint8_t* isolate_data_buffer = reinterpret_cast<const uint8_t*>( |
| 213 Extensions::ResolveSymbol(library, kIsolateSnapshotDataSymbolName)); |
| 214 if (isolate_data_buffer == NULL) { |
| 215 FATAL1("Failed to resolve symbol '%s'\n", kIsolateSnapshotDataSymbolName); |
| 216 } |
| 217 |
| 218 const uint8_t* isolate_instructions_buffer = |
| 149 reinterpret_cast<const uint8_t*>(Extensions::ResolveSymbol( | 219 reinterpret_cast<const uint8_t*>(Extensions::ResolveSymbol( |
| 150 library, kIsolateSnapshotInstructionsSymbolName)); | 220 library, kIsolateSnapshotInstructionsSymbolName)); |
| 151 if (*isolate_instructions_buffer == NULL) { | 221 if (isolate_instructions_buffer == NULL) { |
| 152 Log::PrintErr("Failed to resolve symbol '%s'\n", | 222 FATAL1("Failed to resolve symbol '%s'\n", |
| 153 kIsolateSnapshotInstructionsSymbolName); | 223 kIsolateSnapshotInstructionsSymbolName); |
| 154 Platform::Exit(kErrorExitCode); | |
| 155 } | 224 } |
| 156 | 225 |
| 157 return true; | 226 return new DylibAppSnapshot(library, vm_data_buffer, vm_instructions_buffer, |
| 227 isolate_data_buffer, isolate_instructions_buffer); |
| 158 } | 228 } |
| 159 #endif // defined(DART_PRECOMPILED_RUNTIME) | 229 #endif // defined(DART_PRECOMPILED_RUNTIME) |
| 160 | 230 |
| 161 | 231 |
| 162 bool Snapshot::ReadAppSnapshot(const char* script_name, | 232 AppSnapshot* Snapshot::TryReadAppSnapshot(const char* script_name) { |
| 163 const uint8_t** vm_data_buffer, | |
| 164 const uint8_t** vm_instructions_buffer, | |
| 165 const uint8_t** isolate_data_buffer, | |
| 166 const uint8_t** isolate_instructions_buffer) { | |
| 167 if (File::GetType(script_name, true) != File::kIsFile) { | 233 if (File::GetType(script_name, true) != File::kIsFile) { |
| 168 // If 'script_name' refers to a pipe, don't read to check for an app | 234 // If 'script_name' refers to a pipe, don't read to check for an app |
| 169 // snapshot since we cannot rewind if it isn't (and couldn't mmap it in | 235 // snapshot since we cannot rewind if it isn't (and couldn't mmap it in |
| 170 // anyway if it was). | 236 // anyway if it was). |
| 171 return false; | 237 return NULL; |
| 172 } | 238 } |
| 173 if (ReadAppSnapshotBlobs(script_name, vm_data_buffer, vm_instructions_buffer, | 239 AppSnapshot* snapshot = TryReadAppSnapshotBlobs(script_name); |
| 174 isolate_data_buffer, isolate_instructions_buffer)) { | 240 if (snapshot != NULL) { |
| 175 return true; | 241 return snapshot; |
| 176 } | 242 } |
| 177 #if defined(DART_PRECOMPILED_RUNTIME) | 243 #if defined(DART_PRECOMPILED_RUNTIME) |
| 178 // For testing AOT with the standalone embedder, we also support loading | 244 // For testing AOT with the standalone embedder, we also support loading |
| 179 // from a dynamic library to simulate what happens on iOS. | 245 // from a dynamic library to simulate what happens on iOS. |
| 180 return ReadAppSnapshotDynamicLibrary( | 246 snapshot = TryReadAppSnapshotDynamicLibrary(script_name); |
| 181 script_name, vm_data_buffer, vm_instructions_buffer, isolate_data_buffer, | 247 if (snapshot != NULL) { |
| 182 isolate_instructions_buffer); | 248 return snapshot; |
| 183 #else | 249 } |
| 184 return false; | |
| 185 #endif // defined(DART_PRECOMPILED_RUNTIME) | 250 #endif // defined(DART_PRECOMPILED_RUNTIME) |
| 251 return NULL; |
| 186 } | 252 } |
| 187 | 253 |
| 188 | 254 |
| 189 static void WriteSnapshotFile(const char* filename, | 255 static void WriteSnapshotFile(const char* filename, |
| 190 bool write_magic_number, | 256 bool write_magic_number, |
| 191 const uint8_t* buffer, | 257 const uint8_t* buffer, |
| 192 const intptr_t size) { | 258 const intptr_t size) { |
| 193 File* file = File::Open(filename, File::kWriteTruncate); | 259 File* file = File::Open(filename, File::kWriteTruncate); |
| 194 if (file == NULL) { | 260 if (file == NULL) { |
| 195 ErrorExit(kErrorExitCode, "Unable to open file %s for writing snapshot\n", | 261 ErrorExit(kErrorExitCode, "Unable to open file %s for writing snapshot\n", |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 340 Dart_Handle result = | 406 Dart_Handle result = |
| 341 Dart_CreateAppAOTSnapshotAsAssembly(&assembly_buffer, &assembly_size); | 407 Dart_CreateAppAOTSnapshotAsAssembly(&assembly_buffer, &assembly_size); |
| 342 if (Dart_IsError(result)) { | 408 if (Dart_IsError(result)) { |
| 343 ErrorExit(kErrorExitCode, "%s\n", Dart_GetError(result)); | 409 ErrorExit(kErrorExitCode, "%s\n", Dart_GetError(result)); |
| 344 } | 410 } |
| 345 WriteSnapshotFile(snapshot_filename, false, assembly_buffer, assembly_size); | 411 WriteSnapshotFile(snapshot_filename, false, assembly_buffer, assembly_size); |
| 346 } | 412 } |
| 347 | 413 |
| 348 } // namespace bin | 414 } // namespace bin |
| 349 } // namespace dart | 415 } // namespace dart |
| OLD | NEW |