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

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
« vm/snapshot.h ('K') | « 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_is_deserialized(true);
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 AddBackwardReference(object_id, &cls, true);
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(GetBackwardReference(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 AddBackwardReference(object_id, &result, false);
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 AddBackwardReference(object_id, &array, false);
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 AddBackwardReference(object_id, &array, false);
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::AddBackwardReference(intptr_t id,
233 Object* obj,
234 bool is_deserialized) {
235 intptr_t index = (id - kMaxPredefinedObjectIds);
236 ASSERT(index == backward_references_.length());
237 BackwardReferenceNode* node = new BackwardReferenceNode(obj, is_deserialized);
238 ASSERT(node != NULL);
239 backward_references_.Add(node);
240 }
241
242
243 Object* SnapshotReader::GetBackwardReference(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_is_deserialized(true);
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 = GetBackwardReference(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*>(
429 AddBackwardReference(object_id, &result); 546 GetBackwardReference(object_id));
430 547 intptr_t instance_size = 0;
431 cls_ ^= ReadObject(); 548 if (result == NULL) {
432 ASSERT(!cls_.IsNull()); 549 result = &(Instance::ZoneHandle(isolate(), Instance::null()));
433 intptr_t instance_size = cls_.instance_size(); 550 AddBackwardReference(object_id, result, true);
434 ASSERT(instance_size > 0); 551 cls_ ^= ReadObjectImpl();
435 // Allocate the instance and read in all the fields for the object. 552 ASSERT(!cls_.IsNull());
436 if (kind_ == Snapshot::kFull) { 553 instance_size = cls_.instance_size();
437 result ^= AllocateUninitialized(cls_, instance_size); 554 ASSERT(instance_size > 0);
555 // Allocate the instance and read in all the fields for the object.
556 if (kind_ == Snapshot::kFull) {
557 *result ^= AllocateUninitialized(cls_, instance_size);
558 } else {
559 *result ^= Object::Allocate(cls_, instance_size, Heap::kNew);
560 }
438 } else { 561 } else {
439 result ^= Object::Allocate(cls_, instance_size, Heap::kNew); 562 cls_ ^= ReadObjectImpl();
563 ASSERT(!cls_.IsNull());
564 instance_size = cls_.instance_size();
440 } 565 }
441 intptr_t offset = Object::InstanceSize(); 566 intptr_t offset = Object::InstanceSize();
442 while (offset < instance_size) { 567 while (offset < instance_size) {
443 obj_ = ReadObject(); 568 obj_ = ReadObjectRef();
444 result.SetFieldAtOffset(offset, obj_); 569 result->SetFieldAtOffset(offset, obj_);
445 offset += kWordSize; 570 offset += kWordSize;
446 } 571 }
447 if (kind_ == Snapshot::kFull) { 572 if (kind_ == Snapshot::kFull) {
448 result.SetCreatedFromSnapshot(); 573 result->SetCreatedFromSnapshot();
449 } else if (result.IsCanonical()) { 574 } else if (result->IsCanonical()) {
450 result = result.Canonicalize(); 575 *result = result->Canonicalize();
451 } 576 }
452 return result.raw(); 577 return result->raw();
453 } else { 578 } else {
454 ASSERT((class_header & kSmiTagMask) != 0); 579 ASSERT((class_header & kSmiTagMask) != 0);
455 cls_ ^= LookupInternalClass(class_header); 580 cls_ ^= LookupInternalClass(class_header);
456 ASSERT(!cls_.IsNull()); 581 ASSERT(!cls_.IsNull());
457 } 582 }
458 switch (cls_.instance_kind()) { 583 switch (cls_.instance_kind()) {
459 #define SNAPSHOT_READ(clazz) \ 584 #define SNAPSHOT_READ(clazz) \
460 case clazz::kInstanceKind: { \ 585 case clazz::kInstanceKind: { \
461 obj_ = clazz::ReadFrom(this, object_id, tags, kind_); \ 586 obj_ = clazz::ReadFrom(this, object_id, tags, kind_); \
462 break; \ 587 break; \
463 } 588 }
464 CLASS_LIST_NO_OBJECT(SNAPSHOT_READ) 589 CLASS_LIST_NO_OBJECT(SNAPSHOT_READ)
465 #undef SNAPSHOT_READ 590 #undef SNAPSHOT_READ
466 default: UNREACHABLE(); break; 591 default: UNREACHABLE(); break;
467 } 592 }
468 if (kind_ == Snapshot::kFull) { 593 if (kind_ == Snapshot::kFull) {
469 obj_.SetCreatedFromSnapshot(); 594 obj_.SetCreatedFromSnapshot();
470 } 595 }
471 return obj_.raw(); 596 return obj_.raw();
472 } 597 }
473 598
474 599
600 void SnapshotReader::ArrayReadFrom(const Array& result,
601 intptr_t len,
602 intptr_t tags) {
603 // Set the object tags.
604 result.set_tags(tags);
605
606 // Setup the object fields.
607 *TypeArgumentsHandle() ^= ReadObjectImpl();
608 result.SetTypeArguments(*TypeArgumentsHandle());
609
610 for (intptr_t i = 0; i < len; i++) {
611 *ObjectHandle() = ReadObjectRef();
612 result.SetAt(i, *ObjectHandle());
613 }
614 }
615
616
475 void SnapshotWriter::WriteObject(RawObject* rawobj) { 617 void SnapshotWriter::WriteObject(RawObject* rawobj) {
476 // First check if object can be written as a simple predefined type. 618 WriteObjectImpl(rawobj);
477 if (CheckAndWritePredefinedObject(rawobj)) { 619 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 } 620 }
487 621
488 622
489 void SnapshotWriter::UnmarkAll() { 623 void SnapshotWriter::WriteObjectRef(RawObject* raw) {
624 // First check if object can be written as a simple predefined type.
625 if (CheckAndWritePredefinedObject(raw)) {
626 return;
627 }
628 // Check if object has already been serialized, in that
629 // case just write the object id out.
630 uword tags = raw->ptr()->tags_;
631 if (SerializedHeaderTag::decode(tags) == kObjectId) {
632 intptr_t id = SerializedHeaderData::decode(tags);
633 WriteIndexedObject(id);
634 return;
635 }
636
490 NoGCScope no_gc; 637 NoGCScope no_gc;
491 for (intptr_t i = 0; i < forward_list_.length(); i++) { 638 RawClass* cls = class_table_->At(RawObject::ClassIdTag::decode(tags));
492 RawObject* raw = forward_list_[i]->raw(); 639
493 raw->ptr()->tags_ = forward_list_[i]->tags(); // Restore original tags. 640 ObjectKind obj_kind = cls->ptr()->instance_kind_;
641 if (obj_kind == Instance::kInstanceKind) {
642 // Object is being referenced, add it to the forward ref list and mark
643 // it so that future references to this object in the snapshot will use
644 // this object id. Mark it as not having been serialized yet so that we
645 // will serialize the object when we go through the forward list.
646 intptr_t object_id = MarkObject(raw, false);
647
648 // Write out the serialization header value for this object.
649 WriteSerializationMarker(kInlined, object_id);
650
651 // Indicate this is an instance object.
652 WriteIntptrValue(SerializedHeaderData::encode(kInstanceId));
653
654 // Write out the class information for this object.
655 WriteObjectImpl(cls);
656
657 return;
494 } 658 }
659 if (obj_kind == Array::kInstanceKind) {
660 // Object is being referenced, add it to the forward ref list and mark
661 // it so that future references to this object in the snapshot will use
662 // this object id. Mark it as not having been serialized yet so that we
663 // will serialize the object when we go through the forward list.
664 intptr_t object_id = MarkObject(raw, false);
665
666 RawArray* rawarray = reinterpret_cast<RawArray*>(raw);
667
668 // Write out the serialization header value for this object.
669 WriteSerializationMarker(kInlined, object_id);
670
671 // Write out the class information.
672 WriteIndexedObject(ObjectStore::kArrayClass);
673
674 // Write out the length field.
675 Write<RawObject*>(rawarray->ptr()->length_);
676
677 return;
678 }
679 if (obj_kind == ImmutableArray::kInstanceKind) {
680 // Object is being referenced, add it to the forward ref list and mark
681 // it so that future references to this object in the snapshot will use
682 // this object id. Mark it as not having been serialized yet so that we
683 // will serialize the object when we go through the forward list.
684 intptr_t object_id = MarkObject(raw, false);
685
686 RawArray* rawarray = reinterpret_cast<RawArray*>(raw);
687
688 // Write out the serialization header value for this object.
689 WriteSerializationMarker(kInlined, object_id);
690
691 // Write out the class information.
692 WriteIndexedObject(ObjectStore::kImmutableArrayClass);
693
694 // Write out the length field.
695 Write<RawObject*>(rawarray->ptr()->length_);
696
697 return;
698 }
699 // Object is being referenced, add it to the forward ref list and mark
700 // it so that future references to this object in the snapshot will use
701 // this object id. Mark it as not having been serialized yet so that we
702 // will serialize the object when we go through the forward list.
703 intptr_t object_id = MarkObject(raw, true);
704 switch (obj_kind) {
705 #define SNAPSHOT_WRITE(clazz) \
706 case clazz::kInstanceKind: { \
707 Raw##clazz* raw_obj = reinterpret_cast<Raw##clazz*>(raw); \
708 raw_obj->WriteTo(this, object_id, kind_); \
709 return; \
710 } \
711
712 CLASS_LIST_NO_OBJECT(SNAPSHOT_WRITE)
713 #undef SNAPSHOT_WRITE
714 default: break;
715 }
716 UNREACHABLE();
495 } 717 }
496 718
497 719
498 void SnapshotWriter::WriteFullSnapshot() { 720 void SnapshotWriter::WriteFullSnapshot() {
499 ASSERT(kind_ == Snapshot::kFull); 721 ASSERT(kind_ == Snapshot::kFull);
500 Isolate* isolate = Isolate::Current(); 722 Isolate* isolate = Isolate::Current();
501 ASSERT(isolate != NULL); 723 ASSERT(isolate != NULL);
502 ObjectStore* object_store = isolate->object_store(); 724 ObjectStore* object_store = isolate->object_store();
503 ASSERT(object_store != NULL); 725 ASSERT(object_store != NULL);
504 726
505 // Write out all the objects in the object store of the isolate which 727 // 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. 728 // is the root set for all dart allocated objects at this point.
507 SnapshotWriterVisitor visitor(this); 729 SnapshotWriterVisitor visitor(this, false);
508 object_store->VisitObjectPointers(&visitor); 730 object_store->VisitObjectPointers(&visitor);
509 731
732 // Write out all forwarded objects.
733 WriteForwardedObjects();
734
510 // Finalize the snapshot buffer. 735 // Finalize the snapshot buffer.
511 FinalizeBuffer(); 736 FinalizeBuffer();
512 } 737 }
513 738
514 739
515 uword SnapshotWriter::GetObjectTags(RawObject* raw) { 740 uword SnapshotWriter::GetObjectTags(RawObject* raw) {
516 uword tags = raw->ptr()->tags_; 741 uword tags = raw->ptr()->tags_;
517 if (SerializedHeaderTag::decode(tags) == kObjectId) { 742 if (SerializedHeaderTag::decode(tags) == kObjectId) {
518 intptr_t id = SerializedHeaderData::decode(tags); 743 intptr_t id = SerializedHeaderData::decode(tags);
519 return forward_list_[id - kMaxPredefinedObjectIds]->tags(); 744 return forward_list_[id - kMaxPredefinedObjectIds]->tags();
520 } else { 745 } else {
521 return tags; 746 return tags;
522 } 747 }
523 } 748 }
524 749
525 750
526 intptr_t SnapshotWriter::MarkObject(RawObject* raw) { 751 intptr_t SnapshotWriter::MarkObject(RawObject* raw, bool is_serialized) {
527 NoGCScope no_gc; 752 NoGCScope no_gc;
528 intptr_t object_id = forward_list_.length() + kMaxPredefinedObjectIds; 753 intptr_t object_id = forward_list_.length() + kMaxPredefinedObjectIds;
529 ASSERT(object_id <= kMaxObjectId); 754 ASSERT(object_id <= kMaxObjectId);
530 uword value = 0; 755 uword value = 0;
531 value = SerializedHeaderTag::update(kObjectId, value); 756 value = SerializedHeaderTag::update(kObjectId, value);
532 value = SerializedHeaderData::update(object_id, value); 757 value = SerializedHeaderData::update(object_id, value);
533 uword tags = raw->ptr()->tags_; 758 uword tags = raw->ptr()->tags_;
534 raw->ptr()->tags_ = value; 759 raw->ptr()->tags_ = value;
535 ForwardObjectNode* node = new ForwardObjectNode(raw, tags); 760 ForwardObjectNode* node = new ForwardObjectNode(raw, tags, is_serialized);
536 ASSERT(node != NULL); 761 ASSERT(node != NULL);
537 forward_list_.Add(node); 762 forward_list_.Add(node);
538 return object_id; 763 return object_id;
539 } 764 }
540 765
541 766
767 void SnapshotWriter::UnmarkAll() {
768 NoGCScope no_gc;
769 for (intptr_t i = 0; i < forward_list_.length(); i++) {
770 RawObject* raw = forward_list_[i]->raw();
771 raw->ptr()->tags_ = forward_list_[i]->tags(); // Restore original tags.
772 }
773 }
774
775
542 bool SnapshotWriter::CheckAndWritePredefinedObject(RawObject* rawobj) { 776 bool SnapshotWriter::CheckAndWritePredefinedObject(RawObject* rawobj) {
543 // Check if object can be written in one of the following ways: 777 // 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). 778 // - 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) 779 // - 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) 780 // - Object that has already been written: (negative id in stream | 0x3)
547 781
548 NoGCScope no_gc; 782 NoGCScope no_gc;
549 783
550 // First check if it is a Smi (i.e not a heap object). 784 // First check if it is a Smi (i.e not a heap object).
551 if (!rawobj->IsHeapObject()) { 785 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. 830 // Check if classes are not being serialized and it is preinitialized type.
597 if (kind_ != Snapshot::kFull) { 831 if (kind_ != Snapshot::kFull) {
598 RawType* raw_type = reinterpret_cast<RawType*>(rawobj); 832 RawType* raw_type = reinterpret_cast<RawType*>(rawobj);
599 index = object_store()->GetTypeIndex(raw_type); 833 index = object_store()->GetTypeIndex(raw_type);
600 if (index != ObjectStore::kInvalidIndex) { 834 if (index != ObjectStore::kInvalidIndex) {
601 WriteIndexedObject(index); 835 WriteIndexedObject(index);
602 return true; 836 return true;
603 } 837 }
604 } 838 }
605 839
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; 840 return false;
616 } 841 }
617 842
618 843
619 void SnapshotWriter::WriteInlinedObject(RawObject* raw) { 844 void SnapshotWriter::WriteObjectImpl(RawObject* raw) {
620 NoGCScope no_gc; 845 // First check if object can be written as a simple predefined type.
846 if (CheckAndWritePredefinedObject(raw)) {
847 return;
848 }
849
850 // Check if object has already been serialized, in that
851 // case just write the object id out.
621 uword tags = raw->ptr()->tags_; 852 uword tags = raw->ptr()->tags_;
622 RawClass* cls = class_table_->At(RawObject::ClassIdTag::decode(tags)); 853 if (SerializedHeaderTag::decode(tags) == kObjectId) {
854 intptr_t id = SerializedHeaderData::decode(tags);
855 WriteIndexedObject(id);
856 return;
857 }
623 858
624 // Object is being serialized, add it to the forward ref list and mark 859 // 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 860 // it so that future references to this object in the snapshot will use
626 // an object id, instead of trying to serialize it again. 861 // an object id, instead of trying to serialize it again.
627 intptr_t object_id = MarkObject(raw); 862 MarkObject(raw, true);
628 863
864 WriteInlinedObject(raw);
865 }
866
867
868 void SnapshotWriter::WriteInlinedObject(RawObject* raw) {
869 // Assert object is not a simple predefined type.
870 ASSERT(!CheckAndWritePredefinedObject(raw));
871
872 // Now write the object out inline in the stream as follows:
873 // - Object is seen for the first time (inlined as follows):
874 // (object size in multiples of kObjectAlignment | 0x1)
875 // serialized fields of the object
876 // ......
877 NoGCScope no_gc;
878 uword tags = raw->ptr()->tags_;
879 ASSERT(SerializedHeaderTag::decode(tags) == kObjectId);
880 intptr_t object_id = SerializedHeaderData::decode(tags);
881 tags = forward_list_[object_id - kMaxPredefinedObjectIds]->tags();
882 RawClass* cls = class_table_->At(RawObject::ClassIdTag::decode(tags));
629 ObjectKind kind = cls->ptr()->instance_kind_; 883 ObjectKind kind = cls->ptr()->instance_kind_;
884
630 if (kind == Instance::kInstanceKind) { 885 if (kind == Instance::kInstanceKind) {
631 // Object is regular dart instance. 886 // Object is regular dart instance.
632 // TODO(5411462): figure out what we need to do if an object with native 887 // 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). 888 // fields is serialized (throw exception or serialize a null object).
634 ASSERT(cls->ptr()->num_native_fields_ == 0); 889 ASSERT(cls->ptr()->num_native_fields_ == 0);
635 intptr_t instance_size = cls->ptr()->instance_size_; 890 intptr_t instance_size = cls->ptr()->instance_size_;
636 ASSERT(instance_size != 0); 891 ASSERT(instance_size != 0);
637 892
638 // Write out the serialization header value for this object. 893 // Write out the serialization header value for this object.
639 WriteSerializationMarker(kInlined, object_id); 894 WriteSerializationMarker(kInlined, object_id);
640 895
641 // Indicate this is an instance object. 896 // Indicate this is an instance object.
642 WriteIntptrValue(SerializedHeaderData::encode(kInstanceId)); 897 WriteIntptrValue(SerializedHeaderData::encode(kInstanceId));
643 898
644 // Write out the tags. 899 // Write out the tags.
645 WriteIntptrValue(tags); 900 WriteIntptrValue(tags);
646 901
647 // Write out the class information for this object. 902 // Write out the class information for this object.
648 WriteObject(cls); 903 WriteObjectImpl(cls);
649 904
650 // Write out all the fields for the object. 905 // Write out all the fields for the object.
651 intptr_t offset = Object::InstanceSize(); 906 intptr_t offset = Object::InstanceSize();
652 while (offset < instance_size) { 907 while (offset < instance_size) {
653 WriteObject(*reinterpret_cast<RawObject**>( 908 WriteObjectRef(*reinterpret_cast<RawObject**>(
654 reinterpret_cast<uword>(raw->ptr()) + offset)); 909 reinterpret_cast<uword>(raw->ptr()) + offset));
655 offset += kWordSize; 910 offset += kWordSize;
656 } 911 }
657 return; 912 return;
658 } 913 }
659 switch (kind) { 914 switch (kind) {
660 #define SNAPSHOT_WRITE(clazz) \ 915 #define SNAPSHOT_WRITE(clazz) \
661 case clazz::kInstanceKind: { \ 916 case clazz::kInstanceKind: { \
662 Raw##clazz* raw_obj = reinterpret_cast<Raw##clazz*>(raw); \ 917 Raw##clazz* raw_obj = reinterpret_cast<Raw##clazz*>(raw); \
663 raw_obj->WriteTo(this, object_id, kind_); \ 918 raw_obj->WriteTo(this, object_id, kind_); \
664 return; \ 919 return; \
665 } \ 920 } \
666 921
667 CLASS_LIST_NO_OBJECT(SNAPSHOT_WRITE) 922 CLASS_LIST_NO_OBJECT(SNAPSHOT_WRITE)
668 #undef SNAPSHOT_WRITE 923 #undef SNAPSHOT_WRITE
669 default: break; 924 default: break;
670 } 925 }
671 UNREACHABLE(); 926 UNREACHABLE();
672 } 927 }
673 928
674 929
930 void SnapshotWriter::WriteForwardedObjects() {
931 // Write out all objects that were added to the forward list and have
932 // not been serialized yet. These would typically be fields of instance
933 // objects, arrays or immutable arrays (this is done in order to avoid
934 // deep recursive calls to WriteObjectImpl).
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_is_serialized(true);
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
« vm/snapshot.h ('K') | « vm/snapshot.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698