OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |