Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(58)

Side by Side Diff: runtime/vm/clustered_snapshot.h

Issue 2032153003: Use clustered serialization for full snapshots. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: friend macro, sync Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/class_table.cc ('k') | runtime/vm/clustered_snapshot.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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"
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"
21
22 namespace dart {
23
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
32 // loop. The snapshot has two major sections: the first describes how to
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
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) { }
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));
siva 2016/06/30 00:06:07 How does this work when the snapshot is generated
rmacnak 2016/06/30 01:39:21 It doesn't. Added word size to the features descri
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);
siva 2016/06/30 00:06:07 See question about reading a snapshot generated on
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_
OLDNEW
« no previous file with comments | « runtime/vm/class_table.cc ('k') | runtime/vm/clustered_snapshot.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698