Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | |
|
zra
2017/02/09 16:15:38
Maybe snapshot_utils.cc? Worried that there will b
rmacnak
2017/02/10 02:11:56
Good point. Done.
| |
| 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. | |
| 4 | |
| 5 #include "bin/snapshot.h" | |
| 6 | |
| 7 #include "include/dart_api.h" | |
| 8 #include "bin/dartutils.h" | |
| 9 #include "bin/exit.h" | |
| 10 #include "bin/extensions.h" | |
| 11 #include "bin/file.h" | |
| 12 | |
| 13 namespace dart { | |
| 14 namespace bin { | |
| 15 | |
| 16 extern const char* kVmSnapshotDataSymbolName; | |
| 17 extern const char* kVmSnapshotInstructionsSymbolName; | |
| 18 extern const char* kIsolateSnapshotDataSymbolName; | |
| 19 extern const char* kIsolateSnapshotInstructionsSymbolName; | |
| 20 | |
| 21 static const int64_t kAppSnapshotHeaderSize = 5 * kInt64Size; | |
| 22 static const int64_t kAppSnapshotMagicNumber = 0xf6f6dcdc; | |
| 23 static const int64_t kAppSnapshotPageSize = 4 * KB; | |
| 24 | |
| 25 static bool ReadAppSnapshotBlobs(const char* script_name, | |
| 26 const uint8_t** vm_data_buffer, | |
| 27 const uint8_t** vm_instructions_buffer, | |
| 28 const uint8_t** isolate_data_buffer, | |
| 29 const uint8_t** isolate_instructions_buffer) { | |
| 30 File* file = File::Open(script_name, File::kRead); | |
| 31 if (file == NULL) { | |
| 32 return false; | |
| 33 } | |
| 34 if (file->Length() < kAppSnapshotHeaderSize) { | |
| 35 file->Release(); | |
| 36 return false; | |
| 37 } | |
| 38 int64_t header[5]; | |
| 39 ASSERT(sizeof(header) == kAppSnapshotHeaderSize); | |
| 40 if (!file->ReadFully(&header, kAppSnapshotHeaderSize)) { | |
| 41 file->Release(); | |
| 42 return false; | |
| 43 } | |
| 44 if (header[0] != kAppSnapshotMagicNumber) { | |
| 45 file->Release(); | |
| 46 return false; | |
| 47 } | |
| 48 | |
| 49 int64_t vm_data_size = header[1]; | |
| 50 int64_t vm_data_position = | |
| 51 Utils::RoundUp(file->Position(), kAppSnapshotPageSize); | |
| 52 int64_t vm_instructions_size = header[2]; | |
| 53 int64_t vm_instructions_position = vm_data_position + vm_data_size; | |
| 54 if (vm_instructions_size != 0) { | |
| 55 vm_instructions_position = | |
| 56 Utils::RoundUp(vm_instructions_position, kAppSnapshotPageSize); | |
| 57 } | |
| 58 int64_t isolate_data_size = header[3]; | |
| 59 int64_t isolate_data_position = Utils::RoundUp( | |
| 60 vm_instructions_position + vm_instructions_size, kAppSnapshotPageSize); | |
| 61 int64_t isolate_instructions_size = header[4]; | |
| 62 int64_t isolate_instructions_position = | |
| 63 isolate_data_position + isolate_data_size; | |
| 64 if (isolate_instructions_size != 0) { | |
| 65 isolate_instructions_position = | |
| 66 Utils::RoundUp(isolate_instructions_position, kAppSnapshotPageSize); | |
| 67 } | |
| 68 | |
| 69 if (vm_data_size != 0) { | |
| 70 *vm_data_buffer = reinterpret_cast<const uint8_t*>( | |
| 71 file->Map(File::kReadOnly, vm_data_position, vm_data_size)); | |
| 72 if (vm_data_buffer == NULL) { | |
| 73 Log::PrintErr("Failed to memory map snapshot\n"); | |
| 74 Platform::Exit(kErrorExitCode); | |
| 75 } | |
| 76 } | |
| 77 | |
| 78 if (vm_instructions_size != 0) { | |
| 79 *vm_instructions_buffer = reinterpret_cast<const uint8_t*>(file->Map( | |
| 80 File::kReadExecute, vm_instructions_position, vm_instructions_size)); | |
| 81 if (*vm_instructions_buffer == NULL) { | |
| 82 Log::PrintErr("Failed to memory map snapshot\n"); | |
| 83 Platform::Exit(kErrorExitCode); | |
| 84 } | |
| 85 } | |
| 86 | |
| 87 *isolate_data_buffer = reinterpret_cast<const uint8_t*>( | |
| 88 file->Map(File::kReadOnly, isolate_data_position, isolate_data_size)); | |
| 89 if (isolate_data_buffer == NULL) { | |
| 90 Log::PrintErr("Failed to memory map snapshot\n"); | |
| 91 Platform::Exit(kErrorExitCode); | |
| 92 } | |
| 93 | |
| 94 if (isolate_instructions_size == 0) { | |
| 95 *isolate_instructions_buffer = NULL; | |
| 96 } else { | |
| 97 *isolate_instructions_buffer = reinterpret_cast<const uint8_t*>( | |
| 98 file->Map(File::kReadExecute, isolate_instructions_position, | |
| 99 isolate_instructions_size)); | |
| 100 if (*isolate_instructions_buffer == NULL) { | |
| 101 Log::PrintErr("Failed to memory map snapshot\n"); | |
| 102 Platform::Exit(kErrorExitCode); | |
| 103 } | |
| 104 } | |
| 105 | |
| 106 file->Release(); | |
| 107 return true; | |
| 108 } | |
| 109 | |
| 110 | |
| 111 #if defined(DART_PRECOMPILED_RUNTIME) | |
| 112 static bool ReadAppSnapshotDynamicLibrary( | |
| 113 const char* script_name, | |
| 114 const uint8_t** vm_data_buffer, | |
| 115 const uint8_t** vm_instructions_buffer, | |
| 116 const uint8_t** isolate_data_buffer, | |
| 117 const uint8_t** isolate_instructions_buffer) { | |
| 118 void* library = Extensions::LoadExtensionLibrary(script_name); | |
| 119 if (library == NULL) { | |
| 120 return false; | |
| 121 } | |
| 122 | |
| 123 *vm_data_buffer = reinterpret_cast<const uint8_t*>( | |
| 124 Extensions::ResolveSymbol(library, kVmSnapshotDataSymbolName)); | |
| 125 if (*vm_data_buffer == NULL) { | |
| 126 Log::PrintErr("Failed to resolve symbol '%s'\n", kVmSnapshotDataSymbolName); | |
| 127 Platform::Exit(kErrorExitCode); | |
| 128 } | |
| 129 | |
| 130 *vm_instructions_buffer = reinterpret_cast<const uint8_t*>( | |
| 131 Extensions::ResolveSymbol(library, kVmSnapshotInstructionsSymbolName)); | |
| 132 if (*vm_instructions_buffer == NULL) { | |
| 133 Log::PrintErr("Failed to resolve symbol '%s'\n", | |
| 134 kVmSnapshotInstructionsSymbolName); | |
| 135 Platform::Exit(kErrorExitCode); | |
| 136 } | |
| 137 | |
| 138 *isolate_data_buffer = reinterpret_cast<const uint8_t*>( | |
| 139 Extensions::ResolveSymbol(library, kIsolateSnapshotDataSymbolName)); | |
| 140 if (*isolate_data_buffer == NULL) { | |
| 141 Log::PrintErr("Failed to resolve symbol '%s'\n", | |
| 142 kIsolateSnapshotDataSymbolName); | |
| 143 Platform::Exit(kErrorExitCode); | |
| 144 } | |
| 145 | |
| 146 *isolate_instructions_buffer = | |
| 147 reinterpret_cast<const uint8_t*>(Extensions::ResolveSymbol( | |
| 148 library, kIsolateSnapshotInstructionsSymbolName)); | |
| 149 if (*isolate_instructions_buffer == NULL) { | |
| 150 Log::PrintErr("Failed to resolve symbol '%s'\n", | |
| 151 kIsolateSnapshotInstructionsSymbolName); | |
| 152 Platform::Exit(kErrorExitCode); | |
| 153 } | |
| 154 | |
| 155 return true; | |
| 156 } | |
| 157 #endif // defined(DART_PRECOMPILED_RUNTIME) | |
| 158 | |
| 159 | |
| 160 bool Snapshot::ReadAppSnapshot(const char* script_name, | |
| 161 const uint8_t** vm_data_buffer, | |
| 162 const uint8_t** vm_instructions_buffer, | |
| 163 const uint8_t** isolate_data_buffer, | |
| 164 const uint8_t** isolate_instructions_buffer) { | |
| 165 if (File::GetType(script_name, true) != File::kIsFile) { | |
| 166 // If 'script_name' refers to a pipe, don't read to check for an app | |
| 167 // snapshot since we cannot rewind if it isn't (and couldn't mmap it in | |
| 168 // anyway if it was). | |
| 169 return false; | |
| 170 } | |
| 171 if (ReadAppSnapshotBlobs(script_name, vm_data_buffer, vm_instructions_buffer, | |
| 172 isolate_data_buffer, isolate_instructions_buffer)) { | |
| 173 return true; | |
| 174 } | |
| 175 #if defined(DART_PRECOMPILED_RUNTIME) | |
| 176 // For testing AOT with the standalone embedder, we also support loading | |
| 177 // from a dynamic library to simulate what happens on iOS. | |
| 178 return ReadAppSnapshotDynamicLibrary( | |
| 179 script_name, vm_data_buffer, vm_instructions_buffer, isolate_data_buffer, | |
| 180 isolate_instructions_buffer); | |
| 181 #else | |
| 182 return false; | |
| 183 #endif // defined(DART_PRECOMPILED_RUNTIME) | |
| 184 } | |
| 185 | |
| 186 | |
| 187 static void WriteSnapshotFile(const char* filename, | |
| 188 bool write_magic_number, | |
| 189 const uint8_t* buffer, | |
| 190 const intptr_t size) { | |
| 191 File* file = File::Open(filename, File::kWriteTruncate); | |
| 192 if (file == NULL) { | |
| 193 ErrorExit(kErrorExitCode, "Unable to open file %s for writing snapshot\n", | |
| 194 filename); | |
| 195 } | |
| 196 | |
| 197 if (write_magic_number) { | |
| 198 // Write the magic number to indicate file is a script snapshot. | |
| 199 DartUtils::WriteMagicNumber(file); | |
| 200 } | |
| 201 | |
| 202 if (!file->WriteFully(buffer, size)) { | |
| 203 ErrorExit(kErrorExitCode, "Unable to write file %s for writing snapshot\n", | |
| 204 filename); | |
| 205 } | |
| 206 file->Release(); | |
| 207 } | |
| 208 | |
| 209 | |
| 210 static bool WriteInt64(File* file, int64_t size) { | |
| 211 return file->WriteFully(&size, sizeof(size)); | |
| 212 } | |
| 213 | |
| 214 | |
| 215 static void WriteAppSnapshot(const char* filename, | |
| 216 uint8_t* vm_data_buffer, | |
| 217 intptr_t vm_data_size, | |
| 218 uint8_t* vm_instructions_buffer, | |
| 219 intptr_t vm_instructions_size, | |
| 220 uint8_t* isolate_data_buffer, | |
| 221 intptr_t isolate_data_size, | |
| 222 uint8_t* isolate_instructions_buffer, | |
| 223 intptr_t isolate_instructions_size) { | |
| 224 File* file = File::Open(filename, File::kWriteTruncate); | |
| 225 if (file == NULL) { | |
| 226 ErrorExit(kErrorExitCode, "Unable to write snapshot file '%s'\n", filename); | |
| 227 } | |
| 228 | |
| 229 file->WriteFully(&kAppSnapshotMagicNumber, sizeof(kAppSnapshotMagicNumber)); | |
| 230 WriteInt64(file, vm_data_size); | |
| 231 WriteInt64(file, vm_instructions_size); | |
| 232 WriteInt64(file, isolate_data_size); | |
| 233 WriteInt64(file, isolate_instructions_size); | |
| 234 ASSERT(file->Position() == kAppSnapshotHeaderSize); | |
| 235 | |
| 236 file->SetPosition(Utils::RoundUp(file->Position(), kAppSnapshotPageSize)); | |
| 237 if (!file->WriteFully(vm_data_buffer, vm_data_size)) { | |
| 238 ErrorExit(kErrorExitCode, "Unable to write snapshot file '%s'\n", filename); | |
| 239 } | |
| 240 | |
| 241 if (vm_instructions_size != 0) { | |
| 242 file->SetPosition(Utils::RoundUp(file->Position(), kAppSnapshotPageSize)); | |
| 243 if (!file->WriteFully(vm_instructions_buffer, vm_instructions_size)) { | |
| 244 ErrorExit(kErrorExitCode, "Unable to write snapshot file '%s'\n", | |
| 245 filename); | |
| 246 } | |
| 247 } | |
| 248 | |
| 249 file->SetPosition(Utils::RoundUp(file->Position(), kAppSnapshotPageSize)); | |
| 250 if (!file->WriteFully(isolate_data_buffer, isolate_data_size)) { | |
| 251 ErrorExit(kErrorExitCode, "Unable to write snapshot file '%s'\n", filename); | |
| 252 } | |
| 253 | |
| 254 if (isolate_instructions_size != 0) { | |
| 255 file->SetPosition(Utils::RoundUp(file->Position(), kAppSnapshotPageSize)); | |
| 256 if (!file->WriteFully(isolate_instructions_buffer, | |
| 257 isolate_instructions_size)) { | |
| 258 ErrorExit(kErrorExitCode, "Unable to write snapshot file '%s'\n", | |
| 259 filename); | |
| 260 } | |
| 261 } | |
| 262 | |
| 263 file->Flush(); | |
| 264 file->Release(); | |
| 265 } | |
| 266 | |
| 267 | |
| 268 void Snapshot::GenerateScript(const char* snapshot_filename) { | |
| 269 // First create a snapshot. | |
| 270 uint8_t* buffer = NULL; | |
| 271 intptr_t size = 0; | |
| 272 Dart_Handle result = Dart_CreateScriptSnapshot(&buffer, &size); | |
| 273 if (Dart_IsError(result)) { | |
| 274 ErrorExit(kErrorExitCode, "%s\n", Dart_GetError(result)); | |
| 275 } | |
| 276 | |
| 277 WriteSnapshotFile(snapshot_filename, true, buffer, size); | |
| 278 } | |
| 279 | |
| 280 | |
| 281 void Snapshot::GenerateAppJIT(const char* snapshot_filename) { | |
| 282 #if defined(TARGET_ARCH_X64) | |
| 283 uint8_t* isolate_data_buffer = NULL; | |
| 284 intptr_t isolate_data_size = 0; | |
| 285 uint8_t* isolate_instructions_buffer = NULL; | |
| 286 intptr_t isolate_instructions_size = 0; | |
| 287 Dart_Handle result = Dart_CreateAppJITSnapshotAsBlobs( | |
| 288 &isolate_data_buffer, &isolate_data_size, &isolate_instructions_buffer, | |
| 289 &isolate_instructions_size); | |
| 290 if (Dart_IsError(result)) { | |
| 291 ErrorExit(kErrorExitCode, "%s\n", Dart_GetError(result)); | |
| 292 } | |
| 293 WriteAppSnapshot(snapshot_filename, NULL, 0, NULL, 0, isolate_data_buffer, | |
| 294 isolate_data_size, isolate_instructions_buffer, | |
| 295 isolate_instructions_size); | |
| 296 #else | |
| 297 uint8_t* isolate_buffer = NULL; | |
| 298 intptr_t isolate_size = 0; | |
| 299 | |
| 300 Dart_Handle result = | |
| 301 Dart_CreateSnapshot(NULL, NULL, &isolate_buffer, &isolate_size); | |
| 302 if (Dart_IsError(result)) { | |
| 303 ErrorExit(kErrorExitCode, "%s\n", Dart_GetError(result)); | |
| 304 } | |
| 305 | |
| 306 WriteAppSnapshot(snapshot_filename, NULL, 0, NULL, 0, isolate_buffer, | |
| 307 isolate_size, NULL, 0); | |
| 308 #endif // defined(TARGET_ARCH_X64) | |
| 309 } | |
| 310 | |
| 311 | |
| 312 void Snapshot::GenerateAppAOTAsBlobs(const char* snapshot_filename) { | |
| 313 uint8_t* vm_data_buffer = NULL; | |
| 314 intptr_t vm_data_size = 0; | |
| 315 uint8_t* vm_instructions_buffer = NULL; | |
| 316 intptr_t vm_instructions_size = 0; | |
| 317 uint8_t* isolate_data_buffer = NULL; | |
| 318 intptr_t isolate_data_size = 0; | |
| 319 uint8_t* isolate_instructions_buffer = NULL; | |
| 320 intptr_t isolate_instructions_size = 0; | |
| 321 Dart_Handle result = Dart_CreateAppAOTSnapshotAsBlobs( | |
| 322 &vm_data_buffer, &vm_data_size, &vm_instructions_buffer, | |
| 323 &vm_instructions_size, &isolate_data_buffer, &isolate_data_size, | |
| 324 &isolate_instructions_buffer, &isolate_instructions_size); | |
| 325 if (Dart_IsError(result)) { | |
| 326 ErrorExit(kErrorExitCode, "%s\n", Dart_GetError(result)); | |
| 327 } | |
| 328 WriteAppSnapshot(snapshot_filename, vm_data_buffer, vm_data_size, | |
| 329 vm_instructions_buffer, vm_instructions_size, | |
| 330 isolate_data_buffer, isolate_data_size, | |
| 331 isolate_instructions_buffer, isolate_instructions_size); | |
| 332 } | |
| 333 | |
| 334 | |
| 335 void Snapshot::GenerateAppAOTAsAssembly(const char* snapshot_filename) { | |
| 336 uint8_t* assembly_buffer = NULL; | |
| 337 intptr_t assembly_size = 0; | |
| 338 Dart_Handle result = | |
| 339 Dart_CreateAppAOTSnapshotAsAssembly(&assembly_buffer, &assembly_size); | |
| 340 if (Dart_IsError(result)) { | |
| 341 ErrorExit(kErrorExitCode, "%s\n", Dart_GetError(result)); | |
| 342 } | |
| 343 WriteSnapshotFile(snapshot_filename, false, assembly_buffer, assembly_size); | |
| 344 } | |
| 345 | |
| 346 } // namespace bin | |
| 347 } // namespace dart | |
| OLD | NEW |