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

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