From e61f1dc8ce48789166121364bcbc961f45dc38be Mon Sep 17 00:00:00 2001 From: Siva Annamalai Date: Mon, 10 Aug 2015 11:02:31 -0700 Subject: [PATCH] 1. Reclaim the CreatedFromSnapshot bit and use the bit to indicate VM heap object. 2. Cleanup calls to set_tags when reading objects from a snapshot. 3. Fixes issue 21816 R=regis@google.com Review URL: https://codereview.chromium.org//1221503004 . --- runtime/vm/dart_api_message.cc | 1 + runtime/vm/object.cc | 38 +++- runtime/vm/object.h | 32 ++- runtime/vm/raw_object.cc | 4 - runtime/vm/raw_object.h | 20 +- runtime/vm/raw_object_snapshot.cc | 315 +++++++++--------------------- runtime/vm/snapshot.cc | 32 ++- runtime/vm/snapshot.h | 2 + tests/isolate/isolate.status | 3 - tests/isolate/message3_test.dart | 4 +- 10 files changed, 168 insertions(+), 283 deletions(-) diff --git a/runtime/vm/dart_api_message.cc b/runtime/vm/dart_api_message.cc index 2788be09d8d..69fb8919b44 100644 --- a/runtime/vm/dart_api_message.cc +++ b/runtime/vm/dart_api_message.cc @@ -535,6 +535,7 @@ Dart_CObject* ApiMessageReader::ReadInternalVMObject(intptr_t class_id, intptr_t object_id) { switch (class_id) { case kClassCid: { + Read(); // Consume the is_in_fullsnapshot indicator. Dart_CObject_Internal* object = AllocateDartCObjectClass(); AddBackRef(object_id, object, kIsDeserialized); object->internal.as_class.library_url = ReadObjectImpl(); diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index 1b73107e7b4..61c605fa1a0 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -399,7 +399,7 @@ void Object::InitNull(Isolate* isolate) { uword address = heap->Allocate(Instance::InstanceSize(), Heap::kOld); null_ = reinterpret_cast(address + kHeapObjectTag); // The call below is using 'null_' to initialize itself. - InitializeObject(address, kNullCid, Instance::InstanceSize()); + InitializeObject(address, kNullCid, Instance::InstanceSize(), true); } } @@ -462,7 +462,7 @@ void Object::InitOnce(Isolate* isolate) { intptr_t size = Class::InstanceSize(); uword address = heap->Allocate(size, Heap::kOld); class_class_ = reinterpret_cast(address + kHeapObjectTag); - InitializeObject(address, Class::kClassId, size); + InitializeObject(address, Class::kClassId, size, true); Class fake; // Initialization from Class::New. @@ -635,7 +635,7 @@ void Object::InitOnce(Isolate* isolate) { // Allocate and initialize the empty_array instance. { uword address = heap->Allocate(Array::InstanceSize(0), Heap::kOld); - InitializeObject(address, kImmutableArrayCid, Array::InstanceSize(0)); + InitializeObject(address, kImmutableArrayCid, Array::InstanceSize(0), true); Array::initializeHandle( empty_array_, reinterpret_cast(address + kHeapObjectTag)); @@ -646,7 +646,7 @@ void Object::InitOnce(Isolate* isolate) { // Allocate and initialize the zero_array instance. { uword address = heap->Allocate(Array::InstanceSize(1), Heap::kOld); - InitializeObject(address, kImmutableArrayCid, Array::InstanceSize(1)); + InitializeObject(address, kImmutableArrayCid, Array::InstanceSize(1), true); Array::initializeHandle( zero_array_, reinterpret_cast(address + kHeapObjectTag)); @@ -661,7 +661,8 @@ void Object::InitOnce(Isolate* isolate) { heap->Allocate(ObjectPool::InstanceSize(0), Heap::kOld); InitializeObject(address, kObjectPoolCid, - ObjectPool::InstanceSize(0)); + ObjectPool::InstanceSize(0), + true); ObjectPool::initializeHandle( empty_object_pool_, reinterpret_cast(address + kHeapObjectTag)); @@ -673,7 +674,8 @@ void Object::InitOnce(Isolate* isolate) { { uword address = heap->Allocate(PcDescriptors::InstanceSize(0), Heap::kOld); InitializeObject(address, kPcDescriptorsCid, - PcDescriptors::InstanceSize(0)); + PcDescriptors::InstanceSize(0), + true); PcDescriptors::initializeHandle( empty_descriptors_, reinterpret_cast(address + kHeapObjectTag)); @@ -687,7 +689,8 @@ void Object::InitOnce(Isolate* isolate) { heap->Allocate(LocalVarDescriptors::InstanceSize(0), Heap::kOld); InitializeObject(address, kLocalVarDescriptorsCid, - LocalVarDescriptors::InstanceSize(0)); + LocalVarDescriptors::InstanceSize(0), + true); LocalVarDescriptors::initializeHandle( empty_var_descriptors_, reinterpret_cast(address + kHeapObjectTag)); @@ -703,7 +706,8 @@ void Object::InitOnce(Isolate* isolate) { heap->Allocate(ExceptionHandlers::InstanceSize(0), Heap::kOld); InitializeObject(address, kExceptionHandlersCid, - ExceptionHandlers::InstanceSize(0)); + ExceptionHandlers::InstanceSize(0), + true); ExceptionHandlers::initializeHandle( empty_exception_handlers_, reinterpret_cast(address + kHeapObjectTag)); @@ -809,6 +813,7 @@ class PremarkingVisitor : public ObjectVisitor { ASSERT(!obj->IsMarked()); // Free list elements should never be marked. if (!obj->IsFreeListElement()) { + ASSERT(obj->IsVMHeapObject()); obj->SetMarkBitUnsynchronized(); } } @@ -1674,7 +1679,10 @@ RawString* Object::DictionaryName() const { } -void Object::InitializeObject(uword address, intptr_t class_id, intptr_t size) { +void Object::InitializeObject(uword address, + intptr_t class_id, + intptr_t size, + bool is_vm_object) { // TODO(iposva): Get a proper halt instruction from the assembler which // would be needed here for code objects. uword initial_value = reinterpret_cast(null_); @@ -1688,7 +1696,9 @@ void Object::InitializeObject(uword address, intptr_t class_id, intptr_t size) { ASSERT(class_id != kIllegalCid); tags = RawObject::ClassIdTag::update(class_id, tags); tags = RawObject::SizeTag::update(size, tags); + tags = RawObject::VMHeapObjectTag::update(is_vm_object, tags); reinterpret_cast(address)->tags_ = tags; + ASSERT(is_vm_object == RawObject::IsVMHeapObject(tags)); VerifiedMemory::Accept(address, size); } @@ -1746,7 +1756,7 @@ RawObject* Object::Allocate(intptr_t cls_id, Profiler::RecordAllocation(isolate, cls_id); } NoSafepointScope no_safepoint; - InitializeObject(address, cls_id, size); + InitializeObject(address, cls_id, size, (isolate == Dart::vm_isolate())); RawObject* raw_obj = reinterpret_cast(address + kHeapObjectTag); ASSERT(cls_id == RawObject::ClassIdTag::decode(raw_obj->ptr()->tags_)); return raw_obj; @@ -1840,6 +1850,12 @@ RawString* Class::UserVisibleName() const { } +bool Class::IsInFullSnapshot() const { + NoSafepointScope no_safepoint; + return raw_ptr()->library_->ptr()->is_in_fullsnapshot_; +} + + RawType* Class::SignatureType() const { ASSERT(IsSignatureClass()); const Function& function = Function::Handle(signature_function()); @@ -9828,6 +9844,7 @@ RawLibrary* Library::NewLibraryHelper(const String& url, result.StorePointer(&result.raw_ptr()->load_error_, Instance::null()); result.set_native_entry_resolver(NULL); result.set_native_entry_symbol_resolver(NULL); + result.set_is_in_fullsnapshot(false); result.StoreNonPointer(&result.raw_ptr()->corelib_imported_, true); result.set_debuggable(false); result.set_is_dart_scheme(url.StartsWith(Symbols::DartScheme())); @@ -15260,6 +15277,7 @@ RawType* Type::NewNonParameterizedType(const Class& type_class) { void Type::SetIsFinalized() const { ASSERT(!IsFinalized()); if (IsInstantiated()) { + ASSERT(HasResolvedTypeClass()); set_type_state(RawType::kFinalizedInstantiated); } else { set_type_state(RawType::kFinalizedUninstantiated); diff --git a/runtime/vm/object.h b/runtime/vm/object.h index 8df34c1cb0a..8d3ef5ed669 100644 --- a/runtime/vm/object.h +++ b/runtime/vm/object.h @@ -249,23 +249,6 @@ class Object { return AtomicOperations::CompareAndSwapWord( &raw()->ptr()->tags_, old_tags, new_tags); } - void set_tags(intptr_t value) const { - ASSERT(!IsNull()); - // TODO(asiva): Remove the capability of setting tags in general. The mask - // here only allows for canonical and from_snapshot flags to be set. - value = value & 0x0000000c; - uword tags = raw()->ptr()->tags_; - uword old_tags; - do { - old_tags = tags; - uword new_tags = (old_tags & ~0x0000000c) | value; - tags = CompareAndSwapTags(old_tags, new_tags); - } while (tags != old_tags); - } - void SetCreatedFromSnapshot() const { - ASSERT(!IsNull()); - raw()->SetCreatedFromSnapshot(); - } bool IsCanonical() const { ASSERT(!IsNull()); return raw()->IsCanonical(); @@ -728,7 +711,10 @@ class Object { return -kWordSize; } - static void InitializeObject(uword address, intptr_t id, intptr_t size); + static void InitializeObject(uword address, + intptr_t id, + intptr_t size, + bool is_vm_object); static void RegisterClass(const Class& cls, const String& name, @@ -945,6 +931,7 @@ class Class : public Object { RawString* Name() const; RawString* PrettyName() const; RawString* UserVisibleName() const; + bool IsInFullSnapshot() const; virtual RawString* DictionaryName() const { return Name(); } @@ -1115,6 +1102,10 @@ class Class : public Object { static bool IsSignatureClass(RawClass* cls) { return cls->ptr()->signature_function_ != Object::null(); } + static bool IsInFullSnapshot(RawClass* cls) { + NoSafepointScope no_safepoint; + return cls->ptr()->library_->ptr()->is_in_fullsnapshot_; + } // Check if this class represents a canonical signature class, i.e. not an // alias as defined in a typedef. @@ -3392,6 +3383,11 @@ class Library : public Object { native_symbol_resolver); } + bool is_in_fullsnapshot() const { return raw_ptr()->is_in_fullsnapshot_; } + void set_is_in_fullsnapshot(bool value) const { + StoreNonPointer(&raw_ptr()->is_in_fullsnapshot_, value); + } + RawError* Patch(const Script& script) const; RawString* PrivateName(const String& name) const; diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc index 67f0afc1373..61c2994484e 100644 --- a/runtime/vm/raw_object.cc +++ b/runtime/vm/raw_object.cc @@ -18,10 +18,6 @@ namespace dart { DEFINE_FLAG(bool, validate_overwrite, true, "Verify overwritten fields."); #endif // DEBUG -bool RawObject::IsVMHeapObject() const { - return Dart::vm_isolate()->heap()->Contains(ToAddr(this)); -} - void RawObject::Validate(Isolate* isolate) const { if (Object::void_class_ == reinterpret_cast(kHeapObjectTag)) { diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h index 9976c936fa3..517379b64db 100644 --- a/runtime/vm/raw_object.h +++ b/runtime/vm/raw_object.h @@ -236,7 +236,7 @@ class RawObject { kWatchedBit = 0, kMarkBit = 1, kCanonicalBit = 2, - kFromSnapshotBit = 3, + kVMHeapObjectBit = 3, kRememberedBit = 4, #if defined(ARCH_IS_32_BIT) kReservedTagPos = 5, // kReservedBit{100K,1M,10M} @@ -315,8 +315,6 @@ class RawObject { uword addr = reinterpret_cast(this); return (addr & kNewObjectAlignmentOffset) == kOldObjectAlignmentOffset; } - // Assumes this is a heap object. - bool IsVMHeapObject() const; // Like !IsHeapObject() || IsOldObject(), but compiles to a single branch. bool IsSmiOrOldObject() const { @@ -372,11 +370,11 @@ class RawObject { void ClearCanonical() { UpdateTagBit(false); } - bool IsCreatedFromSnapshot() const { - return CreatedFromSnapshotTag::decode(ptr()->tags_); + bool IsVMHeapObject() const { + return VMHeapObjectTag::decode(ptr()->tags_); } - void SetCreatedFromSnapshot() { - UpdateTagBit(true); + void SetVMHeapObject() { + UpdateTagBit(true); } // Support for GC remembered bit. @@ -445,8 +443,8 @@ class RawObject { return reinterpret_cast(raw_obj->ptr()); } - static bool IsCreatedFromSnapshot(intptr_t value) { - return CreatedFromSnapshotTag::decode(value); + static bool IsVMHeapObject(intptr_t value) { + return VMHeapObjectTag::decode(value); } static bool IsCanonical(intptr_t value) { @@ -482,7 +480,7 @@ class RawObject { class CanonicalObjectTag : public BitField {}; - class CreatedFromSnapshotTag : public BitField {}; + class VMHeapObjectTag : public BitField {}; class ReservedBits : public BitField {}; // NOLINT @@ -950,7 +948,9 @@ class RawLibrary : public RawObject { bool corelib_imported_; bool is_dart_scheme_; bool debuggable_; // True if debugger can stop in library. + bool is_in_fullsnapshot_; // True if library is in a full snapshot. + friend class Class; friend class Isolate; }; diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc index 01aef3ad7f4..9a12d08f26e 100644 --- a/runtime/vm/raw_object_snapshot.cc +++ b/runtime/vm/raw_object_snapshot.cc @@ -31,8 +31,9 @@ RawClass* Class::ReadFrom(SnapshotReader* reader, ASSERT(reader != NULL); Class& cls = Class::ZoneHandle(reader->zone(), Class::null()); + bool is_in_fullsnapshot = reader->Read(); if ((kind == Snapshot::kFull) || - (kind == Snapshot::kScript && !RawObject::IsCreatedFromSnapshot(tags))) { + (kind == Snapshot::kScript && !is_in_fullsnapshot)) { // Read in the base information. classid_t class_id = reader->ReadClassIDValue(); @@ -49,9 +50,6 @@ RawClass* Class::ReadFrom(SnapshotReader* reader, } reader->AddBackRef(object_id, &cls, kIsDeserialized); - // Set the object tags. - cls.set_tags(tags); - // Set all non object fields. if (!RawObject::IsInternalVMdefinedClassId(class_id)) { // Instance size of a VM defined class is already set up. @@ -76,8 +74,10 @@ RawClass* Class::ReadFrom(SnapshotReader* reader, cls.StorePointer((cls.raw()->from() + i), reader->PassiveObjectHandle()->raw()); } + ASSERT(!cls.IsInFullSnapshot() || (kind == Snapshot::kFull)); } else { cls ^= reader->ReadClassId(object_id); + ASSERT((kind == Snapshot::kMessage) || cls.IsInFullSnapshot()); } return cls.raw(); } @@ -87,17 +87,22 @@ void RawClass::WriteTo(SnapshotWriter* writer, intptr_t object_id, Snapshot::Kind kind) { ASSERT(writer != NULL); + bool is_in_fullsnapshot = Class::IsInFullSnapshot(this); // Write out the serialization header value for this object. writer->WriteInlinedObjectHeader(object_id); - if ((kind == Snapshot::kFull) || - (kind == Snapshot::kScript && - !RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this)))) { - // Write out the class and tags information. - writer->WriteVMIsolateObject(kClassCid); - writer->WriteTags(writer->GetObjectTags(this)); + // Write out the class and tags information. + writer->WriteVMIsolateObject(kClassCid); + writer->WriteTags(writer->GetObjectTags(this)); + // Write out the boolean is_in_fullsnapshot first as this will + // help the reader decide how the rest of the information needs + // to be interpreted. + writer->Write(is_in_fullsnapshot); + + if ((kind == Snapshot::kFull) || + (kind == Snapshot::kScript && !is_in_fullsnapshot)) { // Write out all the non object pointer fields. // NOTE: cpp_vtable_ is not written. classid_t class_id = ptr()->id_; @@ -144,9 +149,6 @@ RawUnresolvedClass* UnresolvedClass::ReadFrom(SnapshotReader* reader, reader->zone(), NEW_OBJECT(UnresolvedClass)); reader->AddBackRef(object_id, &unresolved_class, kIsDeserialized); - // Set the object tags. - unresolved_class.set_tags(tags); - // Set all non object fields. unresolved_class.set_token_pos(reader->Read()); @@ -229,11 +231,9 @@ RawType* Type::ReadFrom(SnapshotReader* reader, reader->PassiveObjectHandle()->raw()); } - // Set the object tags. - type.set_tags(tags); - if (defer_canonicalization) { - // We are deferring canonicalization so mark object as not canonical. - type.ClearCanonical(); + // Set the canonical bit. + if (!defer_canonicalization && RawObject::IsCanonical(tags)) { + type.SetCanonical(); } return type.raw(); @@ -248,6 +248,7 @@ void RawType::WriteTo(SnapshotWriter* writer, // Only resolved and finalized types should be written to a snapshot. ASSERT((ptr()->type_state_ == RawType::kFinalizedInstantiated) || (ptr()->type_state_ == RawType::kFinalizedUninstantiated)); + ASSERT(ptr()->type_class_ != Object::null()); // Write out the serialization header value for this object. writer->WriteInlinedObjectHeader(object_id); @@ -263,6 +264,7 @@ void RawType::WriteTo(SnapshotWriter* writer, // Write out all the object pointer fields. Since we will be canonicalizing // the type object when reading it back we should write out all the fields // inline and not as references. + ASSERT(ptr()->type_class_ != Object::null()); SnapshotWriterVisitor visitor(writer); visitor.VisitPointers(from(), to()); } @@ -279,9 +281,6 @@ RawTypeRef* TypeRef::ReadFrom(SnapshotReader* reader, reader->zone(), NEW_OBJECT(TypeRef)); reader->AddBackRef(object_id, &type_ref, kIsDeserialized); - // Set the object tags. - type_ref.set_tags(tags); - // Set all the object fields. // TODO(5411462): Need to assert No GC can happen here, even though // allocations may happen. @@ -327,9 +326,6 @@ RawTypeParameter* TypeParameter::ReadFrom(SnapshotReader* reader, reader->zone(), NEW_OBJECT(TypeParameter)); reader->AddBackRef(object_id, &type_parameter, kIsDeserialized); - // Set the object tags. - type_parameter.set_tags(tags); - // Set all non object fields. type_parameter.set_token_pos(reader->Read()); type_parameter.set_index(reader->Read()); @@ -389,9 +385,6 @@ RawBoundedType* BoundedType::ReadFrom(SnapshotReader* reader, reader->zone(), NEW_OBJECT(BoundedType)); reader->AddBackRef(object_id, &bounded_type, kIsDeserialized); - // Set the object tags. - bounded_type.set_tags(tags); - // Set all the object fields. // TODO(5411462): Need to assert No GC can happen here, even though // allocations may happen. @@ -478,11 +471,9 @@ RawTypeArguments* TypeArguments::ReadFrom(SnapshotReader* reader, type_arguments.SetTypeAt(i, *reader->TypeHandle()); } - // Set the object tags . - type_arguments.set_tags(tags); - if (defer_canonicalization) { - // We are deferring canonicalization so mark object as not canonical. - type_arguments.ClearCanonical(); + // Set the canonical bit. + if (!defer_canonicalization && RawObject::IsCanonical(tags)) { + type_arguments.SetCanonical(); } return type_arguments.raw(); @@ -522,18 +513,12 @@ RawPatchClass* PatchClass::ReadFrom(SnapshotReader* reader, intptr_t tags, Snapshot::Kind kind) { ASSERT(reader != NULL); - ASSERT(((kind == Snapshot::kScript) && - !RawObject::IsCreatedFromSnapshot(tags)) || - (kind == Snapshot::kFull)); // Allocate function object. PatchClass& cls = PatchClass::ZoneHandle(reader->zone(), NEW_OBJECT(PatchClass)); reader->AddBackRef(object_id, &cls, kIsDeserialized); - // Set the object tags. - cls.set_tags(tags); - // Set all the object fields. // TODO(5411462): Need to assert No GC can happen here, even though // allocations may happen. @@ -543,6 +528,9 @@ RawPatchClass* PatchClass::ReadFrom(SnapshotReader* reader, cls.StorePointer((cls.raw()->from() + i), reader->PassiveObjectHandle()->raw()); } + ASSERT(((kind == Snapshot::kScript) && + !Class::IsInFullSnapshot(cls.source_class())) || + (kind == Snapshot::kFull)); return cls.raw(); } @@ -552,9 +540,7 @@ void RawPatchClass::WriteTo(SnapshotWriter* writer, intptr_t object_id, Snapshot::Kind kind) { ASSERT(writer != NULL); - ASSERT(((kind == Snapshot::kScript) && - !RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this))) || - (kind == Snapshot::kFull)); + ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull)); // Write out the serialization header value for this object. writer->WriteInlinedObjectHeader(object_id); @@ -573,18 +559,13 @@ RawClosureData* ClosureData::ReadFrom(SnapshotReader* reader, intptr_t tags, Snapshot::Kind kind) { ASSERT(reader != NULL); - ASSERT(((kind == Snapshot::kScript) && - !RawObject::IsCreatedFromSnapshot(tags)) || - (kind == Snapshot::kFull)); + ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull)); // Allocate closure data object. ClosureData& data = ClosureData::ZoneHandle( reader->zone(), NEW_OBJECT(ClosureData)); reader->AddBackRef(object_id, &data, kIsDeserialized); - // Set the object tags. - data.set_tags(tags); - // Set all the object fields. // TODO(5411462): Need to assert No GC can happen here, even though // allocations may happen. @@ -601,9 +582,7 @@ void RawClosureData::WriteTo(SnapshotWriter* writer, intptr_t object_id, Snapshot::Kind kind) { ASSERT(writer != NULL); - ASSERT(((kind == Snapshot::kScript) && - !RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this))) || - (kind == Snapshot::kFull)); + ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull)); // Write out the serialization header value for this object. writer->WriteInlinedObjectHeader(object_id); @@ -633,18 +612,13 @@ RawRedirectionData* RedirectionData::ReadFrom(SnapshotReader* reader, intptr_t tags, Snapshot::Kind kind) { ASSERT(reader != NULL); - ASSERT(((kind == Snapshot::kScript) && - !RawObject::IsCreatedFromSnapshot(tags)) || - (kind == Snapshot::kFull)); + ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull)); // Allocate redirection data object. RedirectionData& data = RedirectionData::ZoneHandle( reader->zone(), NEW_OBJECT(RedirectionData)); reader->AddBackRef(object_id, &data, kIsDeserialized); - // Set the object tags. - data.set_tags(tags); - // Set all the object fields. // TODO(5411462): Need to assert No GC can happen here, even though // allocations may happen. @@ -665,9 +639,7 @@ void RawRedirectionData::WriteTo(SnapshotWriter* writer, intptr_t object_id, Snapshot::Kind kind) { ASSERT(writer != NULL); - ASSERT(((kind == Snapshot::kScript) && - !RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this))) || - (kind == Snapshot::kFull)); + ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull)); // Write out the serialization header value for this object. writer->WriteInlinedObjectHeader(object_id); @@ -687,18 +659,13 @@ RawFunction* Function::ReadFrom(SnapshotReader* reader, intptr_t tags, Snapshot::Kind kind) { ASSERT(reader != NULL); - ASSERT(((kind == Snapshot::kScript) && - !RawObject::IsCreatedFromSnapshot(tags)) || - (kind == Snapshot::kFull)); + ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull)); // Allocate function object. Function& func = Function::ZoneHandle( reader->zone(), NEW_OBJECT(Function)); reader->AddBackRef(object_id, &func, kIsDeserialized); - // Set the object tags. - func.set_tags(tags); - // Set all the non object fields. func.set_token_pos(reader->Read()); func.set_end_token_pos(reader->Read()); @@ -734,9 +701,7 @@ void RawFunction::WriteTo(SnapshotWriter* writer, intptr_t object_id, Snapshot::Kind kind) { ASSERT(writer != NULL); - ASSERT(((kind == Snapshot::kScript) && - !RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this))) || - (kind == Snapshot::kFull)); + ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull)); // Write out the serialization header value for this object. writer->WriteInlinedObjectHeader(object_id); @@ -768,17 +733,12 @@ RawField* Field::ReadFrom(SnapshotReader* reader, intptr_t tags, Snapshot::Kind kind) { ASSERT(reader != NULL); - ASSERT(((kind == Snapshot::kScript) && - !RawObject::IsCreatedFromSnapshot(tags)) || - (kind == Snapshot::kFull)); + ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull)); // Allocate field object. Field& field = Field::ZoneHandle(reader->zone(), NEW_OBJECT(Field)); reader->AddBackRef(object_id, &field, kIsDeserialized); - // Set the object tags. - field.set_tags(tags); - // Set all non object fields. field.set_token_pos(reader->Read()); field.set_guarded_cid(reader->Read()); @@ -807,9 +767,7 @@ void RawField::WriteTo(SnapshotWriter* writer, intptr_t object_id, Snapshot::Kind kind) { ASSERT(writer != NULL); - ASSERT(((kind == Snapshot::kScript) && - !RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this))) || - (kind == Snapshot::kFull)); + ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull)); // Write out the serialization header value for this object. writer->WriteInlinedObjectHeader(object_id); @@ -842,9 +800,6 @@ RawLiteralToken* LiteralToken::ReadFrom(SnapshotReader* reader, reader->zone(), NEW_OBJECT(LiteralToken)); reader->AddBackRef(object_id, &literal_token, kIsDeserialized); - // Set the object tags. - literal_token.set_tags(tags); - // Read the token attributes. Token::Kind token_kind = static_cast(reader->Read()); literal_token.set_kind(token_kind); @@ -890,9 +845,7 @@ RawTokenStream* TokenStream::ReadFrom(SnapshotReader* reader, intptr_t tags, Snapshot::Kind kind) { ASSERT(reader != NULL); - ASSERT(((kind == Snapshot::kScript) && - !RawObject::IsCreatedFromSnapshot(tags)) || - (kind == Snapshot::kFull)); + ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull)); // Read the length so that we can determine number of tokens to read. intptr_t len = reader->ReadSmiValue(); @@ -902,9 +855,6 @@ RawTokenStream* TokenStream::ReadFrom(SnapshotReader* reader, reader->zone(), NEW_OBJECT_WITH_LEN(TokenStream, len)); reader->AddBackRef(object_id, &token_stream, kIsDeserialized); - // Set the object tags. - token_stream.set_tags(tags); - // Read the stream of tokens into the TokenStream object for script // snapshots as we made a copy of token stream. if (kind == Snapshot::kScript) { @@ -928,9 +878,7 @@ void RawTokenStream::WriteTo(SnapshotWriter* writer, intptr_t object_id, Snapshot::Kind kind) { ASSERT(writer != NULL); - ASSERT(((kind == Snapshot::kScript) && - !RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this))) || - (kind == Snapshot::kFull)); + ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull)); // Write out the serialization header value for this object. writer->WriteInlinedObjectHeader(object_id); @@ -957,17 +905,12 @@ RawScript* Script::ReadFrom(SnapshotReader* reader, intptr_t tags, Snapshot::Kind kind) { ASSERT(reader != NULL); - ASSERT(((kind == Snapshot::kScript) && - !RawObject::IsCreatedFromSnapshot(tags)) || - (kind == Snapshot::kFull)); + ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull)); // Allocate script object. Script& script = Script::ZoneHandle(reader->zone(), NEW_OBJECT(Script)); reader->AddBackRef(object_id, &script, kIsDeserialized); - // Set the object tags. - script.set_tags(tags); - script.StoreNonPointer(&script.raw_ptr()->line_offset_, reader->Read()); script.StoreNonPointer(&script.raw_ptr()->col_offset_, @@ -997,9 +940,7 @@ void RawScript::WriteTo(SnapshotWriter* writer, Snapshot::Kind kind) { ASSERT(writer != NULL); ASSERT(tokens_ != TokenStream::null()); - ASSERT(((kind == Snapshot::kScript) && - !RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this))) || - (kind == Snapshot::kFull)); + ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull)); // Write out the serialization header value for this object. writer->WriteInlinedObjectHeader(object_id); @@ -1029,18 +970,16 @@ RawLibrary* Library::ReadFrom(SnapshotReader* reader, Library& library = Library::ZoneHandle(reader->zone(), Library::null()); reader->AddBackRef(object_id, &library, kIsDeserialized); - if ((kind == Snapshot::kScript) && RawObject::IsCreatedFromSnapshot(tags)) { - ASSERT(kind != Snapshot::kFull); + bool is_in_fullsnapshot = reader->Read(); + if ((kind == Snapshot::kScript) && is_in_fullsnapshot) { // Lookup the object as it should already exist in the heap. *reader->StringHandle() ^= reader->ReadObjectImpl(kAsInlinedObject); library = Library::LookupLibrary(*reader->StringHandle()); + ASSERT(library.is_in_fullsnapshot()); } else { // Allocate library object. library = NEW_OBJECT(Library); - // Set the object tags. - library.set_tags(tags); - // Set all non object fields. library.StoreNonPointer(&library.raw_ptr()->index_, reader->ReadClassIDValue()); @@ -1056,6 +995,11 @@ RawLibrary* Library::ReadFrom(SnapshotReader* reader, reader->Read()); library.StoreNonPointer(&library.raw_ptr()->debuggable_, reader->Read()); + if (kind == Snapshot::kFull) { + is_in_fullsnapshot = true; + } + library.StoreNonPointer(&library.raw_ptr()->is_in_fullsnapshot_, + is_in_fullsnapshot); // The native resolver and symbolizer are not serialized. library.set_native_entry_resolver(NULL); library.set_native_entry_symbol_resolver(NULL); @@ -1092,12 +1036,16 @@ void RawLibrary::WriteTo(SnapshotWriter* writer, writer->WriteVMIsolateObject(kLibraryCid); writer->WriteTags(writer->GetObjectTags(this)); - if ((kind == Snapshot::kScript) && - RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this))) { - ASSERT(kind != Snapshot::kFull); + // Write out the boolean is_in_fullsnapshot_ first as this will + // help the reader decide how the rest of the information needs + // to be interpreted. + writer->Write(ptr()->is_in_fullsnapshot_); + + if ((kind == Snapshot::kScript) && ptr()->is_in_fullsnapshot_) { // Write out library URL so that it can be looked up when reading. writer->WriteObjectImpl(ptr()->url_, kAsInlinedObject); } else { + ASSERT((kind == Snapshot::kFull) || !ptr()->is_in_fullsnapshot_); // Write out all non object fields. writer->WriteClassIDValue(ptr()->index_); writer->WriteClassIDValue(ptr()->num_anonymous_); @@ -1124,18 +1072,13 @@ RawLibraryPrefix* LibraryPrefix::ReadFrom(SnapshotReader* reader, intptr_t tags, Snapshot::Kind kind) { ASSERT(reader != NULL); - ASSERT(((kind == Snapshot::kScript) && - !RawObject::IsCreatedFromSnapshot(tags)) || - (kind == Snapshot::kFull)); + ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull)); // Allocate library prefix object. LibraryPrefix& prefix = LibraryPrefix::ZoneHandle( reader->zone(), NEW_OBJECT(LibraryPrefix)); reader->AddBackRef(object_id, &prefix, kIsDeserialized); - // Set the object tags. - prefix.set_tags(tags); - // Set all non object fields. prefix.StoreNonPointer(&prefix.raw_ptr()->num_imports_, reader->Read()); @@ -1161,9 +1104,7 @@ void RawLibraryPrefix::WriteTo(SnapshotWriter* writer, intptr_t object_id, Snapshot::Kind kind) { ASSERT(writer != NULL); - ASSERT(((kind == Snapshot::kScript) && - !RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this))) || - (kind == Snapshot::kFull)); + ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull)); // Write out the serialization header value for this object. writer->WriteInlinedObjectHeader(object_id); @@ -1188,18 +1129,13 @@ RawNamespace* Namespace::ReadFrom(SnapshotReader* reader, intptr_t tags, Snapshot::Kind kind) { ASSERT(reader != NULL); - ASSERT(((kind == Snapshot::kScript) && - !RawObject::IsCreatedFromSnapshot(tags)) || - (kind == Snapshot::kFull)); + ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull)); // Allocate Namespace object. Namespace& ns = Namespace::ZoneHandle( reader->zone(), NEW_OBJECT(Namespace)); reader->AddBackRef(object_id, &ns, kIsDeserialized); - // Set the object tags. - ns.set_tags(tags); - // Set all the object fields. // TODO(5411462): Need to assert No GC can happen here, even though // allocations may happen. @@ -1218,9 +1154,7 @@ void RawNamespace::WriteTo(SnapshotWriter* writer, intptr_t object_id, Snapshot::Kind kind) { ASSERT(writer != NULL); - ASSERT(((kind == Snapshot::kScript) && - !RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this))) || - (kind == Snapshot::kFull)); + ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull)); // Write out the serialization header value for this object. writer->WriteInlinedObjectHeader(object_id); @@ -1296,9 +1230,6 @@ RawPcDescriptors* PcDescriptors::ReadFrom(SnapshotReader* reader, PcDescriptors::New(length)); reader->AddBackRef(object_id, &result, kIsDeserialized); - // Set the object tags. - result.set_tags(tags); - if (result.Length() > 0) { NoSafepointScope no_safepoint; intptr_t len = result.Length(); @@ -1343,9 +1274,6 @@ RawStackmap* Stackmap::ReadFrom(SnapshotReader* reader, Stackmap::New(length, register_bit_count, pc_offset)); reader->AddBackRef(object_id, &result, kIsDeserialized); - // Set the object tags. - result.set_tags(tags); - if (result.Length() > 0) { NoSafepointScope no_safepoint; intptr_t len = (result.Length() + 7) / 8; @@ -1390,9 +1318,6 @@ RawLocalVarDescriptors* LocalVarDescriptors::ReadFrom(SnapshotReader* reader, LocalVarDescriptors::New(num_entries)); reader->AddBackRef(object_id, &result, kIsDeserialized); - // Set the object tags. - result.set_tags(tags); - for (intptr_t i = 0; i < num_entries; i++) { (*reader->StringHandle()) ^= reader->ReadObjectImpl(kAsReference); result.StorePointer(result.raw()->nameAddrAt(i), @@ -1446,9 +1371,6 @@ RawExceptionHandlers* ExceptionHandlers::ReadFrom(SnapshotReader* reader, ExceptionHandlers::New(*reader->ArrayHandle())); reader->AddBackRef(object_id, &result, kIsDeserialized); - // Set the object tags. - result.set_tags(tags); - if (result.num_entries() > 0) { NoSafepointScope no_safepoint; const intptr_t len = @@ -1496,9 +1418,6 @@ RawContext* Context::ReadFrom(SnapshotReader* reader, } else { context ^= NEW_OBJECT_WITH_LEN(Context, num_vars); - // Set the object tags. - context.set_tags(tags); - // Set all the object fields. // TODO(5411462): Need to assert No GC can happen here, even though // allocations may happen. @@ -1627,9 +1546,6 @@ RawApiError* ApiError::ReadFrom(SnapshotReader* reader, ApiError::ZoneHandle(reader->zone(), NEW_OBJECT(ApiError)); reader->AddBackRef(object_id, &api_error, kIsDeserialized); - // Set the object tags. - api_error.set_tags(tags); - // Set all the object fields. // TODO(5411462): Need to assert No GC can happen here, even though // allocations may happen. @@ -1673,9 +1589,6 @@ RawLanguageError* LanguageError::ReadFrom(SnapshotReader* reader, LanguageError::ZoneHandle(reader->zone(), NEW_OBJECT(LanguageError)); reader->AddBackRef(object_id, &language_error, kIsDeserialized); - // Set the object tags. - language_error.set_tags(tags); - // Set all non object fields. language_error.set_token_pos(reader->Read()); language_error.set_kind(reader->Read()); @@ -1725,9 +1638,6 @@ RawUnhandledException* UnhandledException::ReadFrom(SnapshotReader* reader, reader->zone(), NEW_OBJECT(UnhandledException)); reader->AddBackRef(object_id, &result, kIsDeserialized); - // Set the object tags. - result.set_tags(tags); - // Set all the object fields. // TODO(5411462): Need to assert No GC can happen here, even though // allocations may happen. @@ -1784,26 +1694,20 @@ RawInstance* Instance::ReadFrom(SnapshotReader* reader, Instance& obj = Instance::ZoneHandle(reader->zone(), Instance::null()); if (kind == Snapshot::kFull) { obj = reader->NewInstance(); + // Set the canonical bit. + if (RawObject::IsCanonical(tags)) { + obj.SetCanonical(); + } } else { obj ^= Object::Allocate(kInstanceCid, Instance::InstanceSize(), HEAP_SPACE(kind)); - // When reading a script snapshot we need to canonicalize only those object - // references that are objects from the core library (loaded from a - // full snapshot). Objects that are only in the script need not be - // canonicalized as they are already canonical. - // When reading a message snapshot we always have to canonicalize. - if (RawObject::IsCanonical(tags) && - (RawObject::IsCreatedFromSnapshot(tags) || - (kind == Snapshot::kMessage))) { + if (RawObject::IsCanonical(tags)) { obj = obj.CheckAndCanonicalize(NULL); } } reader->AddBackRef(object_id, &obj, kIsDeserialized); - // Set the object tags. - obj.set_tags(tags); - return obj.raw(); } @@ -1844,25 +1748,21 @@ RawInteger* Mint::ReadFrom(SnapshotReader* reader, Mint& mint = Mint::ZoneHandle(reader->zone(), Mint::null()); if (kind == Snapshot::kFull) { mint = reader->NewMint(value); - // Set the object tags. - mint.set_tags(tags); + // Set the canonical bit. + if (RawObject::IsCanonical(tags)) { + mint.SetCanonical(); + } } else { // When reading a script snapshot we need to canonicalize only those object // references that are objects from the core library (loaded from a // full snapshot). Objects that are only in the script need not be // canonicalized as they are already canonical. // When reading a message snapshot we always have to canonicalize. - if (RawObject::IsCanonical(tags) && - (RawObject::IsCreatedFromSnapshot(tags) || - (kind == Snapshot::kMessage))) { + if (RawObject::IsCanonical(tags)) { mint = Mint::NewCanonical(value); - ASSERT(mint.IsCanonical() && - (kind == Snapshot::kMessage || - RawObject::IsCreatedFromSnapshot(mint.raw()->ptr()->tags_))); + ASSERT(mint.IsCanonical()); } else { mint = Mint::New(value, HEAP_SPACE(kind)); - // Set the object tags. - mint.set_tags(tags); } } reader->AddBackRef(object_id, &mint, kIsDeserialized); @@ -1910,25 +1810,17 @@ RawBigint* Bigint::ReadFrom(SnapshotReader* reader, // If it is a canonical constant make it one. // When reading a full snapshot we don't need to canonicalize the object // as it would already be a canonical object. - // When reading a script snapshot we need to canonicalize only those object - // references that are objects from the core library (loaded from a - // full snapshot). Objects that are only in the script need not be - // canonicalized as they are already canonical. - // When reading a message snapshot we always have to canonicalize the object. - if (kind == Snapshot::kFull) { - // Set the object tags. - obj.set_tags(tags); - } else if (RawObject::IsCanonical(tags) && - (RawObject::IsCreatedFromSnapshot(tags) || - (kind == Snapshot::kMessage))) { - obj ^= obj.CheckAndCanonicalize(NULL); - ASSERT(!obj.IsNull()); - ASSERT(obj.IsCanonical() && - (kind == Snapshot::kMessage || - RawObject::IsCreatedFromSnapshot(obj.raw()->ptr()->tags_))); - } else { - // Set the object tags. - obj.set_tags(tags); + // When reading a script snapshot or a message snapshot we always have + // to canonicalize the object. + if (RawObject::IsCanonical(tags)) { + if (kind == Snapshot::kFull) { + // Set the canonical bit. + obj.SetCanonical(); + } else { + obj ^= obj.CheckAndCanonicalize(NULL); + ASSERT(!obj.IsNull()); + ASSERT(obj.IsCanonical()); + } } return obj.raw(); } @@ -1965,23 +1857,20 @@ RawDouble* Double::ReadFrom(SnapshotReader* reader, Double& dbl = Double::ZoneHandle(reader->zone(), Double::null()); if (kind == Snapshot::kFull) { dbl = reader->NewDouble(value); - // Set the object tags. - dbl.set_tags(tags); + // Set the canonical bit. + if (RawObject::IsCanonical(tags)) { + dbl.SetCanonical(); + } } else { // When reading a script snapshot we need to canonicalize only those object // references that are objects from the core library (loaded from a // full snapshot). Objects that are only in the script need not be // canonicalized as they are already canonical. - if (RawObject::IsCanonical(tags) && - RawObject::IsCreatedFromSnapshot(tags)) { + if (RawObject::IsCanonical(tags)) { dbl = Double::NewCanonical(value); - ASSERT(dbl.IsCanonical() && - (kind == Snapshot::kMessage || - RawObject::IsCreatedFromSnapshot(dbl.raw()->ptr()->tags_))); + ASSERT(dbl.IsCanonical()); } else { dbl = Double::New(value, HEAP_SPACE(kind)); - // Set the object tags. - dbl.set_tags(tags); } } reader->AddBackRef(object_id, &dbl, kIsDeserialized); @@ -2041,7 +1930,6 @@ void String::ReadFromImpl(SnapshotReader* reader, } else { // Set up the string object. *str_obj = StringType::New(len, HEAP_SPACE(kind)); - str_obj->set_tags(tags); str_obj->SetHash(0); // Will get computed when needed. if (len == 0) { return; @@ -2072,7 +1960,9 @@ RawOneByteString* OneByteString::ReadFrom(SnapshotReader* reader, ASSERT(Thread::Current()->no_safepoint_scope_depth() != 0); RawOneByteString* obj = reader->NewOneByteString(len); str_obj = obj; - str_obj.set_tags(tags); + if (RawObject::IsCanonical(tags)) { + str_obj.SetCanonical(); + } str_obj.SetHash(hash); if (len > 0) { uint8_t* raw_ptr = CharAddr(str_obj, 0); @@ -2101,7 +1991,9 @@ RawTwoByteString* TwoByteString::ReadFrom(SnapshotReader* reader, if (kind == Snapshot::kFull) { RawTwoByteString* obj = reader->NewTwoByteString(len); str_obj = obj; - str_obj.set_tags(tags); + if (RawObject::IsCanonical(tags)) { + str_obj.SetCanonical(); + } str_obj.SetHash(hash); NoSafepointScope no_safepoint; uint16_t* raw_ptr = (len > 0)? CharAddr(str_obj, 0) : NULL; @@ -2290,7 +2182,11 @@ RawImmutableArray* ImmutableArray::ReadFrom(SnapshotReader* reader, } reader->ArrayReadFrom(object_id, *array, len, tags); if (RawObject::IsCanonical(tags)) { - *array ^= array->CheckAndCanonicalize(NULL); + if (kind == Snapshot::kFull) { + array->SetCanonical(); + } else { + *array ^= array->CheckAndCanonicalize(NULL); + } } return raw(*array); } @@ -2396,8 +2292,6 @@ RawLinkedHashMap* LinkedHashMap::ReadFrom(SnapshotReader* reader, map = LinkedHashMap::NewUninitialized(HEAP_SPACE(kind)); } reader->AddBackRef(object_id, &map, kIsDeserialized); - // Set the object tags. - map.set_tags(tags); // Read the type arguments. const intptr_t typeargs_offset = @@ -2509,8 +2403,6 @@ RawFloat32x4* Float32x4::ReadFrom(SnapshotReader* reader, simd = Float32x4::New(value0, value1, value2, value3, HEAP_SPACE(kind)); } reader->AddBackRef(object_id, &simd, kIsDeserialized); - // Set the object tags. - simd.set_tags(tags); return simd.raw(); } @@ -2555,8 +2447,6 @@ RawInt32x4* Int32x4::ReadFrom(SnapshotReader* reader, simd = Int32x4::New(value0, value1, value2, value3, HEAP_SPACE(kind)); } reader->AddBackRef(object_id, &simd, kIsDeserialized); - // Set the object tags. - simd.set_tags(tags); return simd.raw(); } @@ -2599,8 +2489,6 @@ RawFloat64x2* Float64x2::ReadFrom(SnapshotReader* reader, simd = Float64x2::New(value0, value1, HEAP_SPACE(kind)); } reader->AddBackRef(object_id, &simd, kIsDeserialized); - // Set the object tags. - simd.set_tags(tags); return simd.raw(); } @@ -2642,9 +2530,6 @@ RawTypedData* TypedData::ReadFrom(SnapshotReader* reader, : TypedData::New(cid, len, HEAP_SPACE(kind))); reader->AddBackRef(object_id, &result, kIsDeserialized); - // Set the object tags. - result.set_tags(tags); - // Setup the array elements. intptr_t element_size = ElementSizeInBytes(cid); intptr_t length_in_bytes = len * element_size; @@ -2993,9 +2878,6 @@ RawJSRegExp* JSRegExp::ReadFrom(SnapshotReader* reader, reader->zone(), JSRegExp::New(HEAP_SPACE(kind))); reader->AddBackRef(object_id, ®ex, kIsDeserialized); - // Set the object tags. - regex.set_tags(tags); - // Read and Set all the other fields. regex.StoreSmi(®ex.raw_ptr()->num_bracket_expressions_, reader->ReadAsSmi()); @@ -3043,9 +2925,6 @@ RawWeakProperty* WeakProperty::ReadFrom(SnapshotReader* reader, reader->zone(), WeakProperty::New(HEAP_SPACE(kind))); reader->AddBackRef(object_id, &weak_property, kIsDeserialized); - // Set the object tags. - weak_property.set_tags(tags); - // Set all the object fields. // TODO(5411462): Need to assert No GC can happen here, even though // allocations may happen. diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc index b08e704d7b2..907e80577cd 100644 --- a/runtime/vm/snapshot.cc +++ b/runtime/vm/snapshot.cc @@ -325,6 +325,11 @@ RawObject* SnapshotReader::VmIsolateSnapshotObject(intptr_t index) const { } +bool SnapshotReader::is_vm_isolate() const { + return isolate_ == Dart::vm_isolate(); +} + + RawObject* SnapshotReader::ReadObjectImpl(bool as_reference, intptr_t patch_object_id, intptr_t patch_offset) { @@ -463,9 +468,6 @@ RawObject* SnapshotReader::ReadObjectRef(intptr_t object_id, #undef SNAPSHOT_READ default: UNREACHABLE(); break; } - if (kind_ == Snapshot::kFull) { - pobj_.SetCreatedFromSnapshot(); - } return pobj_.raw(); } @@ -536,10 +538,14 @@ RawObject* SnapshotReader::ReadInlinedObject(intptr_t object_id, result->SetFieldAtOffset(offset, Object::null_object()); offset += kWordSize; } - result->SetCreatedFromSnapshot(); - } else if (RawObject::IsCanonical(tags)) { - *result = result->CheckAndCanonicalize(NULL); - ASSERT(!result->IsNull()); + } + if (RawObject::IsCanonical(tags)) { + if (kind_ == Snapshot::kFull) { + result->SetCanonical(); + } else { + *result = result->CheckAndCanonicalize(NULL); + ASSERT(!result->IsNull()); + } } return result->raw(); } else if (header_id == kStaticImplicitClosureObjectId) { @@ -578,9 +584,6 @@ RawObject* SnapshotReader::ReadInlinedObject(intptr_t object_id, #undef SNAPSHOT_READ default: UNREACHABLE(); break; } - if (kind_ == Snapshot::kFull) { - pobj_.SetCreatedFromSnapshot(); - } AddPatchRecord(object_id, patch_object_id, patch_offset); return pobj_.raw(); } @@ -1071,6 +1074,7 @@ RawObject* SnapshotReader::AllocateUninitialized(intptr_t class_id, ASSERT(class_id != kIllegalCid); tags = RawObject::ClassIdTag::update(class_id, tags); tags = RawObject::SizeTag::update(size, tags); + tags = RawObject::VMHeapObjectTag::update(is_vm_isolate(), tags); raw_obj->ptr()->tags_ = tags; return raw_obj; } @@ -1209,9 +1213,6 @@ void SnapshotReader::ArrayReadFrom(intptr_t object_id, const Array& result, intptr_t len, intptr_t tags) { - // Set the object tags. - result.set_tags(tags); - // Setup the object fields. const intptr_t typeargs_offset = GrowableObjectArray::type_arguments_offset() / kWordSize; @@ -2053,11 +2054,6 @@ void SnapshotWriter::WriteClassId(RawClass* cls) { ASSERT(kind_ != Snapshot::kFull); int class_id = cls->ptr()->id_; ASSERT(!IsSingletonClassId(class_id) && !IsObjectStoreClassId(class_id)); - // TODO(5411462): Should restrict this to only core-lib classes in this - // case. - // Write out the class and tags information. - WriteVMIsolateObject(kClassCid); - WriteTags(GetObjectTags(cls)); // Write out the library url and class name. RawLibrary* library = cls->ptr()->library_; diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h index 161da597f27..4b3a2781882 100644 --- a/runtime/vm/snapshot.h +++ b/runtime/vm/snapshot.h @@ -450,6 +450,8 @@ class SnapshotReader : public BaseReader { RawObject* VmIsolateSnapshotObject(intptr_t index) const; + bool is_vm_isolate() const; + Snapshot::Kind kind_; // Indicates type of snapshot(full, script, message). Isolate* isolate_; // Current isolate. Zone* zone_; // Zone for allocations while reading snapshot. diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status index 41355d727ae..035100e4eff 100644 --- a/tests/isolate/isolate.status +++ b/tests/isolate/isolate.status @@ -18,9 +18,6 @@ ping_test: Skip # Resolve test issues ping_pause_test: Skip # Resolve test issues kill3_test: Pass, Fail # Bad test: expects total message order -message3_test/constList_identical: RuntimeError # Issue 21816 -message3_test/constMap: RuntimeError # Issue 21816 -message3_test/constInstance: RuntimeError # Issue 21816 message3_test/byteBuffer: Crash # Issue 21818 message3_test/int32x4: Crash # Issue 21818 diff --git a/tests/isolate/message3_test.dart b/tests/isolate/message3_test.dart index c07a7e68329..4267cee9be3 100644 --- a/tests/isolate/message3_test.dart +++ b/tests/isolate/message3_test.dart @@ -394,7 +394,7 @@ void runTests(SendPort ping, Queue checks) { Expect.equals("field", f.field); Expect.isFalse(identical(nonConstF, f)); }); - checks.add((x) { // g1. + checks.add((x) { // g2. Expect.isTrue(x is G); Expect.isFalse(identical(g1, x)); F f = x.field; @@ -403,7 +403,7 @@ void runTests(SendPort ping, Queue checks) { }); checks.add((x) { // g3. Expect.isTrue(x is G); - Expect.identical(g1, x); /// constInstance: continued + Expect.identical(g3, x); /// constInstance: continued F f = x.field; Expect.equals("field", f.field); Expect.identical(constF, f); /// constInstance: continued