| 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/bootstrap.h" | 8 #include "vm/bootstrap.h" |
| 9 #include "vm/class_finalizer.h" | 9 #include "vm/class_finalizer.h" |
| 10 #include "vm/dart.h" | 10 #include "vm/dart.h" |
| (...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 patch_offset); | 391 patch_offset); |
| 392 } | 392 } |
| 393 | 393 |
| 394 | 394 |
| 395 RawObject* SnapshotReader::ReadObjectImpl(intptr_t header_value, | 395 RawObject* SnapshotReader::ReadObjectImpl(intptr_t header_value, |
| 396 bool as_reference, | 396 bool as_reference, |
| 397 intptr_t patch_object_id, | 397 intptr_t patch_object_id, |
| 398 intptr_t patch_offset) { | 398 intptr_t patch_offset) { |
| 399 if (IsVMIsolateObject(header_value)) { | 399 if (IsVMIsolateObject(header_value)) { |
| 400 return ReadVMIsolateObject(header_value); | 400 return ReadVMIsolateObject(header_value); |
| 401 } else { | 401 } |
| 402 if (SerializedHeaderTag::decode(header_value) == kObjectId) { | 402 if (SerializedHeaderTag::decode(header_value) == kObjectId) { |
| 403 return ReadIndexedObject(SerializedHeaderData::decode(header_value), | 403 return ReadIndexedObject(SerializedHeaderData::decode(header_value), |
| 404 patch_object_id, | |
| 405 patch_offset); | |
| 406 } | |
| 407 ASSERT(SerializedHeaderTag::decode(header_value) == kInlined); | |
| 408 intptr_t object_id = SerializedHeaderData::decode(header_value); | |
| 409 if (object_id == kOmittedObjectId) { | |
| 410 object_id = NextAvailableObjectId(); | |
| 411 } | |
| 412 | |
| 413 // Read the class header information. | |
| 414 intptr_t class_header = Read<int32_t>(); | |
| 415 intptr_t tags = ReadTags(); | |
| 416 if (as_reference && !RawObject::IsCanonical(tags)) { | |
| 417 return ReadObjectRef(object_id, | |
| 418 class_header, | |
| 419 tags, | |
| 420 patch_object_id, | |
| 421 patch_offset); | |
| 422 } | |
| 423 return ReadInlinedObject(object_id, | |
| 424 class_header, | |
| 425 tags, | |
| 426 patch_object_id, | 404 patch_object_id, |
| 427 patch_offset); | 405 patch_offset); |
| 428 } | 406 } |
| 429 } | 407 ASSERT(SerializedHeaderTag::decode(header_value) == kInlined); |
| 408 intptr_t object_id = SerializedHeaderData::decode(header_value); |
| 409 if (object_id == kOmittedObjectId) { |
| 410 object_id = NextAvailableObjectId(); |
| 411 } |
| 430 | 412 |
| 431 | 413 // Read the class header information. |
| 432 RawObject* SnapshotReader::ReadObjectRef(intptr_t object_id, | 414 intptr_t class_header = Read<int32_t>(); |
| 433 intptr_t class_header, | 415 intptr_t tags = ReadTags(); |
| 434 intptr_t tags, | 416 bool read_as_reference = as_reference && !RawObject::IsCanonical(tags); |
| 435 intptr_t patch_object_id, | |
| 436 intptr_t patch_offset) { | |
| 437 // Since we are only reading an object reference, If it is an instance kind | |
| 438 // then we only need to figure out the class of the object and allocate an | |
| 439 // instance of it. The individual fields will be read later. | |
| 440 intptr_t header_id = SerializedHeaderData::decode(class_header); | 417 intptr_t header_id = SerializedHeaderData::decode(class_header); |
| 441 if (header_id == kInstanceObjectId) { | 418 if (header_id == kInstanceObjectId) { |
| 442 Instance& result = Instance::ZoneHandle(zone(), Instance::null()); | 419 return ReadInstance(object_id, tags, read_as_reference); |
| 443 AddBackRef(object_id, &result, kIsNotDeserialized); | |
| 444 | |
| 445 cls_ ^= ReadObjectImpl(kAsInlinedObject); // Read class information. | |
| 446 ASSERT(!cls_.IsNull()); | |
| 447 intptr_t instance_size = cls_.instance_size(); | |
| 448 ASSERT(instance_size > 0); | |
| 449 if (kind_ == Snapshot::kFull) { | |
| 450 result ^= AllocateUninitialized(cls_.id(), instance_size); | |
| 451 } else { | |
| 452 result ^= Object::Allocate(cls_.id(), instance_size, HEAP_SPACE(kind_)); | |
| 453 } | |
| 454 return result.raw(); | |
| 455 } else if (header_id == kStaticImplicitClosureObjectId) { | 420 } else if (header_id == kStaticImplicitClosureObjectId) { |
| 456 // We skip the tags that have been written as the implicit static | 421 // We skip the tags that have been written as the implicit static |
| 457 // closure is going to be created in this isolate or the canonical | 422 // closure is going to be created in this isolate or the canonical |
| 458 // version already created in the isolate will be used. | 423 // version already created in the isolate will be used. |
| 459 return ReadStaticImplicitClosure(object_id, class_header); | 424 return ReadStaticImplicitClosure(object_id, class_header); |
| 460 } | 425 } |
| 461 ASSERT((class_header & kSmiTagMask) != kSmiTag); | 426 ASSERT((class_header & kSmiTagMask) != kSmiTag); |
| 462 | 427 |
| 463 // Similarly Array and ImmutableArray objects are also similarly only | |
| 464 // allocated here, the individual array elements are read later. | |
| 465 intptr_t class_id = LookupInternalClass(class_header); | 428 intptr_t class_id = LookupInternalClass(class_header); |
| 466 if (class_id == kArrayCid) { | |
| 467 // Read the length and allocate an object based on the len. | |
| 468 intptr_t len = ReadSmiValue(); | |
| 469 Array& array = Array::ZoneHandle( | |
| 470 zone(), | |
| 471 ((kind_ == Snapshot::kFull) ? | |
| 472 NewArray(len) : Array::New(len, HEAP_SPACE(kind_)))); | |
| 473 AddBackRef(object_id, &array, kIsNotDeserialized); | |
| 474 | |
| 475 return array.raw(); | |
| 476 } | |
| 477 if (class_id == kImmutableArrayCid) { | |
| 478 // Read the length and allocate an object based on the len. | |
| 479 intptr_t len = ReadSmiValue(); | |
| 480 Array& array = Array::ZoneHandle( | |
| 481 zone(), | |
| 482 (kind_ == Snapshot::kFull) ? | |
| 483 NewImmutableArray(len) : ImmutableArray::New(len, HEAP_SPACE(kind_))); | |
| 484 AddBackRef(object_id, &array, kIsNotDeserialized); | |
| 485 | |
| 486 return array.raw(); | |
| 487 } | |
| 488 if (class_id == kObjectPoolCid) { | |
| 489 ASSERT(kind_ == Snapshot::kFull); | |
| 490 // Read the length and allocate an object based on the len. | |
| 491 intptr_t len = Read<intptr_t>(); | |
| 492 ObjectPool& pool = ObjectPool::ZoneHandle(zone(), | |
| 493 NewObjectPool(len)); | |
| 494 AddBackRef(object_id, &pool, kIsNotDeserialized); | |
| 495 | |
| 496 return pool.raw(); | |
| 497 } | |
| 498 | |
| 499 // For all other internal VM classes we read the object inline. | |
| 500 switch (class_id) { | 429 switch (class_id) { |
| 501 #define SNAPSHOT_READ(clazz) \ | 430 #define SNAPSHOT_READ(clazz) \ |
| 502 case clazz::kClassId: { \ | 431 case clazz::kClassId: { \ |
| 503 pobj_ = clazz::ReadFrom(this, object_id, tags, kind_, true); \ | 432 pobj_ = clazz::ReadFrom(this, object_id, tags, kind_, read_as_reference);\ |
| 504 break; \ | 433 break; \ |
| 505 } | 434 } |
| 506 CLASS_LIST_NO_OBJECT(SNAPSHOT_READ) | 435 CLASS_LIST_NO_OBJECT(SNAPSHOT_READ) |
| 507 #undef SNAPSHOT_READ | 436 #undef SNAPSHOT_READ |
| 508 #define SNAPSHOT_READ(clazz) \ | 437 #define SNAPSHOT_READ(clazz) \ |
| 509 case kTypedData##clazz##Cid: \ | 438 case kTypedData##clazz##Cid: \ |
| 510 | 439 |
| 511 CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) { | 440 CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) { |
| 512 tags = RawObject::ClassIdTag::update(class_id, tags); | 441 tags = RawObject::ClassIdTag::update(class_id, tags); |
| 513 pobj_ = TypedData::ReadFrom(this, object_id, tags, kind_, true); | 442 pobj_ = TypedData::ReadFrom( |
| 443 this, object_id, tags, kind_, read_as_reference); |
| 514 break; | 444 break; |
| 515 } | 445 } |
| 516 #undef SNAPSHOT_READ | 446 #undef SNAPSHOT_READ |
| 517 #define SNAPSHOT_READ(clazz) \ | 447 #define SNAPSHOT_READ(clazz) \ |
| 518 case kExternalTypedData##clazz##Cid: \ | 448 case kExternalTypedData##clazz##Cid: \ |
| 519 | 449 |
| 520 CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) { | 450 CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) { |
| 521 tags = RawObject::ClassIdTag::update(class_id, tags); | 451 tags = RawObject::ClassIdTag::update(class_id, tags); |
| 522 pobj_ = ExternalTypedData::ReadFrom(this, object_id, tags, kind_, true); | 452 pobj_ = ExternalTypedData::ReadFrom(this, object_id, tags, kind_, true); |
| 523 break; | 453 break; |
| 524 } | 454 } |
| 525 #undef SNAPSHOT_READ | 455 #undef SNAPSHOT_READ |
| 526 default: UNREACHABLE(); break; | 456 default: UNREACHABLE(); break; |
| 527 } | 457 } |
| 458 if (!read_as_reference) { |
| 459 AddPatchRecord(object_id, patch_object_id, patch_offset); |
| 460 } |
| 528 return pobj_.raw(); | 461 return pobj_.raw(); |
| 529 } | 462 } |
| 530 | 463 |
| 531 | 464 |
| 532 RawObject* SnapshotReader::ReadInlinedObject(intptr_t object_id, | 465 RawObject* SnapshotReader::ReadInstance(intptr_t object_id, |
| 533 intptr_t class_header, | 466 intptr_t tags, |
| 534 intptr_t tags, | 467 bool as_reference) { |
| 535 intptr_t patch_object_id, | 468 // Object is regular dart instance. |
| 536 intptr_t patch_offset) { | 469 intptr_t instance_size = 0; |
| 537 // Lookup the class based on the class header information. | 470 Instance* result = NULL; |
| 538 intptr_t header_id = SerializedHeaderData::decode(class_header); | 471 DeserializeState state; |
| 539 if (header_id == kInstanceObjectId) { | 472 if (!as_reference) { |
| 540 // Object is regular dart instance. | 473 result = reinterpret_cast<Instance*>(GetBackRef(object_id)); |
| 541 Instance* result = reinterpret_cast<Instance*>(GetBackRef(object_id)); | 474 state = kIsDeserialized; |
| 542 intptr_t instance_size = 0; | 475 } else { |
| 543 if (result == NULL) { | 476 state = kIsNotDeserialized; |
| 544 result = &(Instance::ZoneHandle(zone(), Instance::null())); | 477 } |
| 545 AddBackRef(object_id, result, kIsDeserialized); | 478 if (result == NULL) { |
| 546 cls_ ^= ReadObjectImpl(kAsInlinedObject); | 479 result = &(Instance::ZoneHandle(zone(), Instance::null())); |
| 547 ASSERT(!cls_.IsNull()); | 480 AddBackRef(object_id, result, state); |
| 548 instance_size = cls_.instance_size(); | 481 cls_ ^= ReadObjectImpl(kAsInlinedObject); |
| 549 ASSERT(instance_size > 0); | 482 ASSERT(!cls_.IsNull()); |
| 550 // Allocate the instance and read in all the fields for the object. | 483 instance_size = cls_.instance_size(); |
| 551 if (kind_ == Snapshot::kFull) { | 484 ASSERT(instance_size > 0); |
| 552 *result ^= AllocateUninitialized(cls_.id(), instance_size); | 485 // Allocate the instance and read in all the fields for the object. |
| 553 } else { | 486 if (kind_ == Snapshot::kFull) { |
| 554 *result ^= Object::Allocate(cls_.id(), | 487 *result ^= AllocateUninitialized(cls_.id(), instance_size); |
| 555 instance_size, | |
| 556 HEAP_SPACE(kind_)); | |
| 557 } | |
| 558 } else { | 488 } else { |
| 559 cls_ ^= ReadObjectImpl(kAsInlinedObject); | 489 *result ^= Object::Allocate(cls_.id(), instance_size, HEAP_SPACE(kind_)); |
| 560 ASSERT(!cls_.IsNull()); | |
| 561 instance_size = cls_.instance_size(); | |
| 562 } | 490 } |
| 491 } else { |
| 492 cls_ ^= ReadObjectImpl(kAsInlinedObject); |
| 493 ASSERT(!cls_.IsNull()); |
| 494 instance_size = cls_.instance_size(); |
| 495 } |
| 496 if (!as_reference) { |
| 497 // Read all the individual fields for inlined objects. |
| 563 intptr_t next_field_offset = Class::IsSignatureClass(cls_.raw()) | 498 intptr_t next_field_offset = Class::IsSignatureClass(cls_.raw()) |
| 564 ? Closure::InstanceSize() : cls_.next_field_offset(); | 499 ? Closure::InstanceSize() : cls_.next_field_offset(); |
| 565 | 500 |
| 566 intptr_t type_argument_field_offset = cls_.type_arguments_field_offset(); | 501 intptr_t type_argument_field_offset = cls_.type_arguments_field_offset(); |
| 567 ASSERT(next_field_offset > 0); | 502 ASSERT(next_field_offset > 0); |
| 568 // Instance::NextFieldOffset() returns the offset of the first field in | 503 // Instance::NextFieldOffset() returns the offset of the first field in |
| 569 // a Dart object. | 504 // a Dart object. |
| 570 bool as_reference = RawObject::IsCanonical(tags) ? false : true; | 505 bool read_as_reference = RawObject::IsCanonical(tags) ? false : true; |
| 571 intptr_t offset = Instance::NextFieldOffset(); | 506 intptr_t offset = Instance::NextFieldOffset(); |
| 572 intptr_t result_cid = result->GetClassId(); | 507 intptr_t result_cid = result->GetClassId(); |
| 573 while (offset < next_field_offset) { | 508 while (offset < next_field_offset) { |
| 574 pobj_ = ReadObjectImpl(as_reference); | 509 pobj_ = ReadObjectImpl(read_as_reference); |
| 575 result->SetFieldAtOffset(offset, pobj_); | 510 result->SetFieldAtOffset(offset, pobj_); |
| 576 if ((offset != type_argument_field_offset) && | 511 if ((offset != type_argument_field_offset) && |
| 577 (kind_ == Snapshot::kMessage)) { | 512 (kind_ == Snapshot::kMessage)) { |
| 578 // TODO(fschneider): Consider hoisting these lookups out of the loop. | 513 // TODO(fschneider): Consider hoisting these lookups out of the loop. |
| 579 // This would involve creating a handle, since cls_ can't be reused | 514 // This would involve creating a handle, since cls_ can't be reused |
| 580 // across the call to ReadObjectImpl. | 515 // across the call to ReadObjectImpl. |
| 581 cls_ = isolate()->class_table()->At(result_cid); | 516 cls_ = isolate()->class_table()->At(result_cid); |
| 582 array_ = cls_.OffsetToFieldMap(); | 517 array_ = cls_.OffsetToFieldMap(); |
| 583 field_ ^= array_.At(offset >> kWordSizeLog2); | 518 field_ ^= array_.At(offset >> kWordSizeLog2); |
| 584 ASSERT(!field_.IsNull()); | 519 ASSERT(!field_.IsNull()); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 599 } | 534 } |
| 600 } | 535 } |
| 601 if (RawObject::IsCanonical(tags)) { | 536 if (RawObject::IsCanonical(tags)) { |
| 602 if (kind_ == Snapshot::kFull) { | 537 if (kind_ == Snapshot::kFull) { |
| 603 result->SetCanonical(); | 538 result->SetCanonical(); |
| 604 } else { | 539 } else { |
| 605 *result = result->CheckAndCanonicalize(NULL); | 540 *result = result->CheckAndCanonicalize(NULL); |
| 606 ASSERT(!result->IsNull()); | 541 ASSERT(!result->IsNull()); |
| 607 } | 542 } |
| 608 } | 543 } |
| 609 return result->raw(); | |
| 610 } else if (header_id == kStaticImplicitClosureObjectId) { | |
| 611 // We do not use the tags as the implicit static closure | |
| 612 // is going to be created in this isolate or the canonical | |
| 613 // version already created in the isolate will be used. | |
| 614 return ReadStaticImplicitClosure(object_id, class_header); | |
| 615 } | 544 } |
| 616 ASSERT((class_header & kSmiTagMask) != kSmiTag); | 545 return result->raw(); |
| 617 intptr_t class_id = LookupInternalClass(class_header); | |
| 618 switch (class_id) { | |
| 619 #define SNAPSHOT_READ(clazz) \ | |
| 620 case clazz::kClassId: { \ | |
| 621 pobj_ = clazz::ReadFrom(this, object_id, tags, kind_, false); \ | |
| 622 break; \ | |
| 623 } | |
| 624 CLASS_LIST_NO_OBJECT(SNAPSHOT_READ) | |
| 625 #undef SNAPSHOT_READ | |
| 626 #define SNAPSHOT_READ(clazz) \ | |
| 627 case kTypedData##clazz##Cid: \ | |
| 628 | |
| 629 CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) { | |
| 630 tags = RawObject::ClassIdTag::update(class_id, tags); | |
| 631 pobj_ = TypedData::ReadFrom(this, object_id, tags, kind_, false); | |
| 632 break; | |
| 633 } | |
| 634 #undef SNAPSHOT_READ | |
| 635 #define SNAPSHOT_READ(clazz) \ | |
| 636 case kExternalTypedData##clazz##Cid: \ | |
| 637 | |
| 638 CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) { | |
| 639 tags = RawObject::ClassIdTag::update(class_id, tags); | |
| 640 pobj_ = ExternalTypedData::ReadFrom(this, object_id, tags, kind_, false); | |
| 641 break; | |
| 642 } | |
| 643 #undef SNAPSHOT_READ | |
| 644 default: UNREACHABLE(); break; | |
| 645 } | |
| 646 AddPatchRecord(object_id, patch_object_id, patch_offset); | |
| 647 return pobj_.raw(); | |
| 648 } | 546 } |
| 649 | 547 |
| 650 | 548 |
| 651 void SnapshotReader::AddBackRef(intptr_t id, | 549 void SnapshotReader::AddBackRef(intptr_t id, |
| 652 Object* obj, | 550 Object* obj, |
| 653 DeserializeState state, | 551 DeserializeState state, |
| 654 bool defer_canonicalization) { | 552 bool defer_canonicalization) { |
| 655 intptr_t index = (id - kMaxPredefinedObjectIds); | 553 intptr_t index = (id - kMaxPredefinedObjectIds); |
| 656 ASSERT(index >= max_vm_isolate_object_id_); | 554 ASSERT(index >= max_vm_isolate_object_id_); |
| 657 index -= max_vm_isolate_object_id_; | 555 index -= max_vm_isolate_object_id_; |
| (...skipping 1997 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2655 if (setjmp(*jump.Set()) == 0) { | 2553 if (setjmp(*jump.Set()) == 0) { |
| 2656 NoSafepointScope no_safepoint; | 2554 NoSafepointScope no_safepoint; |
| 2657 WriteObject(obj.raw()); | 2555 WriteObject(obj.raw()); |
| 2658 } else { | 2556 } else { |
| 2659 ThrowException(exception_type(), exception_msg()); | 2557 ThrowException(exception_type(), exception_msg()); |
| 2660 } | 2558 } |
| 2661 } | 2559 } |
| 2662 | 2560 |
| 2663 | 2561 |
| 2664 } // namespace dart | 2562 } // namespace dart |
| OLD | NEW |