| 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 |