| 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 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 467 default: UNREACHABLE(); break; | 467 default: UNREACHABLE(); break; |
| 468 } | 468 } |
| 469 if (kind_ == Snapshot::kFull) { | 469 if (kind_ == Snapshot::kFull) { |
| 470 obj_.SetCreatedFromSnapshot(); | 470 obj_.SetCreatedFromSnapshot(); |
| 471 } | 471 } |
| 472 return obj_.raw(); | 472 return obj_.raw(); |
| 473 } | 473 } |
| 474 | 474 |
| 475 | 475 |
| 476 void SnapshotWriter::WriteObject(RawObject* rawobj) { | 476 void SnapshotWriter::WriteObject(RawObject* rawobj) { |
| 477 // An object is written in one of the following ways: | 477 // First check if object can be written as a simple predefined type. |
| 478 // - Smi: the Smi value is written as is (last bit is not tagged). | 478 if (CheckAndWritePredefinedObject(rawobj)) { |
| 479 // - VM internal class (from VM isolate): (index of class in vm isolate | 0x3) | 479 return; |
| 480 // - Object that has already been written: (negative id in stream | 0x3) | 480 } |
| 481 // - Object that is seen for the first time (inlined as follows): | 481 // Now write the object out inline in the stream as follows: |
| 482 // - Object is seen for the first time (inlined as follows): |
| 482 // (object size in multiples of kObjectAlignment | 0x1) | 483 // (object size in multiples of kObjectAlignment | 0x1) |
| 483 // serialized fields of the object | 484 // serialized fields of the object |
| 484 // ...... | 485 // ...... |
| 485 | |
| 486 NoGCScope no_gc; | |
| 487 // writing a snap shot. | |
| 488 | |
| 489 // First check if it is a Smi (i.e not a heap object). | |
| 490 if (!rawobj->IsHeapObject()) { | |
| 491 Write<int64_t>(reinterpret_cast<intptr_t>(rawobj)); | |
| 492 return; | |
| 493 } | |
| 494 | |
| 495 // Check if it is a singleton null object which is shared by all isolates. | |
| 496 if (rawobj == Object::null()) { | |
| 497 WriteIndexedObject(Object::kNullObject); | |
| 498 return; | |
| 499 } | |
| 500 | |
| 501 // Check if it is a singleton sentinel object which is shared by all isolates. | |
| 502 if (rawobj == Object::sentinel()) { | |
| 503 WriteIndexedObject(Object::kSentinelObject); | |
| 504 return; | |
| 505 } | |
| 506 | |
| 507 // Check if it is a singleton class object which is shared by | |
| 508 // all isolates. | |
| 509 RawClass* raw_class = reinterpret_cast<RawClass*>(rawobj); | |
| 510 intptr_t index = Object::GetSingletonClassIndex(raw_class); | |
| 511 if (index != Object::kInvalidIndex) { | |
| 512 WriteIndexedObject(index); | |
| 513 return; | |
| 514 } | |
| 515 | |
| 516 // Check if it is a singleton boolean true value. | |
| 517 if (rawobj == object_store()->true_value()) { | |
| 518 WriteIndexedObject(ObjectStore::kTrueValue); | |
| 519 return; | |
| 520 } | |
| 521 | |
| 522 // Check if it is a singleton boolean false value. | |
| 523 if (rawobj == object_store()->false_value()) { | |
| 524 WriteIndexedObject(ObjectStore::kFalseValue); | |
| 525 return; | |
| 526 } | |
| 527 | |
| 528 // Check if it is a code object in that case just write a Null object | |
| 529 // as we do not want code objects in the snapshot. | |
| 530 if (RawObject::ClassIdTag::decode(GetObjectTags(rawobj)) == kCode) { | |
| 531 WriteIndexedObject(Object::kNullObject); | |
| 532 return; | |
| 533 } | |
| 534 | |
| 535 // Check if classes are not being serialized and it is preinitialized type. | |
| 536 if (kind_ != Snapshot::kFull) { | |
| 537 RawType* raw_type = reinterpret_cast<RawType*>(rawobj); | |
| 538 index = object_store()->GetTypeIndex(raw_type); | |
| 539 if (index != ObjectStore::kInvalidIndex) { | |
| 540 WriteIndexedObject(index); | |
| 541 return; | |
| 542 } | |
| 543 } | |
| 544 | |
| 545 // Now write the object out inline in the stream. | |
| 546 WriteInlinedObject(rawobj); | 486 WriteInlinedObject(rawobj); |
| 547 } | 487 } |
| 548 | 488 |
| 549 | 489 |
| 550 void SnapshotWriter::UnmarkAll() { | 490 void SnapshotWriter::UnmarkAll() { |
| 551 NoGCScope no_gc; | 491 NoGCScope no_gc; |
| 552 for (intptr_t i = 0; i < forward_list_.length(); i++) { | 492 for (intptr_t i = 0; i < forward_list_.length(); i++) { |
| 553 RawObject* raw = forward_list_[i]->raw(); | 493 RawObject* raw = forward_list_[i]->raw(); |
| 554 raw->ptr()->tags_ = forward_list_[i]->tags(); // Restore original tags. | 494 raw->ptr()->tags_ = forward_list_[i]->tags(); // Restore original tags. |
| 555 } | 495 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 577 uword tags = raw->ptr()->tags_; | 517 uword tags = raw->ptr()->tags_; |
| 578 if (SerializedHeaderTag::decode(tags) == kObjectId) { | 518 if (SerializedHeaderTag::decode(tags) == kObjectId) { |
| 579 intptr_t id = SerializedHeaderData::decode(tags); | 519 intptr_t id = SerializedHeaderData::decode(tags); |
| 580 return forward_list_[id - kMaxPredefinedObjectIds]->tags(); | 520 return forward_list_[id - kMaxPredefinedObjectIds]->tags(); |
| 581 } else { | 521 } else { |
| 582 return tags; | 522 return tags; |
| 583 } | 523 } |
| 584 } | 524 } |
| 585 | 525 |
| 586 | 526 |
| 587 intptr_t SnapshotWriter::MarkObject(RawObject* raw, RawClass* cls) { | 527 intptr_t SnapshotWriter::MarkObject(RawObject* raw) { |
| 588 NoGCScope no_gc; | 528 NoGCScope no_gc; |
| 589 intptr_t object_id = forward_list_.length() + kMaxPredefinedObjectIds; | 529 intptr_t object_id = forward_list_.length() + kMaxPredefinedObjectIds; |
| 590 ASSERT(object_id <= kMaxObjectId); | 530 ASSERT(object_id <= kMaxObjectId); |
| 591 uword value = 0; | 531 uword value = 0; |
| 592 value = SerializedHeaderTag::update(kObjectId, value); | 532 value = SerializedHeaderTag::update(kObjectId, value); |
| 593 value = SerializedHeaderData::update(object_id, value); | 533 value = SerializedHeaderData::update(object_id, value); |
| 594 uword tags = raw->ptr()->tags_; | 534 uword tags = raw->ptr()->tags_; |
| 595 raw->ptr()->tags_ = value; | 535 raw->ptr()->tags_ = value; |
| 596 ForwardObjectNode* node = new ForwardObjectNode(raw, tags); | 536 ForwardObjectNode* node = new ForwardObjectNode(raw, tags); |
| 597 ASSERT(node != NULL); | 537 ASSERT(node != NULL); |
| 598 forward_list_.Add(node); | 538 forward_list_.Add(node); |
| 599 return object_id; | 539 return object_id; |
| 600 } | 540 } |
| 601 | 541 |
| 602 | 542 |
| 543 bool SnapshotWriter::CheckAndWritePredefinedObject(RawObject* rawobj) { |
| 544 // Check if object can be written in one of the following ways: |
| 545 // - Smi: the Smi value is written as is (last bit is not tagged). |
| 546 // - VM internal class (from VM isolate): (index of class in vm isolate | 0x3) |
| 547 // - Object that has already been written: (negative id in stream | 0x3) |
| 548 |
| 549 NoGCScope no_gc; |
| 550 |
| 551 // First check if it is a Smi (i.e not a heap object). |
| 552 if (!rawobj->IsHeapObject()) { |
| 553 Write<int64_t>(reinterpret_cast<intptr_t>(rawobj)); |
| 554 return true; |
| 555 } |
| 556 |
| 557 // Check if it is a singleton null object which is shared by all isolates. |
| 558 if (rawobj == Object::null()) { |
| 559 WriteIndexedObject(Object::kNullObject); |
| 560 return true; |
| 561 } |
| 562 |
| 563 // Check if it is a singleton sentinel object which is shared by all isolates. |
| 564 if (rawobj == Object::sentinel()) { |
| 565 WriteIndexedObject(Object::kSentinelObject); |
| 566 return true; |
| 567 } |
| 568 |
| 569 // Check if it is a singleton class object which is shared by |
| 570 // all isolates. |
| 571 RawClass* raw_class = reinterpret_cast<RawClass*>(rawobj); |
| 572 intptr_t index = Object::GetSingletonClassIndex(raw_class); |
| 573 if (index != Object::kInvalidIndex) { |
| 574 WriteIndexedObject(index); |
| 575 return true; |
| 576 } |
| 577 |
| 578 // Check if it is a singleton boolean true value. |
| 579 if (rawobj == object_store()->true_value()) { |
| 580 WriteIndexedObject(ObjectStore::kTrueValue); |
| 581 return true; |
| 582 } |
| 583 |
| 584 // Check if it is a singleton boolean false value. |
| 585 if (rawobj == object_store()->false_value()) { |
| 586 WriteIndexedObject(ObjectStore::kFalseValue); |
| 587 return true; |
| 588 } |
| 589 |
| 590 // Check if it is a code object in that case just write a Null object |
| 591 // as we do not want code objects in the snapshot. |
| 592 if (RawObject::ClassIdTag::decode(GetObjectTags(rawobj)) == kCode) { |
| 593 WriteIndexedObject(Object::kNullObject); |
| 594 return true; |
| 595 } |
| 596 |
| 597 // Check if classes are not being serialized and it is preinitialized type. |
| 598 if (kind_ != Snapshot::kFull) { |
| 599 RawType* raw_type = reinterpret_cast<RawType*>(rawobj); |
| 600 index = object_store()->GetTypeIndex(raw_type); |
| 601 if (index != ObjectStore::kInvalidIndex) { |
| 602 WriteIndexedObject(index); |
| 603 return true; |
| 604 } |
| 605 } |
| 606 |
| 607 // Check if object has already been serialized, in that |
| 608 // case just write the object id out. |
| 609 uword tags = rawobj->ptr()->tags_; |
| 610 if (SerializedHeaderTag::decode(tags) == kObjectId) { |
| 611 intptr_t id = SerializedHeaderData::decode(tags); |
| 612 WriteIndexedObject(id); |
| 613 return true; |
| 614 } |
| 615 |
| 616 return false; |
| 617 } |
| 618 |
| 619 |
| 603 void SnapshotWriter::WriteInlinedObject(RawObject* raw) { | 620 void SnapshotWriter::WriteInlinedObject(RawObject* raw) { |
| 604 NoGCScope no_gc; | 621 NoGCScope no_gc; |
| 605 uword tags = raw->ptr()->tags_; | 622 uword tags = raw->ptr()->tags_; |
| 606 | |
| 607 // Check if object has already been serialized, in that | |
| 608 // case just write the object id out. | |
| 609 if (SerializedHeaderTag::decode(tags) == kObjectId) { | |
| 610 intptr_t id = SerializedHeaderData::decode(tags); | |
| 611 WriteIndexedObject(id); | |
| 612 return; | |
| 613 } | |
| 614 | |
| 615 RawClass* cls = class_table_->At(RawObject::ClassIdTag::decode(tags)); | 623 RawClass* cls = class_table_->At(RawObject::ClassIdTag::decode(tags)); |
| 616 | 624 |
| 617 // Object is being serialized, add it to the forward ref list and mark | 625 // Object is being serialized, add it to the forward ref list and mark |
| 618 // it so that future references to this object in the snapshot will use | 626 // it so that future references to this object in the snapshot will use |
| 619 // an object id, instead of trying to serialize it again. | 627 // an object id, instead of trying to serialize it again. |
| 620 intptr_t object_id = MarkObject(raw, cls); | 628 intptr_t object_id = MarkObject(raw); |
| 621 | 629 |
| 622 ObjectKind kind = cls->ptr()->instance_kind_; | 630 ObjectKind kind = cls->ptr()->instance_kind_; |
| 623 if (kind == Instance::kInstanceKind) { | 631 if (kind == Instance::kInstanceKind) { |
| 624 // Object is regular dart instance. | 632 // Object is regular dart instance. |
| 625 // TODO(5411462): figure out what we need to do if an object with native | 633 // TODO(5411462): figure out what we need to do if an object with native |
| 626 // fields is serialized (throw exception or serialize a null object). | 634 // fields is serialized (throw exception or serialize a null object). |
| 627 ASSERT(cls->ptr()->num_native_fields_ == 0); | 635 ASSERT(cls->ptr()->num_native_fields_ == 0); |
| 628 intptr_t instance_size = cls->ptr()->instance_size_; | 636 intptr_t instance_size = cls->ptr()->instance_size_; |
| 629 ASSERT(instance_size != 0); | 637 ASSERT(instance_size != 0); |
| 630 | 638 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 697 | 705 |
| 698 | 706 |
| 699 void SnapshotWriterVisitor::VisitPointers(RawObject** first, RawObject** last) { | 707 void SnapshotWriterVisitor::VisitPointers(RawObject** first, RawObject** last) { |
| 700 for (RawObject** current = first; current <= last; current++) { | 708 for (RawObject** current = first; current <= last; current++) { |
| 701 RawObject* raw_obj = *current; | 709 RawObject* raw_obj = *current; |
| 702 writer_->WriteObject(raw_obj); | 710 writer_->WriteObject(raw_obj); |
| 703 } | 711 } |
| 704 } | 712 } |
| 705 | 713 |
| 706 } // namespace dart | 714 } // namespace dart |
| OLD | NEW |