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

Side by Side Diff: vm/snapshot.cc

Issue 10535066: 1. Remove recursion during snapshot writing and reading (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/runtime/
Patch Set: Created 8 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 | Annotate | Revision Log
« no previous file with comments | « vm/snapshot.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 "vm/snapshot.h" 5 #include "vm/snapshot.h"
6 6
7 #include "platform/assert.h" 7 #include "platform/assert.h"
8 #include "vm/bigint_operations.h" 8 #include "vm/bigint_operations.h"
9 #include "vm/bootstrap.h" 9 #include "vm/bootstrap.h"
10 #include "vm/exceptions.h" 10 #include "vm/exceptions.h"
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 library_(Library::Handle()), 82 library_(Library::Handle()),
83 type_(AbstractType::Handle()), 83 type_(AbstractType::Handle()),
84 type_arguments_(AbstractTypeArguments::Handle()), 84 type_arguments_(AbstractTypeArguments::Handle()),
85 backward_references_((snapshot->kind() == Snapshot::kFull) ? 85 backward_references_((snapshot->kind() == Snapshot::kFull) ?
86 kNumInitialReferencesInFullSnapshot : 86 kNumInitialReferencesInFullSnapshot :
87 kNumInitialReferences) { 87 kNumInitialReferences) {
88 } 88 }
89 89
90 90
91 RawObject* SnapshotReader::ReadObject() { 91 RawObject* SnapshotReader::ReadObject() {
92 int64_t value = Read<int64_t>(); 92 Object& obj = Object::Handle(ReadObjectImpl());
93 if ((value & kSmiTagMask) == 0) { 93 for (intptr_t i = 0; i < backward_references_.length(); i++) {
94 return Integer::New((value >> kSmiTagShift)); 94 if (!backward_references_[i]->is_deserialized()) {
95 ReadObjectImpl();
96 backward_references_[i]->set_state(kIsDeserialized);
97 }
95 } 98 }
96 ASSERT((value <= kIntptrMax) && (value >= kIntptrMin)); 99 return obj.raw();
97 return ReadObjectImpl(value);
98 } 100 }
99 101
100 102
101 RawClass* SnapshotReader::ReadClassId(intptr_t object_id) { 103 RawClass* SnapshotReader::ReadClassId(intptr_t object_id) {
102 ASSERT(kind_ != Snapshot::kFull); 104 ASSERT(kind_ != Snapshot::kFull);
103 // Read the class header information and lookup the class. 105 // Read the class header information and lookup the class.
104 intptr_t class_header = ReadIntptrValue(); 106 intptr_t class_header = ReadIntptrValue();
105 ASSERT((class_header & kSmiTagMask) != 0); 107 ASSERT((class_header & kSmiTagMask) != 0);
106 Class& cls = Class::ZoneHandle(isolate(), Class::null()); 108 Class& cls = Class::ZoneHandle(isolate(), Class::null());
107 cls ^= LookupInternalClass(class_header); 109 cls ^= LookupInternalClass(class_header);
108 AddBackwardReference(object_id, &cls); 110 AddBackRef(object_id, &cls, kIsDeserialized);
109 if (cls.IsNull()) { 111 if (cls.IsNull()) {
110 // Read the library/class information and lookup the class. 112 // Read the library/class information and lookup the class.
111 str_ ^= ReadObjectImpl(class_header); 113 str_ ^= ReadObjectImpl(class_header);
112 library_ = Library::LookupLibrary(str_); 114 library_ = Library::LookupLibrary(str_);
113 ASSERT(!library_.IsNull()); 115 ASSERT(!library_.IsNull());
114 str_ ^= ReadObject(); 116 str_ ^= ReadObjectImpl();
115 cls ^= library_.LookupClass(str_); 117 cls ^= library_.LookupClass(str_);
116 } 118 }
117 ASSERT(!cls.IsNull()); 119 ASSERT(!cls.IsNull());
118 return cls.raw(); 120 return cls.raw();
119 } 121 }
120 122
121 123
122 void SnapshotReader::AddBackwardReference(intptr_t id, Object* obj) { 124 RawObject* SnapshotReader::ReadObjectImpl() {
123 ASSERT((id - kMaxPredefinedObjectIds) == backward_references_.length()); 125 int64_t value = Read<int64_t>();
124 backward_references_.Add(obj); 126 if ((value & kSmiTagMask) == 0) {
127 return Integer::New((value >> kSmiTagShift));
128 }
129 return ReadObjectImpl(value);
130 }
131
132
133 RawObject* SnapshotReader::ReadObjectImpl(intptr_t value) {
134 ASSERT((value <= kIntptrMax) && (value >= kIntptrMin));
135 SerializedHeaderType header_type = SerializedHeaderTag::decode(value);
136 intptr_t header_value = SerializedHeaderData::decode(value);
137
138 if (header_type == kObjectId) {
139 return ReadIndexedObject(header_value);
140 }
141 ASSERT(header_type == kInlined);
142 return ReadInlinedObject(header_value);
143 }
144
145
146 RawObject* SnapshotReader::ReadObjectRef() {
147 int64_t value = Read<int64_t>();
148 if ((value & kSmiTagMask) == 0) {
149 return Integer::New((value >> kSmiTagShift));
150 }
151 ASSERT((value <= kIntptrMax) && (value >= kIntptrMin));
152 SerializedHeaderType header_type = SerializedHeaderTag::decode(value);
153 intptr_t header_value = SerializedHeaderData::decode(value);
154
155 if (header_type == kObjectId) {
156 return ReadIndexedObject(header_value);
157 }
158 ASSERT(header_type == kInlined);
159 intptr_t object_id = header_value;
160 ASSERT(GetBackRef(object_id) == NULL);
161
162 // Read the class header information and lookup the class.
163 intptr_t class_header = ReadIntptrValue();
164
165 // Since we are only reading an object reference, If it is an instance kind
166 // then we only need to figure out the class of the object and allocate an
167 // instance of it. The individual fields will be read later.
168 if (SerializedHeaderData::decode(class_header) == kInstanceId) {
169 Instance& result = Instance::ZoneHandle(isolate(), Instance::null());
170 AddBackRef(object_id, &result, kIsNotDeserialized);
171
172 cls_ ^= ReadObjectImpl(); // Read class information.
173 ASSERT(!cls_.IsNull());
174 intptr_t instance_size = cls_.instance_size();
175 ASSERT(instance_size > 0);
176 if (kind_ == Snapshot::kFull) {
177 result ^= AllocateUninitialized(cls_, instance_size);
178 } else {
179 result ^= Object::Allocate(cls_, instance_size, Heap::kNew);
180 }
181 return result.raw();
182 } else {
183 ASSERT((class_header & kSmiTagMask) != 0);
184 cls_ ^= LookupInternalClass(class_header);
185 ASSERT(!cls_.IsNull());
186 }
187
188 // Similarly Array and ImmutableArray objects are also similarly only
189 // allocated here, the individual array elements are read later.
190 ObjectKind obj_kind = cls_.instance_kind();
191 if (obj_kind == Array::kInstanceKind) {
192 // Read the length and allocate an object based on the len.
193 intptr_t len = ReadSmiValue();
194 Array& array = Array::ZoneHandle(
195 isolate(),
196 (kind_ == Snapshot::kFull) ? NewArray(len) : Array::New(len));
197 AddBackRef(object_id, &array, kIsNotDeserialized);
198
199 return array.raw();
200 }
201 if (obj_kind == ImmutableArray::kInstanceKind) {
202 // Read the length and allocate an object based on the len.
203 intptr_t len = ReadSmiValue();
204 ImmutableArray& array = ImmutableArray::ZoneHandle(
205 isolate(),
206 (kind_ == Snapshot::kFull) ?
207 NewImmutableArray(len) : ImmutableArray::New(len));
208 AddBackRef(object_id, &array, kIsNotDeserialized);
209
210 return array.raw();
211 }
212
213 // For all other internal VM classes we read the object inline.
214 intptr_t tags = ReadIntptrValue();
215 switch (obj_kind) {
216 #define SNAPSHOT_READ(clazz) \
217 case clazz::kInstanceKind: { \
218 obj_ = clazz::ReadFrom(this, object_id, tags, kind_); \
219 break; \
220 }
221 CLASS_LIST_NO_OBJECT(SNAPSHOT_READ)
222 #undef SNAPSHOT_READ
223 default: UNREACHABLE(); break;
224 }
225 if (kind_ == Snapshot::kFull) {
226 obj_.SetCreatedFromSnapshot();
227 }
228 return obj_.raw();
229 }
230
231
232 void SnapshotReader::AddBackRef(intptr_t id,
233 Object* obj,
234 DeserializeState state) {
235 intptr_t index = (id - kMaxPredefinedObjectIds);
236 ASSERT(index == backward_references_.length());
237 BackRefNode* node = new BackRefNode(obj, state);
238 ASSERT(node != NULL);
239 backward_references_.Add(node);
240 }
241
242
243 Object* SnapshotReader::GetBackRef(intptr_t id) {
244 ASSERT(id >= kMaxPredefinedObjectIds);
245 intptr_t index = (id - kMaxPredefinedObjectIds);
246 if (index < backward_references_.length()) {
247 return backward_references_[index]->reference();
248 }
249 return NULL;
125 } 250 }
126 251
127 252
128 void SnapshotReader::ReadFullSnapshot() { 253 void SnapshotReader::ReadFullSnapshot() {
129 ASSERT(kind_ == Snapshot::kFull); 254 ASSERT(kind_ == Snapshot::kFull);
130 Isolate* isolate = Isolate::Current(); 255 Isolate* isolate = Isolate::Current();
131 ASSERT(isolate != NULL); 256 ASSERT(isolate != NULL);
132 ObjectStore* object_store = isolate->object_store(); 257 ObjectStore* object_store = isolate->object_store();
133 ASSERT(object_store != NULL); 258 ASSERT(object_store != NULL);
134 NoGCScope no_gc; 259 NoGCScope no_gc;
135 260
136 // TODO(asiva): Add a check here to ensure we have the right heap 261 // TODO(asiva): Add a check here to ensure we have the right heap
137 // size for the full snapshot being read. 262 // size for the full snapshot being read.
138 263
139 // Read in all the objects stored in the object store. 264 // Read in all the objects stored in the object store.
140 intptr_t num_flds = (object_store->to() - object_store->from()); 265 intptr_t num_flds = (object_store->to() - object_store->from());
141 for (intptr_t i = 0; i <= num_flds; i++) { 266 for (intptr_t i = 0; i <= num_flds; i++) {
142 *(object_store->from() + i) = ReadObject(); 267 *(object_store->from() + i) = ReadObjectImpl();
268 }
269 for (intptr_t i = 0; i < backward_references_.length(); i++) {
270 if (!backward_references_[i]->is_deserialized()) {
271 ReadObjectImpl();
272 backward_references_[i]->set_state(kIsDeserialized);
273 }
143 } 274 }
144 275
145 // Setup native resolver for bootstrap impl. 276 // Setup native resolver for bootstrap impl.
146 Bootstrap::SetupNativeResolver(); 277 Bootstrap::SetupNativeResolver();
147 } 278 }
148 279
149 280
150 #define ALLOC_NEW_OBJECT_WITH_LEN(type, class_obj, length) \ 281 #define ALLOC_NEW_OBJECT_WITH_LEN(type, class_obj, length) \
151 ASSERT(kind_ == Snapshot::kFull); \ 282 ASSERT(kind_ == Snapshot::kFull); \
152 ASSERT(isolate()->no_gc_scope_depth() != 0); \ 283 ASSERT(isolate()->no_gc_scope_depth() != 0); \
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 uword tags = 0; 502 uword tags = 0;
372 intptr_t index = cls.id(); 503 intptr_t index = cls.id();
373 ASSERT(index != kIllegalObjectKind); 504 ASSERT(index != kIllegalObjectKind);
374 tags = RawObject::ClassIdTag::update(index, tags); 505 tags = RawObject::ClassIdTag::update(index, tags);
375 tags = RawObject::SizeTag::update(size, tags); 506 tags = RawObject::SizeTag::update(size, tags);
376 raw_obj->ptr()->tags_ = tags; 507 raw_obj->ptr()->tags_ = tags;
377 return raw_obj; 508 return raw_obj;
378 } 509 }
379 510
380 511
381 RawObject* SnapshotReader::ReadObjectImpl(intptr_t header) {
382 SerializedHeaderType header_type = SerializedHeaderTag::decode(header);
383 intptr_t header_value = SerializedHeaderData::decode(header);
384
385 if (header_type == kObjectId) {
386 return ReadIndexedObject(header_value);
387 }
388 ASSERT(header_type == kInlined);
389 return ReadInlinedObject(header_value);
390 }
391
392
393 RawObject* SnapshotReader::ReadIndexedObject(intptr_t object_id) { 512 RawObject* SnapshotReader::ReadIndexedObject(intptr_t object_id) {
394 if (object_id == Object::kNullObject) { 513 if (object_id == Object::kNullObject) {
395 // This is a singleton null object, return it. 514 // This is a singleton null object, return it.
396 return Object::null(); 515 return Object::null();
397 } 516 }
398 if (object_id == Object::kSentinelObject) { 517 if (object_id == Object::kSentinelObject) {
399 return Object::sentinel(); 518 return Object::sentinel();
400 } 519 }
401 if (IsSingletonClassId(object_id)) { 520 if (IsSingletonClassId(object_id)) {
402 return Object::GetSingletonClass(object_id); // return singleton object. 521 return Object::GetSingletonClass(object_id); // return singleton object.
403 } else if (IsObjectStoreClassId(object_id)) { 522 } else if (IsObjectStoreClassId(object_id)) {
404 return object_store()->GetClass(object_id); 523 return object_store()->GetClass(object_id);
405 } else if (object_id == ObjectStore::kTrueValue) { 524 } else if (object_id == ObjectStore::kTrueValue) {
406 return object_store()->true_value(); 525 return object_store()->true_value();
407 } else if (object_id == ObjectStore::kFalseValue) { 526 } else if (object_id == ObjectStore::kFalseValue) {
408 return object_store()->false_value(); 527 return object_store()->false_value();
409 } else if (kind_ != Snapshot::kFull) { 528 } else if (kind_ != Snapshot::kFull) {
410 if (IsObjectStoreTypeId(object_id)) { 529 if (IsObjectStoreTypeId(object_id)) {
411 return object_store()->GetType(object_id); // return type object. 530 return object_store()->GetType(object_id); // return type object.
412 } 531 }
413 } 532 }
414 533
415 ASSERT(object_id >= kMaxPredefinedObjectIds); 534 Object* object = GetBackRef(object_id);
416 intptr_t index = object_id - kMaxPredefinedObjectIds; 535 return object->raw();
417 ASSERT(index < backward_references_.length());
418 return backward_references_[index]->raw();
419 } 536 }
420 537
421 538
422 RawObject* SnapshotReader::ReadInlinedObject(intptr_t object_id) { 539 RawObject* SnapshotReader::ReadInlinedObject(intptr_t object_id) {
423 // Read the class header information and lookup the class. 540 // Read the class header information and lookup the class.
424 intptr_t class_header = ReadIntptrValue(); 541 intptr_t class_header = ReadIntptrValue();
425 intptr_t tags = ReadIntptrValue(); 542 intptr_t tags = ReadIntptrValue();
426 if (SerializedHeaderData::decode(class_header) == kInstanceId) { 543 if (SerializedHeaderData::decode(class_header) == kInstanceId) {
427 // Object is regular dart instance. 544 // Object is regular dart instance.
428 Instance& result = Instance::ZoneHandle(isolate(), Instance::null()); 545 Instance* result = reinterpret_cast<Instance*>(GetBackRef(object_id));
429 AddBackwardReference(object_id, &result); 546 intptr_t instance_size = 0;
430 547 if (result == NULL) {
431 cls_ ^= ReadObject(); 548 result = &(Instance::ZoneHandle(isolate(), Instance::null()));
432 ASSERT(!cls_.IsNull()); 549 AddBackRef(object_id, result, kIsDeserialized);
433 intptr_t instance_size = cls_.instance_size(); 550 cls_ ^= ReadObjectImpl();
434 ASSERT(instance_size > 0); 551 ASSERT(!cls_.IsNull());
435 // Allocate the instance and read in all the fields for the object. 552 instance_size = cls_.instance_size();
436 if (kind_ == Snapshot::kFull) { 553 ASSERT(instance_size > 0);
437 result ^= AllocateUninitialized(cls_, instance_size); 554 // Allocate the instance and read in all the fields for the object.
555 if (kind_ == Snapshot::kFull) {
556 *result ^= AllocateUninitialized(cls_, instance_size);
557 } else {
558 *result ^= Object::Allocate(cls_, instance_size, Heap::kNew);
559 }
438 } else { 560 } else {
439 result ^= Object::Allocate(cls_, instance_size, Heap::kNew); 561 cls_ ^= ReadObjectImpl();
562 ASSERT(!cls_.IsNull());
563 instance_size = cls_.instance_size();
440 } 564 }
441 intptr_t offset = Object::InstanceSize(); 565 intptr_t offset = Object::InstanceSize();
442 while (offset < instance_size) { 566 while (offset < instance_size) {
443 obj_ = ReadObject(); 567 obj_ = ReadObjectRef();
444 result.SetFieldAtOffset(offset, obj_); 568 result->SetFieldAtOffset(offset, obj_);
445 offset += kWordSize; 569 offset += kWordSize;
446 } 570 }
447 if (kind_ == Snapshot::kFull) { 571 if (kind_ == Snapshot::kFull) {
448 result.SetCreatedFromSnapshot(); 572 result->SetCreatedFromSnapshot();
449 } else if (result.IsCanonical()) { 573 } else if (result->IsCanonical()) {
450 result = result.Canonicalize(); 574 *result = result->Canonicalize();
451 } 575 }
452 return result.raw(); 576 return result->raw();
453 } else { 577 } else {
454 ASSERT((class_header & kSmiTagMask) != 0); 578 ASSERT((class_header & kSmiTagMask) != 0);
455 cls_ ^= LookupInternalClass(class_header); 579 cls_ ^= LookupInternalClass(class_header);
456 ASSERT(!cls_.IsNull()); 580 ASSERT(!cls_.IsNull());
457 } 581 }
458 switch (cls_.instance_kind()) { 582 switch (cls_.instance_kind()) {
459 #define SNAPSHOT_READ(clazz) \ 583 #define SNAPSHOT_READ(clazz) \
460 case clazz::kInstanceKind: { \ 584 case clazz::kInstanceKind: { \
461 obj_ = clazz::ReadFrom(this, object_id, tags, kind_); \ 585 obj_ = clazz::ReadFrom(this, object_id, tags, kind_); \
462 break; \ 586 break; \
463 } 587 }
464 CLASS_LIST_NO_OBJECT(SNAPSHOT_READ) 588 CLASS_LIST_NO_OBJECT(SNAPSHOT_READ)
465 #undef SNAPSHOT_READ 589 #undef SNAPSHOT_READ
466 default: UNREACHABLE(); break; 590 default: UNREACHABLE(); break;
467 } 591 }
468 if (kind_ == Snapshot::kFull) { 592 if (kind_ == Snapshot::kFull) {
469 obj_.SetCreatedFromSnapshot(); 593 obj_.SetCreatedFromSnapshot();
470 } 594 }
471 return obj_.raw(); 595 return obj_.raw();
472 } 596 }
473 597
474 598
599 void SnapshotReader::ArrayReadFrom(const Array& result,
600 intptr_t len,
601 intptr_t tags) {
602 // Set the object tags.
603 result.set_tags(tags);
604
605 // Setup the object fields.
606 *TypeArgumentsHandle() ^= ReadObjectImpl();
607 result.SetTypeArguments(*TypeArgumentsHandle());
608
609 for (intptr_t i = 0; i < len; i++) {
610 *ObjectHandle() = ReadObjectRef();
611 result.SetAt(i, *ObjectHandle());
612 }
613 }
614
615
475 void SnapshotWriter::WriteObject(RawObject* rawobj) { 616 void SnapshotWriter::WriteObject(RawObject* rawobj) {
476 // First check if object can be written as a simple predefined type. 617 WriteObjectImpl(rawobj);
477 if (CheckAndWritePredefinedObject(rawobj)) { 618 WriteForwardedObjects();
478 return;
479 }
480 // Now write the object out inline in the stream as follows:
481 // - Object is seen for the first time (inlined as follows):
482 // (object size in multiples of kObjectAlignment | 0x1)
483 // serialized fields of the object
484 // ......
485 WriteInlinedObject(rawobj);
486 } 619 }
487 620
488 621
489 void SnapshotWriter::UnmarkAll() { 622 void SnapshotWriter::WriteObjectRef(RawObject* raw) {
623 // First check if object can be written as a simple predefined type.
624 if (CheckAndWritePredefinedObject(raw)) {
625 return;
626 }
627 // Check if object has already been serialized, in that
628 // case just write the object id out.
629 uword tags = raw->ptr()->tags_;
630 if (SerializedHeaderTag::decode(tags) == kObjectId) {
631 intptr_t id = SerializedHeaderData::decode(tags);
632 WriteIndexedObject(id);
633 return;
634 }
635
490 NoGCScope no_gc; 636 NoGCScope no_gc;
491 for (intptr_t i = 0; i < forward_list_.length(); i++) { 637 RawClass* cls = class_table_->At(RawObject::ClassIdTag::decode(tags));
492 RawObject* raw = forward_list_[i]->raw(); 638
493 raw->ptr()->tags_ = forward_list_[i]->tags(); // Restore original tags. 639 ObjectKind obj_kind = cls->ptr()->instance_kind_;
640 if (obj_kind == Instance::kInstanceKind) {
641 // Object is being referenced, add it to the forward ref list and mark
642 // it so that future references to this object in the snapshot will use
643 // this object id. Mark it as not having been serialized yet so that we
644 // will serialize the object when we go through the forward list.
645 intptr_t object_id = MarkObject(raw, kIsNotSerialized);
646
647 // Write out the serialization header value for this object.
648 WriteSerializationMarker(kInlined, object_id);
649
650 // Indicate this is an instance object.
651 WriteIntptrValue(SerializedHeaderData::encode(kInstanceId));
652
653 // Write out the class information for this object.
654 WriteObjectImpl(cls);
655
656 return;
494 } 657 }
658 if (obj_kind == Array::kInstanceKind) {
659 // Object is being referenced, add it to the forward ref list and mark
660 // it so that future references to this object in the snapshot will use
661 // this object id. Mark it as not having been serialized yet so that we
662 // will serialize the object when we go through the forward list.
663 intptr_t object_id = MarkObject(raw, kIsNotSerialized);
664
665 RawArray* rawarray = reinterpret_cast<RawArray*>(raw);
666
667 // Write out the serialization header value for this object.
668 WriteSerializationMarker(kInlined, object_id);
669
670 // Write out the class information.
671 WriteIndexedObject(ObjectStore::kArrayClass);
672
673 // Write out the length field.
674 Write<RawObject*>(rawarray->ptr()->length_);
675
676 return;
677 }
678 if (obj_kind == ImmutableArray::kInstanceKind) {
679 // Object is being referenced, add it to the forward ref list and mark
680 // it so that future references to this object in the snapshot will use
681 // this object id. Mark it as not having been serialized yet so that we
682 // will serialize the object when we go through the forward list.
683 intptr_t object_id = MarkObject(raw, kIsNotSerialized);
684
685 RawArray* rawarray = reinterpret_cast<RawArray*>(raw);
686
687 // Write out the serialization header value for this object.
688 WriteSerializationMarker(kInlined, object_id);
689
690 // Write out the class information.
691 WriteIndexedObject(ObjectStore::kImmutableArrayClass);
692
693 // Write out the length field.
694 Write<RawObject*>(rawarray->ptr()->length_);
695
696 return;
697 }
698 // Object is being referenced, add it to the forward ref list and mark
699 // it so that future references to this object in the snapshot will use
700 // this object id. Mark it as not having been serialized yet so that we
701 // will serialize the object when we go through the forward list.
702 intptr_t object_id = MarkObject(raw, kIsSerialized);
703 switch (obj_kind) {
704 #define SNAPSHOT_WRITE(clazz) \
705 case clazz::kInstanceKind: { \
706 Raw##clazz* raw_obj = reinterpret_cast<Raw##clazz*>(raw); \
707 raw_obj->WriteTo(this, object_id, kind_); \
708 return; \
709 } \
710
711 CLASS_LIST_NO_OBJECT(SNAPSHOT_WRITE)
712 #undef SNAPSHOT_WRITE
713 default: break;
714 }
715 UNREACHABLE();
495 } 716 }
496 717
497 718
498 void SnapshotWriter::WriteFullSnapshot() { 719 void SnapshotWriter::WriteFullSnapshot() {
499 ASSERT(kind_ == Snapshot::kFull); 720 ASSERT(kind_ == Snapshot::kFull);
500 Isolate* isolate = Isolate::Current(); 721 Isolate* isolate = Isolate::Current();
501 ASSERT(isolate != NULL); 722 ASSERT(isolate != NULL);
502 ObjectStore* object_store = isolate->object_store(); 723 ObjectStore* object_store = isolate->object_store();
503 ASSERT(object_store != NULL); 724 ASSERT(object_store != NULL);
504 725
505 // Write out all the objects in the object store of the isolate which 726 // Write out all the objects in the object store of the isolate which
506 // is the root set for all dart allocated objects at this point. 727 // is the root set for all dart allocated objects at this point.
507 SnapshotWriterVisitor visitor(this); 728 SnapshotWriterVisitor visitor(this, false);
508 object_store->VisitObjectPointers(&visitor); 729 object_store->VisitObjectPointers(&visitor);
509 730
731 // Write out all forwarded objects.
732 WriteForwardedObjects();
733
510 // Finalize the snapshot buffer. 734 // Finalize the snapshot buffer.
511 FinalizeBuffer(); 735 FinalizeBuffer();
512 } 736 }
513 737
514 738
515 uword SnapshotWriter::GetObjectTags(RawObject* raw) { 739 uword SnapshotWriter::GetObjectTags(RawObject* raw) {
516 uword tags = raw->ptr()->tags_; 740 uword tags = raw->ptr()->tags_;
517 if (SerializedHeaderTag::decode(tags) == kObjectId) { 741 if (SerializedHeaderTag::decode(tags) == kObjectId) {
518 intptr_t id = SerializedHeaderData::decode(tags); 742 intptr_t id = SerializedHeaderData::decode(tags);
519 return forward_list_[id - kMaxPredefinedObjectIds]->tags(); 743 return forward_list_[id - kMaxPredefinedObjectIds]->tags();
520 } else { 744 } else {
521 return tags; 745 return tags;
522 } 746 }
523 } 747 }
524 748
525 749
526 intptr_t SnapshotWriter::MarkObject(RawObject* raw) { 750 intptr_t SnapshotWriter::MarkObject(RawObject* raw, SerializeState state) {
527 NoGCScope no_gc; 751 NoGCScope no_gc;
528 intptr_t object_id = forward_list_.length() + kMaxPredefinedObjectIds; 752 intptr_t object_id = forward_list_.length() + kMaxPredefinedObjectIds;
529 ASSERT(object_id <= kMaxObjectId); 753 ASSERT(object_id <= kMaxObjectId);
530 uword value = 0; 754 uword value = 0;
531 value = SerializedHeaderTag::update(kObjectId, value); 755 value = SerializedHeaderTag::update(kObjectId, value);
532 value = SerializedHeaderData::update(object_id, value); 756 value = SerializedHeaderData::update(object_id, value);
533 uword tags = raw->ptr()->tags_; 757 uword tags = raw->ptr()->tags_;
534 raw->ptr()->tags_ = value; 758 raw->ptr()->tags_ = value;
535 ForwardObjectNode* node = new ForwardObjectNode(raw, tags); 759 ForwardObjectNode* node = new ForwardObjectNode(raw, tags, state);
536 ASSERT(node != NULL); 760 ASSERT(node != NULL);
537 forward_list_.Add(node); 761 forward_list_.Add(node);
538 return object_id; 762 return object_id;
539 } 763 }
540 764
541 765
766 void SnapshotWriter::UnmarkAll() {
767 NoGCScope no_gc;
768 for (intptr_t i = 0; i < forward_list_.length(); i++) {
769 RawObject* raw = forward_list_[i]->raw();
770 raw->ptr()->tags_ = forward_list_[i]->tags(); // Restore original tags.
771 }
772 }
773
774
542 bool SnapshotWriter::CheckAndWritePredefinedObject(RawObject* rawobj) { 775 bool SnapshotWriter::CheckAndWritePredefinedObject(RawObject* rawobj) {
543 // Check if object can be written in one of the following ways: 776 // Check if object can be written in one of the following ways:
544 // - Smi: the Smi value is written as is (last bit is not tagged). 777 // - Smi: the Smi value is written as is (last bit is not tagged).
545 // - VM internal class (from VM isolate): (index of class in vm isolate | 0x3) 778 // - VM internal class (from VM isolate): (index of class in vm isolate | 0x3)
546 // - Object that has already been written: (negative id in stream | 0x3) 779 // - Object that has already been written: (negative id in stream | 0x3)
547 780
548 NoGCScope no_gc; 781 NoGCScope no_gc;
549 782
550 // First check if it is a Smi (i.e not a heap object). 783 // First check if it is a Smi (i.e not a heap object).
551 if (!rawobj->IsHeapObject()) { 784 if (!rawobj->IsHeapObject()) {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
596 // Check if classes are not being serialized and it is preinitialized type. 829 // Check if classes are not being serialized and it is preinitialized type.
597 if (kind_ != Snapshot::kFull) { 830 if (kind_ != Snapshot::kFull) {
598 RawType* raw_type = reinterpret_cast<RawType*>(rawobj); 831 RawType* raw_type = reinterpret_cast<RawType*>(rawobj);
599 index = object_store()->GetTypeIndex(raw_type); 832 index = object_store()->GetTypeIndex(raw_type);
600 if (index != ObjectStore::kInvalidIndex) { 833 if (index != ObjectStore::kInvalidIndex) {
601 WriteIndexedObject(index); 834 WriteIndexedObject(index);
602 return true; 835 return true;
603 } 836 }
604 } 837 }
605 838
606 // Check if object has already been serialized, in that
607 // case just write the object id out.
608 uword tags = rawobj->ptr()->tags_;
609 if (SerializedHeaderTag::decode(tags) == kObjectId) {
610 intptr_t id = SerializedHeaderData::decode(tags);
611 WriteIndexedObject(id);
612 return true;
613 }
614
615 return false; 839 return false;
616 } 840 }
617 841
618 842
619 void SnapshotWriter::WriteInlinedObject(RawObject* raw) { 843 void SnapshotWriter::WriteObjectImpl(RawObject* raw) {
620 NoGCScope no_gc; 844 // First check if object can be written as a simple predefined type.
845 if (CheckAndWritePredefinedObject(raw)) {
846 return;
847 }
848
849 // Check if object has already been serialized, in that
850 // case just write the object id out.
621 uword tags = raw->ptr()->tags_; 851 uword tags = raw->ptr()->tags_;
622 RawClass* cls = class_table_->At(RawObject::ClassIdTag::decode(tags)); 852 if (SerializedHeaderTag::decode(tags) == kObjectId) {
853 intptr_t id = SerializedHeaderData::decode(tags);
854 WriteIndexedObject(id);
855 return;
856 }
623 857
624 // Object is being serialized, add it to the forward ref list and mark 858 // Object is being serialized, add it to the forward ref list and mark
625 // it so that future references to this object in the snapshot will use 859 // it so that future references to this object in the snapshot will use
626 // an object id, instead of trying to serialize it again. 860 // an object id, instead of trying to serialize it again.
627 intptr_t object_id = MarkObject(raw); 861 MarkObject(raw, kIsSerialized);
628 862
863 WriteInlinedObject(raw);
864 }
865
866
867 void SnapshotWriter::WriteInlinedObject(RawObject* raw) {
868 // Assert object is not a simple predefined type.
869 ASSERT(!CheckAndWritePredefinedObject(raw));
870
871 // Now write the object out inline in the stream as follows:
872 // - Object is seen for the first time (inlined as follows):
873 // (object size in multiples of kObjectAlignment | 0x1)
874 // serialized fields of the object
875 // ......
876 NoGCScope no_gc;
877 uword tags = raw->ptr()->tags_;
878 ASSERT(SerializedHeaderTag::decode(tags) == kObjectId);
879 intptr_t object_id = SerializedHeaderData::decode(tags);
880 tags = forward_list_[object_id - kMaxPredefinedObjectIds]->tags();
881 RawClass* cls = class_table_->At(RawObject::ClassIdTag::decode(tags));
629 ObjectKind kind = cls->ptr()->instance_kind_; 882 ObjectKind kind = cls->ptr()->instance_kind_;
883
630 if (kind == Instance::kInstanceKind) { 884 if (kind == Instance::kInstanceKind) {
631 // Object is regular dart instance. 885 // Object is regular dart instance.
632 // TODO(5411462): figure out what we need to do if an object with native 886 // TODO(5411462): figure out what we need to do if an object with native
633 // fields is serialized (throw exception or serialize a null object). 887 // fields is serialized (throw exception or serialize a null object).
634 ASSERT(cls->ptr()->num_native_fields_ == 0); 888 ASSERT(cls->ptr()->num_native_fields_ == 0);
635 intptr_t instance_size = cls->ptr()->instance_size_; 889 intptr_t instance_size = cls->ptr()->instance_size_;
636 ASSERT(instance_size != 0); 890 ASSERT(instance_size != 0);
637 891
638 // Write out the serialization header value for this object. 892 // Write out the serialization header value for this object.
639 WriteSerializationMarker(kInlined, object_id); 893 WriteSerializationMarker(kInlined, object_id);
640 894
641 // Indicate this is an instance object. 895 // Indicate this is an instance object.
642 WriteIntptrValue(SerializedHeaderData::encode(kInstanceId)); 896 WriteIntptrValue(SerializedHeaderData::encode(kInstanceId));
643 897
644 // Write out the tags. 898 // Write out the tags.
645 WriteIntptrValue(tags); 899 WriteIntptrValue(tags);
646 900
647 // Write out the class information for this object. 901 // Write out the class information for this object.
648 WriteObject(cls); 902 WriteObjectImpl(cls);
649 903
650 // Write out all the fields for the object. 904 // Write out all the fields for the object.
651 intptr_t offset = Object::InstanceSize(); 905 intptr_t offset = Object::InstanceSize();
652 while (offset < instance_size) { 906 while (offset < instance_size) {
653 WriteObject(*reinterpret_cast<RawObject**>( 907 WriteObjectRef(*reinterpret_cast<RawObject**>(
654 reinterpret_cast<uword>(raw->ptr()) + offset)); 908 reinterpret_cast<uword>(raw->ptr()) + offset));
655 offset += kWordSize; 909 offset += kWordSize;
656 } 910 }
657 return; 911 return;
658 } 912 }
659 switch (kind) { 913 switch (kind) {
660 #define SNAPSHOT_WRITE(clazz) \ 914 #define SNAPSHOT_WRITE(clazz) \
661 case clazz::kInstanceKind: { \ 915 case clazz::kInstanceKind: { \
662 Raw##clazz* raw_obj = reinterpret_cast<Raw##clazz*>(raw); \ 916 Raw##clazz* raw_obj = reinterpret_cast<Raw##clazz*>(raw); \
663 raw_obj->WriteTo(this, object_id, kind_); \ 917 raw_obj->WriteTo(this, object_id, kind_); \
664 return; \ 918 return; \
665 } \ 919 } \
666 920
667 CLASS_LIST_NO_OBJECT(SNAPSHOT_WRITE) 921 CLASS_LIST_NO_OBJECT(SNAPSHOT_WRITE)
668 #undef SNAPSHOT_WRITE 922 #undef SNAPSHOT_WRITE
669 default: break; 923 default: break;
670 } 924 }
671 UNREACHABLE(); 925 UNREACHABLE();
672 } 926 }
673 927
674 928
929 void SnapshotWriter::WriteForwardedObjects() {
930 // Write out all objects that were added to the forward list and have
931 // not been serialized yet. These would typically be fields of instance
932 // objects, arrays or immutable arrays (this is done in order to avoid
933 // deep recursive calls to WriteObjectImpl).
934 // NOTE: The forward list might grow as we process the list.
935 for (intptr_t i = 0; i < forward_list_.length(); i++) {
936 if (!forward_list_[i]->is_serialized()) {
937 // Write the object out in the stream.
938 RawObject* raw = forward_list_[i]->raw();
939 WriteInlinedObject(raw);
940
941 // Mark object as serialized.
942 forward_list_[i]->set_state(kIsSerialized);
943 }
944 }
945 }
946
947
675 void SnapshotWriter::WriteClassId(RawClass* cls) { 948 void SnapshotWriter::WriteClassId(RawClass* cls) {
676 ASSERT(kind_ != Snapshot::kFull); 949 ASSERT(kind_ != Snapshot::kFull);
677 int id = object_store()->GetClassIndex(cls); 950 int id = object_store()->GetClassIndex(cls);
678 if (IsSingletonClassId(id) || IsObjectStoreClassId(id)) { 951 if (IsSingletonClassId(id) || IsObjectStoreClassId(id)) {
679 WriteIndexedObject(id); 952 WriteIndexedObject(id);
680 } else { 953 } else {
681 // TODO(5411462): Should restrict this to only core-lib classes in this 954 // TODO(5411462): Should restrict this to only core-lib classes in this
682 // case. 955 // case.
683 // Write out the class and tags information. 956 // Write out the class and tags information.
684 WriteObjectHeader(Object::kClassClass, cls->ptr()->tags_); 957 WriteObjectHeader(Object::kClassClass, GetObjectTags(cls));
685 958
686 // Write out the library url and class name. 959 // Write out the library url and class name.
687 RawLibrary* library = cls->ptr()->library_; 960 RawLibrary* library = cls->ptr()->library_;
688 ASSERT(library != Library::null()); 961 ASSERT(library != Library::null());
689 WriteObject(library->ptr()->url_); 962 WriteObjectImpl(library->ptr()->url_);
690 WriteObject(cls->ptr()->name_); 963 WriteObjectImpl(cls->ptr()->name_);
964 }
965 }
966
967
968 void SnapshotWriter::ArrayWriteTo(intptr_t object_id,
969 intptr_t array_kind,
970 intptr_t tags,
971 RawSmi* length,
972 RawAbstractTypeArguments* type_arguments,
973 RawObject* data[]) {
974 intptr_t len = Smi::Value(length);
975
976 // Write out the serialization header value for this object.
977 WriteSerializationMarker(kInlined, object_id);
978
979 // Write out the class and tags information.
980 WriteObjectHeader(array_kind, tags);
981
982 // Write out the length field.
983 Write<RawObject*>(length);
984
985 // Write out the type arguments.
986 WriteObjectImpl(type_arguments);
987
988 // Write out the individual object ids.
989 for (intptr_t i = 0; i < len; i++) {
990 WriteObjectRef(data[i]);
691 } 991 }
692 } 992 }
693 993
694 994
695 void ScriptSnapshotWriter::WriteScriptSnapshot(const Library& lib) { 995 void ScriptSnapshotWriter::WriteScriptSnapshot(const Library& lib) {
696 ASSERT(kind() == Snapshot::kScript); 996 ASSERT(kind() == Snapshot::kScript);
697 997
698 // Write out the library object. 998 // Write out the library object.
699 WriteObject(lib.raw()); 999 WriteObject(lib.raw());
700 1000
701 // Finalize the snapshot buffer. 1001 // Finalize the snapshot buffer.
702 FinalizeBuffer(); 1002 FinalizeBuffer();
703 } 1003 }
704 1004
705 1005
706 void SnapshotWriterVisitor::VisitPointers(RawObject** first, RawObject** last) { 1006 void SnapshotWriterVisitor::VisitPointers(RawObject** first, RawObject** last) {
707 for (RawObject** current = first; current <= last; current++) { 1007 for (RawObject** current = first; current <= last; current++) {
708 RawObject* raw_obj = *current; 1008 RawObject* raw_obj = *current;
709 writer_->WriteObject(raw_obj); 1009 if (as_references_) {
1010 writer_->WriteObjectRef(raw_obj);
1011 } else {
1012 writer_->WriteObjectImpl(raw_obj);
1013 }
710 } 1014 }
711 } 1015 }
712 1016
713 } // namespace dart 1017 } // namespace dart
OLDNEW
« no previous file with comments | « vm/snapshot.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698