Chromium Code Reviews| 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 Log::PrintErr("Failed to memory map snapshot\n"); |
|
zra
2017/02/15 04:41:40
Why not:
FATAL1("Failed to memory map snapshot: %
rmacnak
2017/02/16 03:05:30
Done.
| |
| 76 Platform::Exit(kErrorExitCode); | 121 Platform::Exit(kErrorExitCode); |
| 77 } | 122 } |
| 78 } | 123 } |
| 79 | 124 |
| 125 MappedMemory* vm_instr_mapping = NULL; | |
| 80 if (vm_instructions_size != 0) { | 126 if (vm_instructions_size != 0) { |
| 81 *vm_instructions_buffer = reinterpret_cast<const uint8_t*>(file->Map( | 127 vm_instr_mapping = file->Map(File::kReadExecute, vm_instructions_position, |
| 82 File::kReadExecute, vm_instructions_position, vm_instructions_size)); | 128 vm_instructions_size); |
| 83 if (*vm_instructions_buffer == NULL) { | 129 if (vm_instr_mapping == NULL) { |
| 84 Log::PrintErr("Failed to memory map snapshot\n"); | 130 Log::PrintErr("Failed to memory map snapshot\n"); |
| 85 Platform::Exit(kErrorExitCode); | 131 Platform::Exit(kErrorExitCode); |
| 86 } | 132 } |
| 87 } | 133 } |
| 88 | 134 |
| 89 *isolate_data_buffer = reinterpret_cast<const uint8_t*>( | 135 MappedMemory* isolate_data_mapping = NULL; |
| 90 file->Map(File::kReadOnly, isolate_data_position, isolate_data_size)); | 136 if (isolate_data_size != 0) { |
| 91 if (isolate_data_buffer == NULL) { | 137 isolate_data_mapping = |
| 92 Log::PrintErr("Failed to memory map snapshot\n"); | 138 file->Map(File::kReadOnly, isolate_data_position, isolate_data_size); |
| 93 Platform::Exit(kErrorExitCode); | 139 if (isolate_data_mapping == NULL) { |
| 140 Log::PrintErr("Failed to memory map snapshot\n"); | |
| 141 Platform::Exit(kErrorExitCode); | |
| 142 } | |
| 94 } | 143 } |
| 95 | 144 |
| 96 if (isolate_instructions_size == 0) { | 145 MappedMemory* isolate_instr_mapping = NULL; |
| 97 *isolate_instructions_buffer = NULL; | 146 if (isolate_instructions_size != 0) { |
| 98 } else { | 147 isolate_instr_mapping = |
| 99 *isolate_instructions_buffer = reinterpret_cast<const uint8_t*>( | |
| 100 file->Map(File::kReadExecute, isolate_instructions_position, | 148 file->Map(File::kReadExecute, isolate_instructions_position, |
| 101 isolate_instructions_size)); | 149 isolate_instructions_size); |
| 102 if (*isolate_instructions_buffer == NULL) { | 150 if (isolate_instr_mapping == NULL) { |
| 103 Log::PrintErr("Failed to memory map snapshot\n"); | 151 Log::PrintErr("Failed to memory map snapshot\n"); |
| 104 Platform::Exit(kErrorExitCode); | 152 Platform::Exit(kErrorExitCode); |
| 105 } | 153 } |
| 106 } | 154 } |
| 107 | 155 |
| 108 file->Release(); | 156 file->Release(); |
| 109 return true; | 157 return new MappedAppSnapshot(vm_data_mapping, vm_instr_mapping, |
| 158 isolate_data_mapping, isolate_instr_mapping); | |
| 110 } | 159 } |
| 111 | 160 |
| 112 | 161 |
| 113 #if defined(DART_PRECOMPILED_RUNTIME) | 162 #if defined(DART_PRECOMPILED_RUNTIME) |
| 114 static bool ReadAppSnapshotDynamicLibrary( | 163 class DylibAppSnapshot : public AppSnapshot { |
| 115 const char* script_name, | 164 public: |
| 116 const uint8_t** vm_data_buffer, | 165 DylibAppSnapshot(void* library, |
| 117 const uint8_t** vm_instructions_buffer, | 166 const uint8_t* vm_snapshot_data, |
| 118 const uint8_t** isolate_data_buffer, | 167 const uint8_t* vm_snapshot_instructions, |
| 119 const uint8_t** isolate_instructions_buffer) { | 168 const uint8_t* isolate_snapshot_data, |
| 120 void* library = Extensions::LoadExtensionLibrary(script_name); | 169 const uint8_t* isolate_snapshot_instructions) |
| 121 if (library == NULL) { | 170 : library_(library), |
| 122 return false; | 171 vm_snapshot_data_(vm_snapshot_data), |
| 172 vm_snapshot_instructions_(vm_snapshot_instructions), | |
| 173 isolate_snapshot_data_(isolate_snapshot_data), | |
| 174 isolate_snapshot_instructions_(isolate_snapshot_instructions) {} | |
| 175 | |
| 176 ~DylibAppSnapshot() { Extensions::UnloadLibrary(library_); } | |
| 177 | |
| 178 void SetBuffers(const uint8_t** vm_data_buffer, | |
| 179 const uint8_t** vm_instructions_buffer, | |
| 180 const uint8_t** isolate_data_buffer, | |
| 181 const uint8_t** isolate_instructions_buffer) { | |
| 182 *vm_data_buffer = vm_snapshot_data_; | |
| 183 *vm_instructions_buffer = vm_snapshot_instructions_; | |
| 184 *isolate_data_buffer = isolate_snapshot_data_; | |
| 185 *isolate_instructions_buffer = isolate_snapshot_instructions_; | |
| 123 } | 186 } |
| 124 | 187 |
| 125 *vm_data_buffer = reinterpret_cast<const uint8_t*>( | 188 private: |
| 189 void* library_; | |
| 190 const uint8_t* vm_snapshot_data_; | |
| 191 const uint8_t* vm_snapshot_instructions_; | |
| 192 const uint8_t* isolate_snapshot_data_; | |
| 193 const uint8_t* isolate_snapshot_instructions_; | |
| 194 }; | |
| 195 | |
| 196 | |
| 197 static AppSnapshot* TryReadAppSnapshotDynamicLibrary(const char* script_name) { | |
| 198 void* library = Extensions::LoadLibrary(script_name); | |
| 199 if (library == NULL) { | |
| 200 return NULL; | |
| 201 } | |
| 202 | |
| 203 const uint8_t* vm_data_buffer = reinterpret_cast<const uint8_t*>( | |
| 126 Extensions::ResolveSymbol(library, kVmSnapshotDataSymbolName)); | 204 Extensions::ResolveSymbol(library, kVmSnapshotDataSymbolName)); |
| 127 if (*vm_data_buffer == NULL) { | 205 if (vm_data_buffer == NULL) { |
| 128 Log::PrintErr("Failed to resolve symbol '%s'\n", kVmSnapshotDataSymbolName); | 206 Log::PrintErr("Failed to resolve symbol '%s'\n", kVmSnapshotDataSymbolName); |
| 129 Platform::Exit(kErrorExitCode); | 207 Platform::Exit(kErrorExitCode); |
| 130 } | 208 } |
| 131 | 209 |
| 132 *vm_instructions_buffer = reinterpret_cast<const uint8_t*>( | 210 const uint8_t* vm_instructions_buffer = reinterpret_cast<const uint8_t*>( |
| 133 Extensions::ResolveSymbol(library, kVmSnapshotInstructionsSymbolName)); | 211 Extensions::ResolveSymbol(library, kVmSnapshotInstructionsSymbolName)); |
| 134 if (*vm_instructions_buffer == NULL) { | 212 if (vm_instructions_buffer == NULL) { |
| 135 Log::PrintErr("Failed to resolve symbol '%s'\n", | 213 Log::PrintErr("Failed to resolve symbol '%s'\n", |
| 136 kVmSnapshotInstructionsSymbolName); | 214 kVmSnapshotInstructionsSymbolName); |
| 137 Platform::Exit(kErrorExitCode); | 215 Platform::Exit(kErrorExitCode); |
| 138 } | 216 } |
| 139 | 217 |
| 140 *isolate_data_buffer = reinterpret_cast<const uint8_t*>( | 218 const uint8_t* isolate_data_buffer = reinterpret_cast<const uint8_t*>( |
| 141 Extensions::ResolveSymbol(library, kIsolateSnapshotDataSymbolName)); | 219 Extensions::ResolveSymbol(library, kIsolateSnapshotDataSymbolName)); |
| 142 if (*isolate_data_buffer == NULL) { | 220 if (isolate_data_buffer == NULL) { |
| 143 Log::PrintErr("Failed to resolve symbol '%s'\n", | 221 Log::PrintErr("Failed to resolve symbol '%s'\n", |
| 144 kIsolateSnapshotDataSymbolName); | 222 kIsolateSnapshotDataSymbolName); |
| 145 Platform::Exit(kErrorExitCode); | 223 Platform::Exit(kErrorExitCode); |
| 146 } | 224 } |
| 147 | 225 |
| 148 *isolate_instructions_buffer = | 226 const uint8_t* isolate_instructions_buffer = |
| 149 reinterpret_cast<const uint8_t*>(Extensions::ResolveSymbol( | 227 reinterpret_cast<const uint8_t*>(Extensions::ResolveSymbol( |
| 150 library, kIsolateSnapshotInstructionsSymbolName)); | 228 library, kIsolateSnapshotInstructionsSymbolName)); |
| 151 if (*isolate_instructions_buffer == NULL) { | 229 if (isolate_instructions_buffer == NULL) { |
| 152 Log::PrintErr("Failed to resolve symbol '%s'\n", | 230 Log::PrintErr("Failed to resolve symbol '%s'\n", |
| 153 kIsolateSnapshotInstructionsSymbolName); | 231 kIsolateSnapshotInstructionsSymbolName); |
| 154 Platform::Exit(kErrorExitCode); | 232 Platform::Exit(kErrorExitCode); |
| 155 } | 233 } |
| 156 | 234 |
| 157 return true; | 235 return new DylibAppSnapshot(library, vm_data_buffer, vm_instructions_buffer, |
| 236 isolate_data_buffer, isolate_instructions_buffer); | |
| 158 } | 237 } |
| 159 #endif // defined(DART_PRECOMPILED_RUNTIME) | 238 #endif // defined(DART_PRECOMPILED_RUNTIME) |
| 160 | 239 |
| 161 | 240 |
| 162 bool Snapshot::ReadAppSnapshot(const char* script_name, | 241 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) { | 242 if (File::GetType(script_name, true) != File::kIsFile) { |
| 168 // If 'script_name' refers to a pipe, don't read to check for an app | 243 // 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 | 244 // snapshot since we cannot rewind if it isn't (and couldn't mmap it in |
| 170 // anyway if it was). | 245 // anyway if it was). |
| 171 return false; | 246 return NULL; |
| 172 } | 247 } |
| 173 if (ReadAppSnapshotBlobs(script_name, vm_data_buffer, vm_instructions_buffer, | 248 AppSnapshot* snapshot = TryReadAppSnapshotBlobs(script_name); |
| 174 isolate_data_buffer, isolate_instructions_buffer)) { | 249 if (snapshot != NULL) { |
| 175 return true; | 250 return snapshot; |
| 176 } | 251 } |
| 177 #if defined(DART_PRECOMPILED_RUNTIME) | 252 #if defined(DART_PRECOMPILED_RUNTIME) |
| 178 // For testing AOT with the standalone embedder, we also support loading | 253 // For testing AOT with the standalone embedder, we also support loading |
| 179 // from a dynamic library to simulate what happens on iOS. | 254 // from a dynamic library to simulate what happens on iOS. |
| 180 return ReadAppSnapshotDynamicLibrary( | 255 snapshot = TryReadAppSnapshotDynamicLibrary(script_name); |
| 181 script_name, vm_data_buffer, vm_instructions_buffer, isolate_data_buffer, | 256 if (snapshot != NULL) { |
| 182 isolate_instructions_buffer); | 257 return snapshot; |
| 183 #else | 258 } |
| 184 return false; | |
| 185 #endif // defined(DART_PRECOMPILED_RUNTIME) | 259 #endif // defined(DART_PRECOMPILED_RUNTIME) |
| 260 return NULL; | |
| 186 } | 261 } |
| 187 | 262 |
| 188 | 263 |
| 189 static void WriteSnapshotFile(const char* filename, | 264 static void WriteSnapshotFile(const char* filename, |
| 190 bool write_magic_number, | 265 bool write_magic_number, |
| 191 const uint8_t* buffer, | 266 const uint8_t* buffer, |
| 192 const intptr_t size) { | 267 const intptr_t size) { |
| 193 File* file = File::Open(filename, File::kWriteTruncate); | 268 File* file = File::Open(filename, File::kWriteTruncate); |
| 194 if (file == NULL) { | 269 if (file == NULL) { |
| 195 ErrorExit(kErrorExitCode, "Unable to open file %s for writing snapshot\n", | 270 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 = | 415 Dart_Handle result = |
| 341 Dart_CreateAppAOTSnapshotAsAssembly(&assembly_buffer, &assembly_size); | 416 Dart_CreateAppAOTSnapshotAsAssembly(&assembly_buffer, &assembly_size); |
| 342 if (Dart_IsError(result)) { | 417 if (Dart_IsError(result)) { |
| 343 ErrorExit(kErrorExitCode, "%s\n", Dart_GetError(result)); | 418 ErrorExit(kErrorExitCode, "%s\n", Dart_GetError(result)); |
| 344 } | 419 } |
| 345 WriteSnapshotFile(snapshot_filename, false, assembly_buffer, assembly_size); | 420 WriteSnapshotFile(snapshot_filename, false, assembly_buffer, assembly_size); |
| 346 } | 421 } |
| 347 | 422 |
| 348 } // namespace bin | 423 } // namespace bin |
| 349 } // namespace dart | 424 } // namespace dart |
| OLD | NEW |