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 |