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 |