OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | |
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 #ifndef VM_CLUSTERED_SNAPSHOT_H_ | |
6 #define VM_CLUSTERED_SNAPSHOT_H_ | |
7 | |
8 #include "platform/assert.h" | |
siva
2016/06/21 23:51:43
blank line after this?
rmacnak
2016/06/22 19:42:17
We generally only separate a cc's corresponding he
| |
9 #include "vm/allocation.h" | |
10 #include "vm/bitfield.h" | |
11 #include "vm/datastream.h" | |
12 #include "vm/exceptions.h" | |
13 #include "vm/globals.h" | |
14 #include "vm/growable_array.h" | |
15 #include "vm/isolate.h" | |
16 #include "vm/visitor.h" | |
17 #include "vm/snapshot.h" | |
18 #include "vm/heap.h" | |
19 #include "vm/object.h" | |
20 #include "vm/version.h" | |
siva
2016/06/21 23:51:43
doesn't seem to be in alphabetic order
rmacnak
2016/06/22 19:42:17
Re-sorted.
| |
21 | |
22 namespace dart { | |
23 | |
siva
2016/06/21 23:51:43
Add comment,
// Forward declarations.
rmacnak
2016/06/22 19:42:17
Done.
| |
24 class Serializer; | |
25 class Deserializer; | |
26 class ObjectStore; | |
27 | |
28 // For full snapshots, we use a clustered snapshot format that trades longer | |
29 // serialization time for faster deserialization time and smaller snapshots. | |
30 // Objects are clustered by class to allow writing type information once per | |
31 // class instead for each object, and to allow filling the objects in a tight | |
siva
2016/06/21 23:51:43
instead of once per object,
rmacnak
2016/06/22 19:42:17
Done.
| |
32 // loop. The snapshot has two major sections: the first describes how to | |
siva
2016/06/21 23:51:43
two sections ? (there are no minor sections right)
rmacnak
2016/06/22 19:42:17
Well, in some sense the major sections for allocat
| |
33 // allocate the objects and the second describes how to initialize them. | |
34 // Deserialization starts by allocating a reference array large enough to hold | |
35 // the base objects (objects already available to both the serializer and | |
36 // deserializer) and the objects written in the snapshot. The allocation section | |
37 // is then read for each cluster, filling the reference array. Then the | |
38 // initialization/fill secton is read for cluster, using the indices into the | |
siva
2016/06/21 23:51:43
for each cluster
rmacnak
2016/06/22 19:42:18
Done.
| |
39 // reference array to fill pointers. At this point, every object has been | |
40 // touched exactly once and in order, making this approach very cache friendly. | |
41 // Finally, each cluster is given an opportunity to perform some fix-ups that | |
42 // require the graph has been fully loaded, such as rehashing, though most | |
43 // clusters do not require fixups. | |
44 | |
45 class SerializationCluster : public ZoneAllocated { | |
46 public: | |
47 virtual ~SerializationCluster() { } | |
48 | |
49 // Add [object] to the cluster and push its outgoing references. | |
50 virtual void Trace(Serializer* serializer, RawObject* object) = 0; | |
51 | |
52 // Write the cluster type and information needed to allocate the cluster's | |
53 // objects. For fixed sized objects, this is just the object count. For | |
54 // variable sized objects, this is the object count and length of each object. | |
55 virtual void WriteAlloc(Serializer* serializer) = 0; | |
56 | |
57 // Write the byte and reference data of the cluster's objects. | |
58 virtual void WriteFill(Serializer* serializer) = 0; | |
59 }; | |
60 | |
61 | |
62 class DeserializationCluster : public ZoneAllocated { | |
63 public: | |
64 DeserializationCluster() : start_index_(-1), stop_index_(-1) { } | |
65 virtual ~DeserializationCluster() { } | |
66 | |
67 // Allocate memory for all objects in the cluster and write their addresses | |
68 // into the ref array. Do not touch this memory. | |
69 virtual void ReadAlloc(Deserializer* deserializer) = 0; | |
70 | |
71 // Initialize the cluster's objects. Do not touch the memory of other objects. | |
72 virtual void ReadFill(Deserializer* deserializer) = 0; | |
73 | |
74 // Complete any action that requires the full graph to be deserialized, such | |
75 // as rehashing. | |
76 virtual void PostLoad(const Array& refs, Snapshot::Kind kind, Zone* zone) { } | |
siva
2016/06/21 23:51:43
Why do you have the kind parameter here if this is
rmacnak
2016/06/22 19:42:18
Some actions are taken only for AOT snapshots.
| |
77 | |
78 protected: | |
79 // The range of the ref array that belongs to this cluster. | |
80 intptr_t start_index_; | |
81 intptr_t stop_index_; | |
82 }; | |
83 | |
84 | |
85 class Serializer : public StackResource { | |
86 public: | |
87 Serializer(Thread* thread, | |
88 Snapshot::Kind kind, | |
89 uint8_t** buffer, | |
90 ReAlloc alloc, | |
91 intptr_t initial_size, | |
92 InstructionsWriter* instructions_writer_); | |
93 ~Serializer(); | |
94 | |
95 intptr_t WriteVMSnapshot(const Array& symbols, const Array& scripts); | |
96 void WriteFullSnapshot(intptr_t num_base_objects, ObjectStore* object_store); | |
97 | |
98 void AddVMIsolateBaseObjects(); | |
99 | |
100 void AddBaseObject(RawObject* base_object) { | |
101 AssignRefNotTraced(base_object); | |
102 num_base_objects_++; | |
103 } | |
104 | |
105 void AssignRefNotTraced(RawObject* object) { | |
106 ASSERT(next_ref_index_ != 0); | |
107 heap_->SetObjectId(object, next_ref_index_); | |
108 ASSERT(heap_->GetObjectId(object) == next_ref_index_); | |
109 next_ref_index_++; | |
110 } | |
111 | |
112 void AssignRef(RawObject* object) { | |
113 ASSERT(next_ref_index_ != 0); | |
114 ASSERT(heap_->GetObjectId(object) == 1); | |
115 heap_->SetObjectId(object, next_ref_index_); | |
116 ASSERT(heap_->GetObjectId(object) == next_ref_index_); | |
117 next_ref_index_++; | |
118 } | |
119 | |
120 void Push(RawObject* object) { | |
121 if (!object->IsHeapObject()) { | |
122 return; | |
123 } | |
124 | |
125 if (object->IsCode() && !Snapshot::IncludesCode(kind_)) { | |
126 return; // Do not trace, will write null. | |
127 } | |
128 | |
129 if (object->IsSendPort()) { | |
130 // TODO(rmacnak): Do a better job of resetting fields in precompilation | |
131 // and assert this is unreachable. | |
132 return; // Do not trace, will write null. | |
133 } | |
134 | |
135 intptr_t id = heap_->GetObjectId(object); | |
136 if (id == 0) { | |
137 heap_->SetObjectId(object, 1); | |
138 ASSERT(heap_->GetObjectId(object) != 0); | |
139 stack_.Add(object); | |
140 num_written_objects_++; | |
141 } | |
142 } | |
143 | |
144 void AddUntracedRef() { | |
145 num_written_objects_++; | |
146 } | |
147 | |
148 void Trace(RawObject* object); | |
149 | |
150 SerializationCluster* NewClusterForClass(intptr_t cid); | |
151 | |
152 void ReserveHeader() { | |
153 // Make room for recording snapshot buffer size. | |
154 stream_.set_current(stream_.buffer() + Snapshot::kHeaderSize); | |
155 } | |
156 | |
157 void FillHeader(Snapshot::Kind kind) { | |
158 int64_t* data = reinterpret_cast<int64_t*>(stream_.buffer()); | |
159 data[Snapshot::kLengthIndex] = stream_.bytes_written(); | |
160 data[Snapshot::kSnapshotFlagIndex] = kind; | |
161 } | |
162 | |
163 void WriteVersionAndFeatures(); | |
164 | |
165 void Serialize(); | |
166 intptr_t bytes_written() { return stream_.bytes_written(); } | |
167 | |
168 // Writes raw data to the stream (basic type). | |
169 // sizeof(T) must be in {1,2,4,8}. | |
170 template <typename T> | |
171 void Write(T value) { | |
172 WriteStream::Raw<sizeof(T), T>::Write(&stream_, value); | |
173 } | |
174 | |
175 void WriteBytes(const uint8_t* addr, intptr_t len) { | |
176 stream_.WriteBytes(addr, len); | |
177 } | |
178 | |
179 void WriteRef(RawObject* object) { | |
180 if (!object->IsHeapObject()) { | |
181 Write<intptr_t>(reinterpret_cast<intptr_t>(object)); | |
182 return; | |
183 } | |
184 | |
185 intptr_t id = heap_->GetObjectId(object); | |
186 if (id == 0) { | |
187 if (object->IsCode() && !Snapshot::IncludesCode(kind_)) { | |
188 WriteRef(Object::null()); | |
189 return; | |
190 } | |
191 if (object->IsSendPort()) { | |
192 // TODO(rmacnak): Do a better job of resetting fields in precompilation | |
193 // and assert this is unreachable. | |
194 WriteRef(Object::null()); | |
195 return; | |
196 } | |
197 FATAL("Missing ref"); | |
198 } | |
199 Write<intptr_t>((id << 1) | 1); | |
200 } | |
201 | |
202 void WriteTokenPosition(TokenPosition pos) { | |
203 Write<int32_t>(pos.SnapshotEncode()); | |
204 } | |
205 | |
206 void WriteCid(intptr_t cid) { | |
207 Write<int32_t>(cid); | |
208 } | |
209 | |
210 int32_t GetTextOffset(RawInstructions* instr, RawCode* code) { | |
211 return instructions_writer_->GetOffsetFor(instr, code); | |
212 } | |
213 | |
214 int32_t GetRODataOffset(RawObject* object) { | |
215 return instructions_writer_->GetObjectOffsetFor(object); | |
216 } | |
217 | |
218 Snapshot::Kind kind() const { return kind_; } | |
219 | |
220 private: | |
221 Heap* heap_; | |
222 Zone* zone_; | |
223 Snapshot::Kind kind_; | |
224 WriteStream stream_; | |
225 InstructionsWriter* instructions_writer_; | |
226 SerializationCluster** clusters_by_cid_; | |
227 GrowableArray<RawObject*> stack_; | |
228 intptr_t num_cids_; | |
229 intptr_t num_base_objects_; | |
230 intptr_t num_written_objects_; | |
231 intptr_t next_ref_index_; | |
232 | |
233 DISALLOW_IMPLICIT_CONSTRUCTORS(Serializer); | |
234 }; | |
235 | |
236 | |
237 class Deserializer : public StackResource { | |
238 public: | |
239 Deserializer(Thread* thread, | |
240 Snapshot::Kind kind, | |
241 const uint8_t* buffer, | |
242 intptr_t size, | |
243 const uint8_t* instructions_buffer, | |
244 const uint8_t* data_buffer); | |
245 ~Deserializer(); | |
246 | |
247 void ReadFullSnapshot(ObjectStore* object_store); | |
248 void ReadVMSnapshot(); | |
249 | |
250 void AddVMIsolateBaseObjects(); | |
251 | |
252 static void InitializeHeader(RawObject* raw, | |
253 intptr_t cid, | |
254 intptr_t size, | |
255 bool is_vm_isolate, | |
256 bool is_canonical = false); | |
257 | |
258 // Reads raw data (for basic types). | |
259 // sizeof(T) must be in {1,2,4,8}. | |
260 template <typename T> | |
261 T Read() { | |
262 return ReadStream::Raw<sizeof(T), T>::Read(&stream_); | |
263 } | |
264 | |
265 void ReadBytes(uint8_t* addr, intptr_t len) { | |
266 stream_.ReadBytes(addr, len); | |
267 } | |
268 | |
269 const uint8_t* CurrentBufferAddress() const { | |
270 return stream_.AddressOfCurrentPosition(); | |
271 } | |
272 | |
273 void Advance(intptr_t value) { | |
274 stream_.Advance(value); | |
275 } | |
276 | |
277 intptr_t PendingBytes() const { | |
278 return stream_.PendingBytes(); | |
279 } | |
280 | |
281 void AddBaseObject(RawObject* base_object) { | |
282 AssignRef(base_object); | |
283 } | |
284 | |
285 void AssignRef(RawObject* object) { | |
286 ASSERT(next_ref_index_ <= num_objects_); | |
287 refs_->ptr()->data()[next_ref_index_] = object; | |
288 next_ref_index_++; | |
289 } | |
290 | |
291 RawObject* Ref(intptr_t index) const { | |
292 ASSERT(index > 0); | |
293 ASSERT(index <= num_objects_); | |
294 return refs_->ptr()->data()[index]; | |
295 } | |
296 | |
297 RawObject* ReadRef() { | |
298 intptr_t index = Read<intptr_t>(); | |
299 if ((index & 1) == 0) { | |
300 return reinterpret_cast<RawSmi*>(index); | |
301 } | |
302 return Ref(index >> 1); | |
303 } | |
304 | |
305 TokenPosition ReadTokenPosition() { | |
306 return TokenPosition::SnapshotDecode(Read<int32_t>()); | |
307 } | |
308 | |
309 intptr_t ReadCid() { | |
310 return Read<int32_t>(); | |
311 } | |
312 | |
313 uword GetInstructionsAt(int32_t offset) { | |
314 return instructions_reader_->GetInstructionsAt(offset); | |
315 } | |
316 | |
317 RawObject* GetObjectAt(int32_t offset) { | |
318 return instructions_reader_->GetObjectAt(offset); | |
319 } | |
320 | |
321 RawApiError* VerifyVersionAndFeatures(); | |
322 | |
323 void Prepare(); | |
324 void Deserialize(); | |
325 | |
326 DeserializationCluster* ReadCluster(); | |
327 | |
328 intptr_t next_index() const { return next_ref_index_; } | |
329 Heap* heap() const { return heap_; } | |
330 Snapshot::Kind kind() const { return kind_; } | |
331 | |
332 private: | |
333 Heap* heap_; | |
334 Zone* zone_; | |
335 Snapshot::Kind kind_; | |
336 ReadStream stream_; | |
337 InstructionsReader* instructions_reader_; | |
338 intptr_t num_objects_; | |
339 intptr_t num_clusters_; | |
340 RawArray* refs_; | |
341 intptr_t next_ref_index_; | |
342 DeserializationCluster** clusters_; | |
343 }; | |
344 | |
345 | |
346 class FullSnapshotWriter { | |
347 public: | |
348 static const intptr_t kInitialSize = 64 * KB; | |
349 FullSnapshotWriter(Snapshot::Kind kind, | |
350 uint8_t** vm_isolate_snapshot_buffer, | |
351 uint8_t** isolate_snapshot_buffer, | |
352 ReAlloc alloc, | |
353 InstructionsWriter* instructions_writer); | |
354 ~FullSnapshotWriter(); | |
355 | |
356 uint8_t** vm_isolate_snapshot_buffer() { | |
357 return vm_isolate_snapshot_buffer_; | |
358 } | |
359 | |
360 uint8_t** isolate_snapshot_buffer() { | |
361 return isolate_snapshot_buffer_; | |
362 } | |
363 | |
364 Thread* thread() const { return thread_; } | |
365 Zone* zone() const { return thread_->zone(); } | |
366 Isolate* isolate() const { return thread_->isolate(); } | |
367 Heap* heap() const { return isolate()->heap(); } | |
368 | |
369 // Writes a full snapshot of the Isolate. | |
370 void WriteFullSnapshot(); | |
371 | |
372 intptr_t VmIsolateSnapshotSize() const { | |
373 return vm_isolate_snapshot_size_; | |
374 } | |
375 intptr_t IsolateSnapshotSize() const { | |
376 return isolate_snapshot_size_; | |
377 } | |
378 | |
379 private: | |
380 // Writes a snapshot of the VM Isolate. | |
381 intptr_t WriteVmIsolateSnapshot(); | |
382 | |
383 // Writes a full snapshot of a regular Dart Isolate. | |
384 void WriteIsolateFullSnapshot(intptr_t num_base_objects); | |
385 | |
386 Thread* thread_; | |
387 Snapshot::Kind kind_; | |
388 uint8_t** vm_isolate_snapshot_buffer_; | |
389 uint8_t** isolate_snapshot_buffer_; | |
390 ReAlloc alloc_; | |
391 intptr_t vm_isolate_snapshot_size_; | |
392 intptr_t isolate_snapshot_size_; | |
393 ForwardList* forward_list_; | |
394 InstructionsWriter* instructions_writer_; | |
395 Array& scripts_; | |
396 Array& saved_symbol_table_; | |
397 Array& new_vm_symbol_table_; | |
398 | |
399 DISALLOW_COPY_AND_ASSIGN(FullSnapshotWriter); | |
400 }; | |
401 | |
402 | |
403 class VmIsolateSnapshotReader { | |
404 public: | |
405 VmIsolateSnapshotReader(Snapshot::Kind kind, | |
406 const uint8_t* buffer, | |
407 intptr_t size, | |
408 const uint8_t* instructions_buffer, | |
409 const uint8_t* data_buffer, | |
410 Thread* thread) : | |
411 kind_(kind), | |
412 thread_(thread), | |
413 buffer_(buffer), | |
414 size_(size), | |
415 instructions_buffer_(instructions_buffer), | |
416 data_buffer_(data_buffer) { | |
417 thread->isolate()->set_compilation_allowed(kind != Snapshot::kAppNoJIT); | |
418 } | |
419 | |
420 ~VmIsolateSnapshotReader() { } | |
421 | |
422 RawApiError* ReadVmIsolateSnapshot(); | |
423 | |
424 private: | |
425 Snapshot::Kind kind_; | |
426 Thread* thread_; | |
427 const uint8_t* buffer_; | |
428 intptr_t size_; | |
429 const uint8_t* instructions_buffer_; | |
430 const uint8_t* data_buffer_; | |
431 | |
432 DISALLOW_COPY_AND_ASSIGN(VmIsolateSnapshotReader); | |
433 }; | |
434 | |
435 | |
436 class IsolateSnapshotReader { | |
437 public: | |
438 IsolateSnapshotReader(Snapshot::Kind kind, | |
439 const uint8_t* buffer, | |
440 intptr_t size, | |
441 const uint8_t* instructions_buffer, | |
442 const uint8_t* data_buffer, | |
443 Thread* thread) : | |
444 kind_(kind), | |
445 thread_(thread), | |
446 buffer_(buffer), | |
447 size_(size), | |
448 instructions_buffer_(instructions_buffer), | |
449 data_buffer_(data_buffer) { | |
450 thread->isolate()->set_compilation_allowed(kind != Snapshot::kAppNoJIT); | |
451 } | |
452 | |
453 ~IsolateSnapshotReader() {} | |
454 | |
455 RawApiError* ReadFullSnapshot(); | |
456 | |
457 private: | |
458 Snapshot::Kind kind_; | |
459 Thread* thread_; | |
460 const uint8_t* buffer_; | |
461 intptr_t size_; | |
462 const uint8_t* instructions_buffer_; | |
463 const uint8_t* data_buffer_; | |
464 | |
465 DISALLOW_COPY_AND_ASSIGN(IsolateSnapshotReader); | |
466 }; | |
467 | |
468 } // namespace dart | |
469 | |
470 #endif // VM_CLUSTERED_SNAPSHOT_H_ | |
OLD | NEW |