| // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| #include "vm/bigint_operations.h" |
| #include "vm/object.h" |
| #include "vm/object_store.h" |
| #include "vm/snapshot.h" |
| #include "vm/symbols.h" |
| #include "vm/visitor.h" |
| |
| namespace dart { |
| |
| DECLARE_FLAG(bool, error_on_malformed_type); |
| |
| |
| #define NEW_OBJECT(type) \ |
| ((kind == Snapshot::kFull) ? reader->New##type() : type::New()) |
| |
| #define NEW_OBJECT_WITH_LEN(type, len) \ |
| ((kind == Snapshot::kFull) ? reader->New##type(len) : type::New(len)) |
| |
| #define NEW_OBJECT_WITH_LEN_SPACE(type, len, kind) \ |
| ((kind == Snapshot::kFull) ? \ |
| reader->New##type(len) : type::New(len, HEAP_SPACE(kind))) |
| |
| |
| static uword BigintAllocator(intptr_t size) { |
| Zone* zone = Isolate::Current()->current_zone(); |
| return zone->AllocUnsafe(size); |
| } |
| |
| |
| RawClass* Class::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| |
| Class& cls = Class::ZoneHandle(reader->isolate(), Class::null()); |
| if ((kind == Snapshot::kFull) || |
| (kind == Snapshot::kScript && !RawObject::IsCreatedFromSnapshot(tags))) { |
| // Read in the base information. |
| intptr_t class_id = reader->ReadIntptrValue(); |
| |
| // Allocate class object of specified kind. |
| if (kind == Snapshot::kFull) { |
| cls = reader->NewClass(class_id); |
| } else { |
| if (class_id < kNumPredefinedCids) { |
| ASSERT((class_id >= kInstanceCid) && (class_id <= kDartFunctionCid)); |
| cls = reader->isolate()->class_table()->At(class_id); |
| } else { |
| cls = New<Instance>(kIllegalCid); |
| } |
| } |
| reader->AddBackRef(object_id, &cls, kIsDeserialized); |
| |
| // Set the object tags. |
| cls.set_tags(tags); |
| |
| // Set all non object fields. |
| cls.set_instance_size_in_words(reader->ReadIntptrValue()); |
| cls.set_type_arguments_field_offset_in_words(reader->ReadIntptrValue()); |
| cls.set_next_field_offset_in_words(reader->ReadIntptrValue()); |
| cls.set_num_native_fields(reader->ReadIntptrValue()); |
| cls.set_token_pos(reader->ReadIntptrValue()); |
| cls.set_state_bits(reader->Read<uint8_t>()); |
| |
| // Set all the object fields. |
| // TODO(5411462): Need to assert No GC can happen here, even though |
| // allocations may happen. |
| intptr_t num_flds = (cls.raw()->to() - cls.raw()->from()); |
| for (intptr_t i = 0; i <= num_flds; i++) { |
| *(cls.raw()->from() + i) = reader->ReadObjectRef(); |
| } |
| } else { |
| cls ^= reader->ReadClassId(object_id); |
| } |
| return cls.raw(); |
| } |
| |
| |
| void RawClass::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| ASSERT(writer != NULL); |
| |
| // 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->WriteIntptrValue(writer->GetObjectTags(this)); |
| |
| // Write out all the non object pointer fields. |
| // NOTE: cpp_vtable_ is not written. |
| writer->WriteIntptrValue(ptr()->id_); |
| writer->WriteIntptrValue(ptr()->instance_size_in_words_); |
| writer->WriteIntptrValue(ptr()->type_arguments_field_offset_in_words_); |
| writer->WriteIntptrValue(ptr()->next_field_offset_in_words_); |
| writer->WriteIntptrValue(ptr()->num_native_fields_); |
| writer->WriteIntptrValue(ptr()->token_pos_); |
| writer->Write<uint8_t>(ptr()->state_bits_); |
| |
| // Write out all the object pointer fields. |
| SnapshotWriterVisitor visitor(writer); |
| visitor.VisitPointers(from(), to()); |
| } else { |
| writer->WriteClassId(this); |
| } |
| } |
| |
| |
| RawUnresolvedClass* UnresolvedClass::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| |
| // Allocate unresolved class object. |
| UnresolvedClass& unresolved_class = UnresolvedClass::ZoneHandle( |
| reader->isolate(), 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->ReadIntptrValue()); |
| |
| // Set all the object fields. |
| // TODO(5411462): Need to assert No GC can happen here, even though |
| // allocations may happen. |
| intptr_t num_flds = (unresolved_class.raw()->to() - |
| unresolved_class.raw()->from()); |
| for (intptr_t i = 0; i <= num_flds; i++) { |
| unresolved_class.StorePointer((unresolved_class.raw()->from() + i), |
| reader->ReadObjectRef()); |
| } |
| return unresolved_class.raw(); |
| } |
| |
| |
| void RawUnresolvedClass::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| ASSERT(writer != NULL); |
| |
| // Write out the serialization header value for this object. |
| writer->WriteInlinedObjectHeader(object_id); |
| |
| // Write out the class and tags information. |
| writer->WriteVMIsolateObject(kUnresolvedClassCid); |
| writer->WriteIntptrValue(writer->GetObjectTags(this)); |
| |
| // Write out all the non object pointer fields. |
| writer->WriteIntptrValue(ptr()->token_pos_); |
| |
| // Write out all the object pointer fields. |
| SnapshotWriterVisitor visitor(writer); |
| visitor.VisitPointers(from(), to()); |
| } |
| |
| |
| RawAbstractType* AbstractType::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); // AbstractType is an abstract class. |
| return NULL; |
| } |
| |
| |
| void RawAbstractType::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); // AbstractType is an abstract class. |
| } |
| |
| |
| RawType* Type::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| |
| // Allocate type object. |
| Type& type = Type::ZoneHandle(reader->isolate(), NEW_OBJECT(Type)); |
| reader->AddBackRef(object_id, &type, kIsDeserialized); |
| |
| // Set all non object fields. |
| type.set_token_pos(reader->ReadIntptrValue()); |
| type.set_type_state(reader->Read<int8_t>()); |
| |
| // Set all the object fields. |
| // TODO(5411462): Need to assert No GC can happen here, even though |
| // allocations may happen. |
| intptr_t num_flds = (type.raw()->to() - type.raw()->from()); |
| for (intptr_t i = 0; i <= num_flds; i++) { |
| type.StorePointer((type.raw()->from() + i), reader->ReadObjectRef()); |
| } |
| |
| // If object needs to be a canonical object, Canonicalize it. |
| // 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) && RawObject::IsCanonical(tags) && |
| (RawObject::IsCreatedFromSnapshot(tags) || |
| (kind == Snapshot::kMessage))) { |
| type ^= type.Canonicalize(); |
| } |
| |
| // Set the object tags (This is done after 'Canonicalize', which |
| // does not canonicalize a type already marked as canonical). |
| type.set_tags(tags); |
| |
| return type.raw(); |
| } |
| |
| |
| static const char* RawOneByteStringToCString(RawOneByteString* str) { |
| const char* start = reinterpret_cast<char*>(str) - kHeapObjectTag + |
| OneByteString::data_offset(); |
| const int len = Smi::Value(*reinterpret_cast<RawSmi**>( |
| reinterpret_cast<uword>(str) - kHeapObjectTag + String::length_offset())); |
| char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
| memmove(chars, start, len); |
| chars[len] = '\0'; |
| return chars; |
| } |
| |
| |
| void RawType::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| ASSERT(writer != NULL); |
| |
| // Only resolved and finalized types should be written to a snapshot. |
| // TODO(regis): Replace the test below by an ASSERT() or remove the flag test. |
| if (FLAG_error_on_malformed_type && |
| (ptr()->type_state_ != RawType::kFinalizedInstantiated) && |
| (ptr()->type_state_ != RawType::kFinalizedUninstantiated)) { |
| // Print the name of the class of the unfinalized type, as well as the |
| // token location from where it is referred to, making sure not |
| // to allocate any handles. Unfortunately, we cannot print the script name. |
| const intptr_t cid = ClassIdTag::decode(*reinterpret_cast<uword*>( |
| reinterpret_cast<uword>(ptr()->type_class_) - kHeapObjectTag + |
| Object::tags_offset())); |
| if (cid == kUnresolvedClassCid) { |
| OS::Print("Snapshotting unresolved type '%s' at token pos %"Pd"\n", |
| RawOneByteStringToCString( |
| reinterpret_cast<RawOneByteString*>( |
| reinterpret_cast<RawUnresolvedClass*>( |
| ptr()->type_class_)->ptr()->ident_)), |
| ptr()->token_pos_); |
| } else { |
| // Assume cid == kClassId, but it can also be kIllegalCid. |
| OS::Print("Snapshotting unfinalized type '%s' at token pos %"Pd"\n", |
| RawOneByteStringToCString( |
| reinterpret_cast<RawOneByteString*>( |
| reinterpret_cast<RawClass*>( |
| ptr()->type_class_)->ptr()->name_)), |
| ptr()->token_pos_); |
| } |
| UNREACHABLE(); |
| } |
| |
| // Write out the serialization header value for this object. |
| writer->WriteInlinedObjectHeader(object_id); |
| |
| // Write out the class and tags information. |
| writer->WriteIndexedObject(kTypeCid); |
| writer->WriteIntptrValue(writer->GetObjectTags(this)); |
| |
| // Write out all the non object pointer fields. |
| writer->WriteIntptrValue(ptr()->token_pos_); |
| writer->Write<int8_t>(ptr()->type_state_); |
| |
| // Write out all the object pointer fields. |
| SnapshotWriterVisitor visitor(writer); |
| visitor.VisitPointers(from(), to()); |
| } |
| |
| |
| RawTypeParameter* TypeParameter::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| |
| // Allocate type parameter object. |
| TypeParameter& type_parameter = TypeParameter::ZoneHandle( |
| reader->isolate(), 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_index(reader->ReadIntptrValue()); |
| type_parameter.set_token_pos(reader->ReadIntptrValue()); |
| type_parameter.set_type_state(reader->Read<int8_t>()); |
| |
| // Set all the object fields. |
| // TODO(5411462): Need to assert No GC can happen here, even though |
| // allocations may happen. |
| intptr_t num_flds = (type_parameter.raw()->to() - |
| type_parameter.raw()->from()); |
| for (intptr_t i = 0; i <= num_flds; i++) { |
| type_parameter.StorePointer((type_parameter.raw()->from() + i), |
| reader->ReadObjectRef()); |
| } |
| |
| return type_parameter.raw(); |
| } |
| |
| |
| void RawTypeParameter::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| ASSERT(writer != NULL); |
| |
| // Only finalized type parameters should be written to a snapshot. |
| // TODO(regis): Replace the test below by an ASSERT() or remove the flag test. |
| if (FLAG_error_on_malformed_type && |
| (ptr()->type_state_ != RawTypeParameter::kFinalizedUninstantiated)) { |
| // Print the name of the unfinalized type parameter, the name of the class |
| // it parameterizes, as well as the token location from where it is referred |
| // to, making sure not to allocate any handles. Unfortunately, we cannot |
| // print the script name. |
| OS::Print("Snapshotting unfinalized type parameter '%s' of class '%s' at " |
| "token pos %"Pd"\n", |
| RawOneByteStringToCString( |
| reinterpret_cast<RawOneByteString*>(ptr()->name_)), |
| RawOneByteStringToCString( |
| reinterpret_cast<RawOneByteString*>( |
| reinterpret_cast<RawClass*>( |
| ptr()->parameterized_class_)->ptr()->name_)), |
| ptr()->token_pos_); |
| UNREACHABLE(); |
| } |
| |
| // Write out the serialization header value for this object. |
| writer->WriteInlinedObjectHeader(object_id); |
| |
| // Write out the class and tags information. |
| writer->WriteIndexedObject(kTypeParameterCid); |
| writer->WriteIntptrValue(writer->GetObjectTags(this)); |
| |
| // Write out all the non object pointer fields. |
| writer->WriteIntptrValue(ptr()->index_); |
| writer->WriteIntptrValue(ptr()->token_pos_); |
| writer->Write<int8_t>(ptr()->type_state_); |
| |
| // Write out all the object pointer fields. |
| SnapshotWriterVisitor visitor(writer); |
| visitor.VisitPointers(from(), to()); |
| } |
| |
| |
| RawBoundedType* BoundedType::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| |
| // Allocate bounded type object. |
| BoundedType& bounded_type = BoundedType::ZoneHandle( |
| reader->isolate(), 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. |
| intptr_t num_flds = (bounded_type.raw()->to() - |
| bounded_type.raw()->from()); |
| for (intptr_t i = 0; i <= num_flds; i++) { |
| bounded_type.StorePointer((bounded_type.raw()->from() + i), |
| reader->ReadObjectRef()); |
| } |
| |
| bounded_type.set_is_being_checked(false); |
| |
| return bounded_type.raw(); |
| } |
| |
| |
| void RawBoundedType::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| ASSERT(writer != NULL); |
| |
| // Write out the serialization header value for this object. |
| writer->WriteInlinedObjectHeader(object_id); |
| |
| // Write out the class and tags information. |
| writer->WriteIndexedObject(kBoundedTypeCid); |
| writer->WriteIntptrValue(writer->GetObjectTags(this)); |
| |
| // Write out all the object pointer fields. |
| SnapshotWriterVisitor visitor(writer); |
| visitor.VisitPointers(from(), to()); |
| } |
| |
| |
| RawMixinAppType* MixinAppType::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); // MixinAppType objects do not survive finalization. |
| return MixinAppType::null(); |
| } |
| |
| |
| void RawMixinAppType::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); // MixinAppType objects do not survive finalization. |
| } |
| |
| |
| RawAbstractTypeArguments* AbstractTypeArguments::ReadFrom( |
| SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); // AbstractTypeArguments is an abstract class. |
| return TypeArguments::null(); |
| } |
| |
| |
| void RawAbstractTypeArguments::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); // AbstractTypeArguments is an abstract class. |
| } |
| |
| |
| RawTypeArguments* TypeArguments::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| |
| // Read the length so that we can determine instance size to allocate. |
| intptr_t len = reader->ReadSmiValue(); |
| |
| TypeArguments& type_arguments = TypeArguments::ZoneHandle( |
| reader->isolate(), NEW_OBJECT_WITH_LEN_SPACE(TypeArguments, len, kind)); |
| reader->AddBackRef(object_id, &type_arguments, kIsDeserialized); |
| |
| // Now set all the object fields. |
| for (intptr_t i = 0; i < len; i++) { |
| *reader->TypeHandle() ^= reader->ReadObjectImpl(); |
| type_arguments.SetTypeAt(i, *reader->TypeHandle()); |
| } |
| |
| // If object needs to be a canonical object, Canonicalize it. |
| // 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) && RawObject::IsCanonical(tags) && |
| (RawObject::IsCreatedFromSnapshot(tags) || |
| (kind == Snapshot::kMessage))) { |
| type_arguments ^= type_arguments.Canonicalize(); |
| } |
| |
| // Set the object tags (This is done after setting the object fields |
| // because 'SetTypeAt' has an assertion to check if the object is not |
| // already canonical. Also, this is done after 'Canonicalize', which |
| // does not canonicalize a type already marked as canonical). |
| type_arguments.set_tags(tags); |
| |
| return type_arguments.raw(); |
| } |
| |
| |
| void RawTypeArguments::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| ASSERT(writer != NULL); |
| |
| // Write out the serialization header value for this object. |
| writer->WriteInlinedObjectHeader(object_id); |
| |
| // Write out the class and tags information. |
| writer->WriteVMIsolateObject(kTypeArgumentsCid); |
| writer->WriteIntptrValue(writer->GetObjectTags(this)); |
| |
| // Write out the length field. |
| writer->Write<RawObject*>(ptr()->length_); |
| |
| // Write out the individual types. |
| intptr_t len = Smi::Value(ptr()->length_); |
| for (intptr_t i = 0; i < len; i++) { |
| writer->WriteObjectImpl(ptr()->types_[i]); |
| } |
| } |
| |
| |
| RawInstantiatedTypeArguments* InstantiatedTypeArguments::ReadFrom( |
| SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| ASSERT(kind == Snapshot::kMessage); |
| |
| // Allocate instantiated types object. |
| InstantiatedTypeArguments& instantiated_type_arguments = |
| InstantiatedTypeArguments::ZoneHandle(reader->isolate(), |
| InstantiatedTypeArguments::New()); |
| reader->AddBackRef(object_id, &instantiated_type_arguments, kIsDeserialized); |
| |
| // Set the object tags. |
| instantiated_type_arguments.set_tags(tags); |
| |
| // Set all the object fields. |
| // TODO(5411462): Need to assert No GC can happen here, even though |
| // allocations may happen. |
| intptr_t num_flds = (instantiated_type_arguments.raw()->to() - |
| instantiated_type_arguments.raw()->from()); |
| for (intptr_t i = 0; i <= num_flds; i++) { |
| instantiated_type_arguments.StorePointer( |
| (instantiated_type_arguments.raw()->from() + i), |
| reader->ReadObjectRef()); |
| } |
| return instantiated_type_arguments.raw(); |
| } |
| |
| |
| void RawInstantiatedTypeArguments::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| ASSERT(writer != NULL); |
| ASSERT(kind == Snapshot::kMessage); |
| |
| // Write out the serialization header value for this object. |
| writer->WriteInlinedObjectHeader(object_id); |
| |
| // Write out the class and tags information. |
| writer->WriteVMIsolateObject(kInstantiatedTypeArgumentsCid); |
| writer->WriteIntptrValue(writer->GetObjectTags(this)); |
| |
| // Write out all the object pointer fields. |
| SnapshotWriterVisitor visitor(writer); |
| visitor.VisitPointers(from(), to()); |
| } |
| |
| |
| RawPatchClass* PatchClass::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| ASSERT((kind != Snapshot::kMessage) && |
| !RawObject::IsCreatedFromSnapshot(tags)); |
| |
| // Allocate function object. |
| PatchClass& cls = PatchClass::ZoneHandle(reader->isolate(), |
| 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. |
| intptr_t num_flds = (cls.raw()->to() - cls.raw()->from()); |
| for (intptr_t i = 0; i <= num_flds; i++) { |
| *(cls.raw()->from() + i) = reader->ReadObjectRef(); |
| } |
| |
| return cls.raw(); |
| } |
| |
| |
| void RawPatchClass::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| ASSERT(writer != NULL); |
| ASSERT((kind != Snapshot::kMessage) && |
| !RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this))); |
| |
| // Write out the serialization header value for this object. |
| writer->WriteInlinedObjectHeader(object_id); |
| |
| // Write out the class and tags information. |
| writer->WriteVMIsolateObject(kPatchClassCid); |
| writer->WriteIntptrValue(writer->GetObjectTags(this)); |
| // Write out all the object pointer fields. |
| SnapshotWriterVisitor visitor(writer); |
| visitor.VisitPointers(from(), to()); |
| } |
| |
| |
| RawClosureData* ClosureData::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| ASSERT((kind != Snapshot::kMessage) && |
| !RawObject::IsCreatedFromSnapshot(tags)); |
| |
| // Allocate closure data object. |
| ClosureData& data = ClosureData::ZoneHandle( |
| reader->isolate(), 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. |
| intptr_t num_flds = (data.raw()->to() - data.raw()->from()); |
| for (intptr_t i = 0; i <= num_flds; i++) { |
| *(data.raw()->from() + i) = reader->ReadObjectRef(); |
| } |
| |
| return data.raw(); |
| } |
| |
| |
| void RawClosureData::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| ASSERT(writer != NULL); |
| ASSERT((kind != Snapshot::kMessage) && |
| !RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this))); |
| |
| // Write out the serialization header value for this object. |
| writer->WriteInlinedObjectHeader(object_id); |
| |
| // Write out the class and tags information. |
| writer->WriteVMIsolateObject(kClosureDataCid); |
| writer->WriteIntptrValue(writer->GetObjectTags(this)); |
| |
| // Context scope. |
| // We don't write the context scope in the snapshot. |
| writer->WriteObjectImpl(Object::null()); |
| |
| // Parent function. |
| writer->WriteObjectImpl(ptr()->parent_function_); |
| |
| // Signature class. |
| writer->WriteObjectImpl(ptr()->signature_class_); |
| |
| // Static closure/Closure allocation stub. |
| // We don't write the closure or allocation stub in the snapshot. |
| writer->WriteObjectImpl(Object::null()); |
| } |
| |
| |
| RawRedirectionData* RedirectionData::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| ASSERT((kind != Snapshot::kMessage) && |
| !RawObject::IsCreatedFromSnapshot(tags)); |
| |
| // Allocate redirection data object. |
| RedirectionData& data = RedirectionData::ZoneHandle( |
| reader->isolate(), 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. |
| intptr_t num_flds = (data.raw()->to() - data.raw()->from()); |
| for (intptr_t i = 0; i <= num_flds; i++) { |
| *(data.raw()->from() + i) = reader->ReadObjectRef(); |
| } |
| |
| return data.raw(); |
| } |
| |
| |
| void RawRedirectionData::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| ASSERT(writer != NULL); |
| ASSERT((kind != Snapshot::kMessage) && |
| !RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this))); |
| |
| // Write out the serialization header value for this object. |
| writer->WriteInlinedObjectHeader(object_id); |
| |
| // Write out the class and tags information. |
| writer->WriteVMIsolateObject(kRedirectionDataCid); |
| writer->WriteIntptrValue(writer->GetObjectTags(this)); |
| |
| // Write out all the object pointer fields. |
| SnapshotWriterVisitor visitor(writer); |
| visitor.VisitPointers(from(), to()); |
| } |
| |
| |
| RawFunction* Function::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| ASSERT((kind != Snapshot::kMessage) && |
| !RawObject::IsCreatedFromSnapshot(tags)); |
| |
| // Allocate function object. |
| Function& func = Function::ZoneHandle( |
| reader->isolate(), 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->ReadIntptrValue()); |
| func.set_end_token_pos(reader->ReadIntptrValue()); |
| func.set_usage_counter(reader->ReadIntptrValue()); |
| func.set_num_fixed_parameters(reader->ReadIntptrValue()); |
| func.set_num_optional_parameters(reader->ReadIntptrValue()); |
| func.set_deoptimization_counter(reader->ReadIntptrValue()); |
| func.set_kind_tag(reader->Read<uint16_t>()); |
| func.set_optimized_instruction_count(reader->Read<uint16_t>()); |
| func.set_optimized_call_site_count(reader->Read<uint16_t>()); |
| |
| // Set all the object fields. |
| // TODO(5411462): Need to assert No GC can happen here, even though |
| // allocations may happen. |
| intptr_t num_flds = (func.raw()->to() - func.raw()->from()); |
| for (intptr_t i = 0; i <= num_flds; i++) { |
| *(func.raw()->from() + i) = reader->ReadObjectRef(); |
| } |
| |
| return func.raw(); |
| } |
| |
| |
| void RawFunction::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| ASSERT(writer != NULL); |
| ASSERT((kind != Snapshot::kMessage) && |
| !RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this))); |
| |
| // Write out the serialization header value for this object. |
| writer->WriteInlinedObjectHeader(object_id); |
| |
| // Write out the class and tags information. |
| writer->WriteVMIsolateObject(kFunctionCid); |
| writer->WriteIntptrValue(writer->GetObjectTags(this)); |
| |
| // Write out all the non object fields. |
| writer->WriteIntptrValue(ptr()->token_pos_); |
| writer->WriteIntptrValue(ptr()->end_token_pos_); |
| writer->WriteIntptrValue(ptr()->usage_counter_); |
| writer->WriteIntptrValue(ptr()->num_fixed_parameters_); |
| writer->WriteIntptrValue(ptr()->num_optional_parameters_); |
| writer->WriteIntptrValue(ptr()->deoptimization_counter_); |
| writer->Write<uint16_t>(ptr()->kind_tag_); |
| writer->Write<uint16_t>(ptr()->optimized_instruction_count_); |
| writer->Write<uint16_t>(ptr()->optimized_call_site_count_); |
| |
| // Write out all the object pointer fields. |
| SnapshotWriterVisitor visitor(writer); |
| visitor.VisitPointers(from(), to()); |
| } |
| |
| |
| RawField* Field::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| ASSERT((kind != Snapshot::kMessage) && |
| !RawObject::IsCreatedFromSnapshot(tags)); |
| |
| // Allocate field object. |
| Field& field = Field::ZoneHandle(reader->isolate(), 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->ReadIntptrValue()); |
| field.set_guarded_cid(reader->ReadIntptrValue()); |
| field.set_is_nullable(reader->ReadIntptrValue()); |
| field.set_kind_bits(reader->Read<uint8_t>()); |
| |
| // Set all the object fields. |
| // TODO(5411462): Need to assert No GC can happen here, even though |
| // allocations may happen. |
| intptr_t num_flds = (field.raw()->to() - field.raw()->from()); |
| for (intptr_t i = 0; i <= num_flds; i++) { |
| *(field.raw()->from() + i) = reader->ReadObjectRef(); |
| } |
| |
| return field.raw(); |
| } |
| |
| |
| void RawField::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| ASSERT(writer != NULL); |
| ASSERT((kind != Snapshot::kMessage) && |
| !RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this))); |
| |
| // Write out the serialization header value for this object. |
| writer->WriteInlinedObjectHeader(object_id); |
| |
| // Write out the class and tags information. |
| writer->WriteVMIsolateObject(kFieldCid); |
| writer->WriteIntptrValue(writer->GetObjectTags(this)); |
| |
| // Write out all the non object fields. |
| writer->WriteIntptrValue(ptr()->token_pos_); |
| writer->WriteIntptrValue(ptr()->guarded_cid_); |
| writer->WriteIntptrValue(ptr()->is_nullable_); |
| writer->Write<uint8_t>(ptr()->kind_bits_); |
| |
| // Write out all the object pointer fields. |
| SnapshotWriterVisitor visitor(writer); |
| visitor.VisitPointers(from(), to()); |
| } |
| |
| |
| RawLiteralToken* LiteralToken::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| ASSERT(kind != Snapshot::kMessage); |
| |
| // Create the literal token object. |
| LiteralToken& literal_token = LiteralToken::ZoneHandle( |
| reader->isolate(), 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<Token::Kind>(reader->ReadIntptrValue()); |
| literal_token.set_kind(token_kind); |
| *reader->StringHandle() ^= reader->ReadObjectImpl(); |
| literal_token.set_literal(*reader->StringHandle()); |
| *reader->ObjectHandle() = reader->ReadObjectImpl(); |
| literal_token.set_value(*reader->ObjectHandle()); |
| |
| return literal_token.raw(); |
| } |
| |
| |
| void RawLiteralToken::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| ASSERT(writer != NULL); |
| ASSERT(kind != Snapshot::kMessage); |
| |
| // Write out the serialization header value for this object. |
| writer->WriteInlinedObjectHeader(object_id); |
| |
| // Write out the class and tags information. |
| writer->WriteVMIsolateObject(kLiteralTokenCid); |
| writer->WriteIntptrValue(writer->GetObjectTags(this)); |
| |
| // Write out the kind field. |
| writer->Write<intptr_t>(ptr()->kind_); |
| |
| // Write out literal and value fields. |
| writer->WriteObjectImpl(ptr()->literal_); |
| writer->WriteObjectImpl(ptr()->value_); |
| } |
| |
| |
| RawTokenStream* TokenStream::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| ASSERT((kind != Snapshot::kMessage) |
| && !RawObject::IsCreatedFromSnapshot(tags)); |
| |
| // Read the length so that we can determine number of tokens to read. |
| intptr_t len = reader->ReadSmiValue(); |
| |
| // Create the token stream object. |
| TokenStream& token_stream = TokenStream::ZoneHandle( |
| reader->isolate(), 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) { |
| NoGCScope no_gc; |
| RawExternalTypedData* stream = token_stream.GetStream(); |
| reader->ReadBytes(stream->ptr()->data_, len); |
| } |
| |
| // Read in the literal/identifier token array. |
| *(reader->TokensHandle()) ^= reader->ReadObjectImpl(); |
| token_stream.SetTokenObjects(*(reader->TokensHandle())); |
| // Read in the private key in use by the token stream. |
| *(reader->StringHandle()) ^= reader->ReadObjectImpl(); |
| token_stream.SetPrivateKey(*(reader->StringHandle())); |
| |
| return token_stream.raw(); |
| } |
| |
| |
| void RawTokenStream::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| ASSERT(writer != NULL); |
| ASSERT((kind != Snapshot::kMessage) && |
| !RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this))); |
| |
| // Write out the serialization header value for this object. |
| writer->WriteInlinedObjectHeader(object_id); |
| |
| // Write out the class and tags information. |
| writer->WriteVMIsolateObject(kTokenStreamCid); |
| writer->WriteIntptrValue(writer->GetObjectTags(this)); |
| |
| // Write out the length field and the token stream. |
| RawExternalTypedData* stream = ptr()->stream_; |
| intptr_t len = Smi::Value(stream->ptr()->length_); |
| writer->Write<RawObject*>(stream->ptr()->length_); |
| writer->WriteBytes(stream->ptr()->data_, len); |
| |
| // Write out the literal/identifier token array. |
| writer->WriteObjectImpl(ptr()->token_objects_); |
| // Write out the private key in use by the token stream. |
| writer->WriteObjectImpl(ptr()->private_key_); |
| } |
| |
| |
| RawScript* Script::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| ASSERT((kind != Snapshot::kMessage) && |
| !RawObject::IsCreatedFromSnapshot(tags)); |
| |
| // Allocate script object. |
| Script& script = Script::ZoneHandle(reader->isolate(), NEW_OBJECT(Script)); |
| reader->AddBackRef(object_id, &script, kIsDeserialized); |
| |
| // Set the object tags. |
| script.set_tags(tags); |
| |
| // Set all the object fields. |
| // TODO(5411462): Need to assert No GC can happen here, even though |
| // allocations may happen. |
| *reader->StringHandle() ^= reader->ReadObjectImpl(); |
| script.set_url(*reader->StringHandle()); |
| *reader->StringHandle() ^= String::null(); |
| script.set_source(*reader->StringHandle()); |
| TokenStream& stream = TokenStream::Handle(); |
| stream ^= reader->ReadObjectImpl(); |
| script.set_tokens(stream); |
| |
| script.raw_ptr()->line_offset_ = reader->Read<int32_t>(); |
| script.raw_ptr()->col_offset_ = reader->Read<int32_t>(); |
| script.raw_ptr()->kind_ = reader->Read<int8_t>(); |
| |
| return script.raw(); |
| } |
| |
| |
| void RawScript::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| ASSERT(writer != NULL); |
| ASSERT(tokens_ != TokenStream::null()); |
| ASSERT((kind != Snapshot::kMessage) && |
| !RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this))); |
| |
| // Write out the serialization header value for this object. |
| writer->WriteInlinedObjectHeader(object_id); |
| |
| // Write out the class and tags information. |
| writer->WriteVMIsolateObject(kScriptCid); |
| writer->WriteIntptrValue(writer->GetObjectTags(this)); |
| |
| // Write out all the object pointer fields. |
| writer->WriteObjectImpl(ptr()->url_); |
| writer->WriteObjectImpl(ptr()->tokens_); |
| |
| writer->Write<int32_t>(ptr()->line_offset_); |
| writer->Write<int32_t>(ptr()->col_offset_); |
| writer->Write<int8_t>(ptr()->kind_); |
| } |
| |
| |
| RawLibrary* Library::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| ASSERT(kind != Snapshot::kMessage); |
| |
| Library& library = Library::ZoneHandle(reader->isolate(), Library::null()); |
| reader->AddBackRef(object_id, &library, kIsDeserialized); |
| |
| if (RawObject::IsCreatedFromSnapshot(tags)) { |
| ASSERT(kind != Snapshot::kFull); |
| // Lookup the object as it should already exist in the heap. |
| *reader->StringHandle() ^= reader->ReadObjectImpl(); |
| library = Library::LookupLibrary(*reader->StringHandle()); |
| } else { |
| // Allocate library object. |
| library = NEW_OBJECT(Library); |
| |
| // Set the object tags. |
| library.set_tags(tags); |
| |
| // Set all non object fields. |
| library.raw_ptr()->index_ = reader->ReadIntptrValue(); |
| library.raw_ptr()->num_imports_ = reader->ReadIntptrValue(); |
| library.raw_ptr()->num_anonymous_ = reader->ReadIntptrValue(); |
| library.raw_ptr()->corelib_imported_ = reader->Read<bool>(); |
| library.raw_ptr()->debuggable_ = reader->Read<bool>(); |
| library.raw_ptr()->load_state_ = reader->Read<int8_t>(); |
| // The native resolver is not serialized. |
| Dart_NativeEntryResolver resolver = |
| reader->Read<Dart_NativeEntryResolver>(); |
| ASSERT(resolver == NULL); |
| library.set_native_entry_resolver(resolver); |
| // The cache of loaded scripts is not serialized. |
| library.raw_ptr()->loaded_scripts_ = Array::null(); |
| |
| // Set all the object fields. |
| // TODO(5411462): Need to assert No GC can happen here, even though |
| // allocations may happen. |
| intptr_t num_flds = (library.raw()->to() - library.raw()->from()); |
| for (intptr_t i = 0; i <= num_flds; i++) { |
| *(library.raw()->from() + i) = reader->ReadObjectRef(); |
| } |
| if (kind != Snapshot::kFull) { |
| library.Register(); |
| } |
| } |
| return library.raw(); |
| } |
| |
| |
| void RawLibrary::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| ASSERT(writer != NULL); |
| ASSERT(kind != Snapshot::kMessage); |
| |
| // Write out the serialization header value for this object. |
| writer->WriteInlinedObjectHeader(object_id); |
| |
| // Write out the class and tags information. |
| writer->WriteVMIsolateObject(kLibraryCid); |
| writer->WriteIntptrValue(writer->GetObjectTags(this)); |
| |
| if (RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this))) { |
| ASSERT(kind != Snapshot::kFull); |
| // Write out library URL so that it can be looked up when reading. |
| writer->WriteObjectImpl(ptr()->url_); |
| } else { |
| // Write out all non object fields. |
| writer->WriteIntptrValue(ptr()->index_); |
| writer->WriteIntptrValue(ptr()->num_imports_); |
| writer->WriteIntptrValue(ptr()->num_anonymous_); |
| writer->Write<bool>(ptr()->corelib_imported_); |
| writer->Write<bool>(ptr()->debuggable_); |
| writer->Write<int8_t>(ptr()->load_state_); |
| // We do not serialize the native resolver over, this needs to be explicitly |
| // set after deserialization. |
| writer->Write<Dart_NativeEntryResolver>(NULL); |
| // We do not write the loaded_scripts_ cache to the snapshot. It gets |
| // set to NULL when reading the library from the snapshot, and will |
| // be rebuilt lazily. |
| |
| // Write out all the object pointer fields. |
| SnapshotWriterVisitor visitor(writer); |
| visitor.VisitPointers(from(), to()); |
| } |
| } |
| |
| |
| RawLibraryPrefix* LibraryPrefix::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| ASSERT((kind != Snapshot::kMessage) && |
| !RawObject::IsCreatedFromSnapshot(tags)); |
| |
| // Allocate library prefix object. |
| LibraryPrefix& prefix = LibraryPrefix::ZoneHandle( |
| reader->isolate(), NEW_OBJECT(LibraryPrefix)); |
| reader->AddBackRef(object_id, &prefix, kIsDeserialized); |
| |
| // Set the object tags. |
| prefix.set_tags(tags); |
| |
| // Set all non object fields. |
| prefix.raw_ptr()->num_imports_ = reader->ReadIntptrValue(); |
| |
| // Set all the object fields. |
| // TODO(5411462): Need to assert No GC can happen here, even though |
| // allocations may happen. |
| intptr_t num_flds = (prefix.raw()->to() - prefix.raw()->from()); |
| for (intptr_t i = 0; i <= num_flds; i++) { |
| *(prefix.raw()->from() + i) = reader->ReadObjectRef(); |
| } |
| |
| return prefix.raw(); |
| } |
| |
| |
| void RawLibraryPrefix::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| ASSERT(writer != NULL); |
| ASSERT((kind != Snapshot::kMessage) && |
| !RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this))); |
| |
| // Write out the serialization header value for this object. |
| writer->WriteInlinedObjectHeader(object_id); |
| |
| // Write out the class and tags information. |
| writer->WriteVMIsolateObject(kLibraryPrefixCid); |
| writer->WriteIntptrValue(writer->GetObjectTags(this)); |
| |
| // Write out all non object fields. |
| writer->WriteIntptrValue(ptr()->num_imports_); |
| |
| // Write out all the object pointer fields. |
| SnapshotWriterVisitor visitor(writer); |
| visitor.VisitPointers(from(), to()); |
| } |
| |
| |
| RawNamespace* Namespace::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| ASSERT((kind != Snapshot::kMessage) && |
| !RawObject::IsCreatedFromSnapshot(tags)); |
| |
| // Allocate Namespace object. |
| Namespace& ns = Namespace::ZoneHandle( |
| reader->isolate(), 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. |
| intptr_t num_flds = (ns.raw()->to() - ns.raw()->from()); |
| for (intptr_t i = 0; i <= num_flds; i++) { |
| *(ns.raw()->from() + i) = reader->ReadObjectRef(); |
| } |
| |
| return ns.raw(); |
| } |
| |
| |
| void RawNamespace::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| ASSERT(writer != NULL); |
| ASSERT((kind != Snapshot::kMessage) && |
| !RawObject::IsCreatedFromSnapshot(writer->GetObjectTags(this))); |
| |
| // Write out the serialization header value for this object. |
| writer->WriteInlinedObjectHeader(object_id); |
| |
| // Write out the class and tags information. |
| writer->WriteVMIsolateObject(kNamespaceCid); |
| writer->WriteIntptrValue(writer->GetObjectTags(this)); |
| |
| // Write out all the object pointer fields. |
| SnapshotWriterVisitor visitor(writer); |
| visitor.VisitPointers(from(), to()); |
| } |
| |
| |
| RawCode* Code::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); |
| return Code::null(); |
| } |
| |
| |
| void RawCode::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| // We have already checked for this and written a NULL object, hence we |
| // should not reach here. |
| UNREACHABLE(); |
| } |
| |
| |
| RawInstructions* Instructions::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); |
| return Instructions::null(); |
| } |
| |
| |
| void RawInstructions::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); |
| } |
| |
| |
| RawPcDescriptors* PcDescriptors::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); |
| return PcDescriptors::null(); |
| } |
| |
| |
| void RawPcDescriptors::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); |
| } |
| |
| |
| RawStackmap* Stackmap::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); |
| return Stackmap::null(); |
| } |
| |
| |
| void RawStackmap::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); |
| } |
| |
| |
| RawLocalVarDescriptors* LocalVarDescriptors::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); |
| return LocalVarDescriptors::null(); |
| } |
| |
| |
| void RawLocalVarDescriptors::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); |
| } |
| |
| |
| RawExceptionHandlers* ExceptionHandlers::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); |
| return ExceptionHandlers::null(); |
| } |
| |
| |
| void RawExceptionHandlers::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); |
| } |
| |
| |
| RawDeoptInfo* DeoptInfo::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); |
| return DeoptInfo::null(); |
| } |
| |
| |
| void RawDeoptInfo::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); |
| } |
| |
| |
| RawContext* Context::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| |
| // Allocate context object. |
| intptr_t num_vars = reader->ReadIntptrValue(); |
| Context& context = Context::ZoneHandle(reader->isolate(), Context::null()); |
| if (kind == Snapshot::kFull) { |
| context = reader->NewContext(num_vars); |
| } else { |
| context = Context::New(num_vars, HEAP_SPACE(kind)); |
| } |
| reader->AddBackRef(object_id, &context, kIsDeserialized); |
| |
| // Set the object tags. |
| context.set_tags(tags); |
| |
| // Set the isolate implicitly. |
| context.set_isolate(Isolate::Current()); |
| |
| // Set all the object fields. |
| // TODO(5411462): Need to assert No GC can happen here, even though |
| // allocations may happen. |
| intptr_t num_flds = (context.raw()->to(num_vars) - context.raw()->from()); |
| for (intptr_t i = 0; i <= num_flds; i++) { |
| context.StorePointer((context.raw()->from() + i), reader->ReadObjectRef()); |
| } |
| |
| return context.raw(); |
| } |
| |
| |
| void RawContext::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| ASSERT(writer != NULL); |
| |
| // Write out the serialization header value for this object. |
| writer->WriteInlinedObjectHeader(object_id); |
| |
| // Write out the class and tags information. |
| writer->WriteVMIsolateObject(kContextCid); |
| writer->WriteIntptrValue(writer->GetObjectTags(this)); |
| |
| // Write out num of variables in the context. |
| writer->WriteIntptrValue(ptr()->num_variables_); |
| |
| // Can't serialize the isolate pointer, we set it implicitly on read. |
| |
| // Write out all the object pointer fields. |
| SnapshotWriterVisitor visitor(writer); |
| visitor.VisitPointers(from(), to(ptr()->num_variables_)); |
| } |
| |
| |
| RawContextScope* ContextScope::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); |
| return NULL; |
| } |
| |
| |
| void RawContextScope::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); |
| } |
| |
| |
| RawICData* ICData::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); |
| return NULL; |
| } |
| |
| |
| void RawICData::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); |
| } |
| |
| |
| RawMegamorphicCache* MegamorphicCache::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); |
| return NULL; |
| } |
| |
| |
| void RawMegamorphicCache::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); |
| } |
| |
| |
| RawSubtypeTestCache* SubtypeTestCache::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); |
| return NULL; |
| } |
| |
| |
| void RawSubtypeTestCache::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); |
| } |
| |
| |
| RawError* Error::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); |
| return Error::null(); // Error is an abstract class. |
| } |
| |
| |
| void RawError::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); // Error is an abstract class. |
| } |
| |
| |
| RawApiError* ApiError::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| |
| // Allocate ApiError object. |
| ApiError& api_error = |
| ApiError::ZoneHandle(reader->isolate(), 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. |
| intptr_t num_flds = (api_error.raw()->to() - api_error.raw()->from()); |
| for (intptr_t i = 0; i <= num_flds; i++) { |
| api_error.StorePointer((api_error.raw()->from() + i), |
| reader->ReadObjectRef()); |
| } |
| |
| return api_error.raw(); |
| } |
| |
| |
| void RawApiError::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| ASSERT(writer != NULL); |
| |
| // Write out the serialization header value for this object. |
| writer->WriteInlinedObjectHeader(object_id); |
| |
| // Write out the class and tags information. |
| writer->WriteVMIsolateObject(kApiErrorCid); |
| writer->WriteIntptrValue(writer->GetObjectTags(this)); |
| |
| // Write out all the object pointer fields. |
| SnapshotWriterVisitor visitor(writer); |
| visitor.VisitPointers(from(), to()); |
| } |
| |
| |
| RawLanguageError* LanguageError::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| |
| // Allocate LanguageError object. |
| LanguageError& language_error = |
| LanguageError::ZoneHandle(reader->isolate(), NEW_OBJECT(LanguageError)); |
| reader->AddBackRef(object_id, &language_error, kIsDeserialized); |
| |
| // Set the object tags. |
| language_error.set_tags(tags); |
| |
| // Set all the object fields. |
| // TODO(5411462): Need to assert No GC can happen here, even though |
| // allocations may happen. |
| intptr_t num_flds = |
| (language_error.raw()->to() - language_error.raw()->from()); |
| for (intptr_t i = 0; i <= num_flds; i++) { |
| language_error.StorePointer((language_error.raw()->from() + i), |
| reader->ReadObjectRef()); |
| } |
| |
| return language_error.raw(); |
| } |
| |
| |
| void RawLanguageError::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| ASSERT(writer != NULL); |
| |
| // Write out the serialization header value for this object. |
| writer->WriteInlinedObjectHeader(object_id); |
| |
| // Write out the class and tags information. |
| writer->WriteVMIsolateObject(kLanguageErrorCid); |
| writer->WriteIntptrValue(writer->GetObjectTags(this)); |
| |
| // Write out all the object pointer fields. |
| SnapshotWriterVisitor visitor(writer); |
| visitor.VisitPointers(from(), to()); |
| } |
| |
| |
| RawUnhandledException* UnhandledException::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); |
| return UnhandledException::null(); |
| } |
| |
| |
| void RawUnhandledException::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); |
| } |
| |
| |
| RawUnwindError* UnwindError::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); |
| return UnwindError::null(); |
| } |
| |
| |
| void RawUnwindError::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); |
| } |
| |
| |
| RawInstance* Instance::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); |
| return Instance::null(); |
| } |
| |
| |
| void RawInstance::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); |
| } |
| |
| |
| RawMint* Mint::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| |
| // Read the 64 bit value for the object. |
| int64_t value = reader->Read<int64_t>(); |
| |
| // Create a Mint object or get canonical one if it is a canonical constant. |
| Mint& mint = Mint::ZoneHandle(reader->isolate(), Mint::null()); |
| if (kind == Snapshot::kFull) { |
| mint = reader->NewMint(value); |
| } 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))) { |
| mint = Mint::NewCanonical(value); |
| } else { |
| mint = Mint::New(value, HEAP_SPACE(kind)); |
| } |
| } |
| reader->AddBackRef(object_id, &mint, kIsDeserialized); |
| |
| // Set the object tags. |
| mint.set_tags(tags); |
| |
| return mint.raw(); |
| } |
| |
| |
| void RawMint::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| ASSERT(writer != NULL); |
| |
| // Write out the serialization header value for this object. |
| writer->WriteInlinedObjectHeader(object_id); |
| |
| // Write out the class and tags information. |
| writer->WriteIndexedObject(kMintCid); |
| writer->WriteIntptrValue(writer->GetObjectTags(this)); |
| |
| // Write out the 64 bit value. |
| writer->Write<int64_t>(ptr()->value_); |
| } |
| |
| |
| RawBigint* Bigint::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| |
| // Read in the HexCString representation of the bigint. |
| intptr_t len = reader->ReadIntptrValue(); |
| char* str = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
| str[len] = '\0'; |
| reader->ReadBytes(reinterpret_cast<uint8_t*>(str), len); |
| |
| // Create a Bigint object from HexCString. |
| Bigint& obj = Bigint::ZoneHandle( |
| reader->isolate(), |
| ((kind == Snapshot::kFull) ? reader->NewBigint(str) : |
| BigintOperations::FromHexCString(str, HEAP_SPACE(kind)))); |
| |
| // 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) && RawObject::IsCanonical(tags) && |
| (RawObject::IsCreatedFromSnapshot(tags) || |
| (kind == Snapshot::kMessage))) { |
| obj ^= obj.Canonicalize(); |
| } |
| reader->AddBackRef(object_id, &obj, kIsDeserialized); |
| |
| // Set the object tags. |
| obj.set_tags(tags); |
| |
| return obj.raw(); |
| } |
| |
| |
| void RawBigint::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| ASSERT(writer != NULL); |
| |
| // Write out the serialization header value for this object. |
| writer->WriteInlinedObjectHeader(object_id); |
| |
| // Write out the class and tags information. |
| writer->WriteIndexedObject(kBigintCid); |
| writer->WriteIntptrValue(writer->GetObjectTags(this)); |
| |
| // Write out the bigint value as a HEXCstring. |
| intptr_t length = ptr()->signed_length_; |
| bool is_negative = false; |
| if (length <= 0) { |
| length = -length; |
| is_negative = true; |
| } |
| uword data_start = reinterpret_cast<uword>(ptr()) + sizeof(RawBigint); |
| const char* str = BigintOperations::ToHexCString( |
| length, |
| is_negative, |
| reinterpret_cast<void*>(data_start), |
| &BigintAllocator); |
| bool neg = false; |
| if (*str == '-') { |
| neg = true; |
| str++; |
| } |
| intptr_t len = strlen(str); |
| ASSERT(len > 2 && str[0] == '0' && str[1] == 'x'); |
| if (neg) { |
| writer->WriteIntptrValue(len - 1); // Include '-' in length. |
| writer->Write<uint8_t>('-'); |
| } else { |
| writer->WriteIntptrValue(len - 2); |
| } |
| writer->WriteBytes(reinterpret_cast<const uint8_t*>(&(str[2])), (len - 2)); |
| } |
| |
| |
| RawDouble* Double::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| // Read the double value for the object. |
| double value = reader->Read<double>(); |
| |
| // Create a Double object or get canonical one if it is a canonical constant. |
| Double& dbl = Double::ZoneHandle(reader->isolate(), Double::null()); |
| if (kind == Snapshot::kFull) { |
| dbl = reader->NewDouble(value); |
| } 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))) { |
| dbl = Double::NewCanonical(value); |
| } else { |
| dbl = Double::New(value, HEAP_SPACE(kind)); |
| } |
| } |
| reader->AddBackRef(object_id, &dbl, kIsDeserialized); |
| |
| // Set the object tags. |
| dbl.set_tags(tags); |
| |
| return dbl.raw(); |
| } |
| |
| |
| void RawDouble::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| ASSERT(writer != NULL); |
| |
| // Write out the serialization header value for this object. |
| writer->WriteInlinedObjectHeader(object_id); |
| |
| // Write out the class and tags information. |
| writer->WriteIndexedObject(kDoubleCid); |
| writer->WriteIntptrValue(writer->GetObjectTags(this)); |
| |
| // Write out the double value. |
| writer->Write<double>(ptr()->value_); |
| } |
| |
| |
| RawString* String::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); // String is an abstract class. |
| return String::null(); |
| } |
| |
| |
| void RawString::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); // String is an abstract class. |
| } |
| |
| |
| template<typename StringType, typename CharacterType, typename CallbackType> |
| void String::ReadFromImpl(SnapshotReader* reader, |
| String* str_obj, |
| intptr_t len, |
| intptr_t tags, |
| CallbackType new_symbol, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| if (RawObject::IsCanonical(tags)) { |
| // Set up canonical string object. |
| ASSERT(reader != NULL); |
| CharacterType* ptr = |
| Isolate::Current()->current_zone()->Alloc<CharacterType>(len); |
| for (intptr_t i = 0; i < len; i++) { |
| ptr[i] = reader->Read<CharacterType>(); |
| } |
| *str_obj ^= (*new_symbol)(ptr, len); |
| } 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. |
| for (intptr_t i = 0; i < len; i++) { |
| *StringType::CharAddr(*str_obj, i) = reader->Read<CharacterType>(); |
| } |
| } |
| } |
| |
| |
| RawOneByteString* OneByteString::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| // Read the length so that we can determine instance size to allocate. |
| ASSERT(reader != NULL); |
| intptr_t len = reader->ReadSmiValue(); |
| intptr_t hash = reader->ReadSmiValue(); |
| String& str_obj = String::Handle(reader->isolate(), String::null()); |
| |
| if (kind == Snapshot::kFull) { |
| ASSERT(reader->isolate()->no_gc_scope_depth() != 0); |
| RawOneByteString* obj = reader->NewOneByteString(len); |
| str_obj = obj; |
| str_obj.set_tags(tags); |
| obj->ptr()->hash_ = Smi::New(hash); |
| if (len > 0) { |
| uint8_t* raw_ptr = CharAddr(str_obj, 0); |
| reader->ReadBytes(raw_ptr, len); |
| } |
| ASSERT((hash == 0) || (String::Hash(str_obj, 0, str_obj.Length()) == hash)); |
| } else { |
| String::ReadFromImpl<OneByteString, uint8_t>( |
| reader, &str_obj, len, tags, Symbols::FromLatin1, kind); |
| } |
| reader->AddBackRef(object_id, &str_obj, kIsDeserialized); |
| return raw(str_obj); |
| } |
| |
| |
| RawTwoByteString* TwoByteString::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| // Read the length so that we can determine instance size to allocate. |
| ASSERT(reader != NULL); |
| intptr_t len = reader->ReadSmiValue(); |
| intptr_t hash = reader->ReadSmiValue(); |
| String& str_obj = String::Handle(reader->isolate(), String::null()); |
| |
| if (kind == Snapshot::kFull) { |
| RawTwoByteString* obj = reader->NewTwoByteString(len); |
| str_obj = obj; |
| str_obj.set_tags(tags); |
| obj->ptr()->hash_ = Smi::New(hash); |
| uint16_t* raw_ptr = (len > 0)? CharAddr(str_obj, 0) : NULL; |
| for (intptr_t i = 0; i < len; i++) { |
| ASSERT(CharAddr(str_obj, i) == raw_ptr); // Will trigger assertions. |
| *raw_ptr = reader->Read<uint16_t>(); |
| raw_ptr += 1; |
| } |
| ASSERT(String::Hash(str_obj, 0, str_obj.Length()) == hash); |
| } else { |
| String::ReadFromImpl<TwoByteString, uint16_t>( |
| reader, &str_obj, len, tags, Symbols::FromUTF16, kind); |
| } |
| reader->AddBackRef(object_id, &str_obj, kIsDeserialized); |
| return raw(str_obj); |
| } |
| |
| |
| template<typename T> |
| static void StringWriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind, |
| intptr_t class_id, |
| intptr_t tags, |
| RawSmi* length, |
| RawSmi* hash, |
| T* data) { |
| ASSERT(writer != NULL); |
| intptr_t len = Smi::Value(length); |
| |
| // Write out the serialization header value for this object. |
| writer->WriteInlinedObjectHeader(object_id); |
| |
| // Write out the class and tags information. |
| writer->WriteIndexedObject(class_id); |
| writer->WriteIntptrValue(tags); |
| |
| // Write out the length field. |
| writer->Write<RawObject*>(length); |
| |
| // Write out the hash field. |
| writer->Write<RawObject*>(hash); |
| |
| // Write out the string. |
| if (len > 0) { |
| if (class_id == kOneByteStringCid) { |
| writer->WriteBytes(reinterpret_cast<const uint8_t*>(data), len); |
| } else { |
| for (intptr_t i = 0; i < len; i++) { |
| writer->Write(data[i]); |
| } |
| } |
| } |
| } |
| |
| |
| void RawOneByteString::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| StringWriteTo(writer, |
| object_id, |
| kind, |
| kOneByteStringCid, |
| writer->GetObjectTags(this), |
| ptr()->length_, |
| ptr()->hash_, |
| ptr()->data_); |
| } |
| |
| |
| void RawTwoByteString::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| StringWriteTo(writer, |
| object_id, |
| kind, |
| kTwoByteStringCid, |
| writer->GetObjectTags(this), |
| ptr()->length_, |
| ptr()->hash_, |
| ptr()->data_); |
| } |
| |
| |
| RawExternalOneByteString* ExternalOneByteString::ReadFrom( |
| SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); |
| return ExternalOneByteString::null(); |
| } |
| |
| |
| RawExternalTwoByteString* ExternalTwoByteString::ReadFrom( |
| SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); |
| return ExternalTwoByteString::null(); |
| } |
| |
| |
| void RawExternalOneByteString::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| // Serialize as a non-external one byte string. |
| StringWriteTo(writer, |
| object_id, |
| kind, |
| kOneByteStringCid, |
| writer->GetObjectTags(this), |
| ptr()->length_, |
| ptr()->hash_, |
| ptr()->external_data_->data()); |
| } |
| |
| |
| void RawExternalTwoByteString::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| // Serialize as a non-external two byte string. |
| StringWriteTo(writer, |
| object_id, |
| kind, |
| kTwoByteStringCid, |
| writer->GetObjectTags(this), |
| ptr()->length_, |
| ptr()->hash_, |
| ptr()->external_data_->data()); |
| } |
| |
| |
| RawBool* Bool::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); |
| return Bool::null(); |
| } |
| |
| |
| void RawBool::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); |
| } |
| |
| |
| RawArray* Array::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| |
| // Read the length so that we can determine instance size to allocate. |
| intptr_t len = reader->ReadSmiValue(); |
| Array* array = reinterpret_cast<Array*>( |
| reader->GetBackRef(object_id)); |
| if (array == NULL) { |
| array = &(Array::ZoneHandle(reader->isolate(), |
| NEW_OBJECT_WITH_LEN_SPACE(Array, len, kind))); |
| reader->AddBackRef(object_id, array, kIsDeserialized); |
| } |
| reader->ArrayReadFrom(*array, len, tags); |
| return array->raw(); |
| } |
| |
| |
| RawImmutableArray* ImmutableArray::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| |
| // Read the length so that we can determine instance size to allocate. |
| intptr_t len = reader->ReadSmiValue(); |
| ImmutableArray* array = reinterpret_cast<ImmutableArray*>( |
| reader->GetBackRef(object_id)); |
| if (array == NULL) { |
| array = &(ImmutableArray::ZoneHandle( |
| reader->isolate(), |
| NEW_OBJECT_WITH_LEN_SPACE(ImmutableArray, len, kind))); |
| reader->AddBackRef(object_id, array, kIsDeserialized); |
| } |
| reader->ArrayReadFrom(*array, len, tags); |
| return array->raw(); |
| } |
| |
| |
| void RawArray::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| writer->ArrayWriteTo(object_id, |
| kArrayCid, |
| writer->GetObjectTags(this), |
| ptr()->length_, |
| ptr()->type_arguments_, |
| ptr()->data()); |
| } |
| |
| |
| void RawImmutableArray::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| writer->ArrayWriteTo(object_id, |
| kImmutableArrayCid, |
| writer->GetObjectTags(this), |
| ptr()->length_, |
| ptr()->type_arguments_, |
| ptr()->data()); |
| } |
| |
| |
| RawGrowableObjectArray* GrowableObjectArray::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| |
| // Read the length so that we can determine instance size to allocate. |
| GrowableObjectArray& array = GrowableObjectArray::ZoneHandle( |
| reader->isolate(), GrowableObjectArray::null()); |
| if (kind == Snapshot::kFull) { |
| array = reader->NewGrowableObjectArray(); |
| } else { |
| array = GrowableObjectArray::New(0, HEAP_SPACE(kind)); |
| } |
| reader->AddBackRef(object_id, &array, kIsDeserialized); |
| intptr_t length = reader->ReadSmiValue(); |
| array.SetLength(length); |
| Array& contents = Array::Handle(); |
| contents ^= reader->ReadObjectImpl(); |
| array.SetData(contents); |
| const AbstractTypeArguments& type_arguments = |
| AbstractTypeArguments::Handle(contents.GetTypeArguments()); |
| array.SetTypeArguments(type_arguments); |
| return array.raw(); |
| } |
| |
| |
| void RawGrowableObjectArray::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| ASSERT(writer != NULL); |
| |
| // Write out the serialization header value for this object. |
| writer->WriteInlinedObjectHeader(object_id); |
| |
| // Write out the class and tags information. |
| writer->WriteIndexedObject(kGrowableObjectArrayCid); |
| writer->WriteIntptrValue(writer->GetObjectTags(this)); |
| |
| // Write out the used length field. |
| writer->Write<RawObject*>(ptr()->length_); |
| |
| // Write out the Array object. |
| writer->WriteObjectImpl(ptr()->data_); |
| } |
| |
| |
| RawFloat32x4* Float32x4::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| // Read the values. |
| float value0 = reader->Read<float>(); |
| float value1 = reader->Read<float>(); |
| float value2 = reader->Read<float>(); |
| float value3 = reader->Read<float>(); |
| |
| // Create a Float32x4 object. |
| Float32x4& simd = Float32x4::ZoneHandle(reader->isolate(), |
| Float32x4::null()); |
| if (kind == Snapshot::kFull) { |
| simd = reader->NewFloat32x4(value0, value1, value2, value3); |
| } else { |
| 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(); |
| } |
| |
| |
| void RawFloat32x4::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| ASSERT(writer != NULL); |
| |
| // Write out the serialization header value for this object. |
| writer->WriteInlinedObjectHeader(object_id); |
| |
| // Write out the class and tags information. |
| writer->WriteIndexedObject(kFloat32x4Cid); |
| writer->WriteIntptrValue(writer->GetObjectTags(this)); |
| |
| // Write out the float values. |
| writer->Write<float>(ptr()->value_[0]); |
| writer->Write<float>(ptr()->value_[1]); |
| writer->Write<float>(ptr()->value_[2]); |
| writer->Write<float>(ptr()->value_[3]); |
| } |
| |
| |
| RawUint32x4* Uint32x4::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| // Read the values. |
| uint32_t value0 = reader->Read<uint32_t>(); |
| uint32_t value1 = reader->Read<uint32_t>(); |
| uint32_t value2 = reader->Read<uint32_t>(); |
| uint32_t value3 = reader->Read<uint32_t>(); |
| |
| // Create a Float32x4 object. |
| Uint32x4& simd = Uint32x4::ZoneHandle(reader->isolate(), Uint32x4::null()); |
| |
| if (kind == Snapshot::kFull) { |
| simd = reader->NewUint32x4(value0, value1, value2, value3); |
| } else { |
| simd = Uint32x4::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(); |
| } |
| |
| |
| void RawUint32x4::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| ASSERT(writer != NULL); |
| |
| // Write out the serialization header value for this object. |
| writer->WriteInlinedObjectHeader(object_id); |
| |
| // Write out the class and tags information. |
| writer->WriteIndexedObject(kUint32x4Cid); |
| writer->WriteIntptrValue(writer->GetObjectTags(this)); |
| |
| // Write out the mask values. |
| writer->Write<uint32_t>(ptr()->value_[0]); |
| writer->Write<uint32_t>(ptr()->value_[1]); |
| writer->Write<uint32_t>(ptr()->value_[2]); |
| writer->Write<uint32_t>(ptr()->value_[3]); |
| } |
| |
| |
| #define TYPED_DATA_READ(setter, type) \ |
| for (intptr_t i = 0; i < lengthInBytes; i += element_size) { \ |
| result.Set##setter(i, reader->Read<type>()); \ |
| } \ |
| |
| |
| RawTypedData* TypedData::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| |
| intptr_t cid = RawObject::ClassIdTag::decode(tags); |
| intptr_t len = reader->ReadSmiValue(); |
| TypedData& result = TypedData::ZoneHandle( |
| reader->isolate(), 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 lengthInBytes = len * element_size; |
| switch (cid) { |
| case kTypedDataInt8ArrayCid: |
| TYPED_DATA_READ(Int8, int8_t); |
| break; |
| case kTypedDataUint8ArrayCid: |
| TYPED_DATA_READ(Uint8, uint8_t); |
| break; |
| case kTypedDataUint8ClampedArrayCid: |
| TYPED_DATA_READ(Uint8, uint8_t); |
| break; |
| case kTypedDataInt16ArrayCid: |
| TYPED_DATA_READ(Int16, int16_t); |
| break; |
| case kTypedDataUint16ArrayCid: |
| TYPED_DATA_READ(Uint16, uint16_t); |
| break; |
| case kTypedDataInt32ArrayCid: |
| TYPED_DATA_READ(Int32, int32_t); |
| break; |
| case kTypedDataUint32ArrayCid: |
| TYPED_DATA_READ(Uint32, uint32_t); |
| break; |
| case kTypedDataInt64ArrayCid: |
| TYPED_DATA_READ(Int64, int64_t); |
| break; |
| case kTypedDataUint64ArrayCid: |
| TYPED_DATA_READ(Uint64, uint64_t); |
| break; |
| case kTypedDataFloat32ArrayCid: |
| TYPED_DATA_READ(Float32, float); |
| break; |
| case kTypedDataFloat64ArrayCid: |
| TYPED_DATA_READ(Float64, double); |
| break; |
| default: |
| UNREACHABLE(); |
| } |
| return result.raw(); |
| } |
| #undef TYPED_DATA_READ |
| |
| |
| RawExternalTypedData* ExternalTypedData::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(kind != Snapshot::kFull); |
| intptr_t cid = RawObject::ClassIdTag::decode(tags); |
| intptr_t length = reader->ReadSmiValue(); |
| uint8_t* data = reinterpret_cast<uint8_t*>(reader->ReadIntptrValue()); |
| const ExternalTypedData& obj = ExternalTypedData::Handle( |
| ExternalTypedData::New(cid, data, length)); |
| void* peer = reinterpret_cast<void*>(reader->ReadIntptrValue()); |
| Dart_WeakPersistentHandleFinalizer callback = |
| reinterpret_cast<Dart_WeakPersistentHandleFinalizer>( |
| reader->ReadIntptrValue()); |
| obj.AddFinalizer(peer, callback); |
| return obj.raw(); |
| } |
| |
| |
| #define TYPED_DATA_WRITE(type) \ |
| { \ |
| type* data = reinterpret_cast<type*>(ptr()->data_); \ |
| for (intptr_t i = 0; i < len; i++) { \ |
| writer->Write(data[i]); \ |
| } \ |
| } \ |
| |
| |
| void RawTypedData::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| ASSERT(writer != NULL); |
| intptr_t tags = writer->GetObjectTags(this); |
| intptr_t cid = ClassIdTag::decode(tags); |
| intptr_t len = Smi::Value(ptr()->length_); |
| |
| // Write out the serialization header value for this object. |
| writer->WriteInlinedObjectHeader(object_id); |
| |
| // Write out the class and tags information. |
| writer->WriteIndexedObject(cid); |
| writer->WriteIntptrValue(tags); |
| |
| // Write out the length field. |
| writer->Write<RawObject*>(ptr()->length_); |
| |
| // Write out the array elements. |
| switch (cid) { |
| case kTypedDataInt8ArrayCid: |
| TYPED_DATA_WRITE(int8_t); |
| break; |
| case kTypedDataUint8ArrayCid: |
| TYPED_DATA_WRITE(uint8_t); |
| break; |
| case kTypedDataUint8ClampedArrayCid: |
| TYPED_DATA_WRITE(uint8_t); |
| break; |
| case kTypedDataInt16ArrayCid: |
| TYPED_DATA_WRITE(int16_t); |
| break; |
| case kTypedDataUint16ArrayCid: |
| TYPED_DATA_WRITE(uint16_t); |
| break; |
| case kTypedDataInt32ArrayCid: |
| TYPED_DATA_WRITE(int32_t); |
| break; |
| case kTypedDataUint32ArrayCid: |
| TYPED_DATA_WRITE(uint32_t); |
| break; |
| case kTypedDataInt64ArrayCid: |
| TYPED_DATA_WRITE(int64_t); |
| break; |
| case kTypedDataUint64ArrayCid: |
| TYPED_DATA_WRITE(uint64_t); |
| break; |
| case kTypedDataFloat32ArrayCid: |
| TYPED_DATA_WRITE(float); // NOLINT. |
| break; |
| case kTypedDataFloat64ArrayCid: |
| TYPED_DATA_WRITE(double); // NOLINT. |
| break; |
| default: |
| UNREACHABLE(); |
| } |
| } |
| |
| |
| #define EXT_TYPED_DATA_WRITE(cid, type) \ |
| writer->WriteIndexedObject(cid); \ |
| writer->WriteIntptrValue(RawObject::ClassIdTag::update(cid, tags)); \ |
| writer->Write<RawObject*>(ptr()->length_); \ |
| TYPED_DATA_WRITE(type) \ |
| |
| |
| void RawExternalTypedData::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| ASSERT(writer != NULL); |
| intptr_t tags = writer->GetObjectTags(this); |
| intptr_t cid = ClassIdTag::decode(tags); |
| intptr_t len = Smi::Value(ptr()->length_); |
| |
| // Write out the serialization header value for this object. |
| writer->WriteInlinedObjectHeader(object_id); |
| |
| switch (cid) { |
| case kExternalTypedDataInt8ArrayCid: |
| EXT_TYPED_DATA_WRITE(kTypedDataInt8ArrayCid, int8_t); |
| break; |
| case kExternalTypedDataUint8ArrayCid: |
| EXT_TYPED_DATA_WRITE(kTypedDataUint8ArrayCid, uint8_t); |
| break; |
| case kExternalTypedDataUint8ClampedArrayCid: |
| EXT_TYPED_DATA_WRITE(kTypedDataUint8ClampedArrayCid, uint8_t); |
| break; |
| case kExternalTypedDataInt16ArrayCid: |
| EXT_TYPED_DATA_WRITE(kTypedDataInt16ArrayCid, int16_t); |
| break; |
| case kExternalTypedDataUint16ArrayCid: |
| EXT_TYPED_DATA_WRITE(kTypedDataUint16ArrayCid, uint16_t); |
| break; |
| case kExternalTypedDataInt32ArrayCid: |
| EXT_TYPED_DATA_WRITE(kTypedDataInt32ArrayCid, int32_t); |
| break; |
| case kExternalTypedDataUint32ArrayCid: |
| EXT_TYPED_DATA_WRITE(kTypedDataUint32ArrayCid, uint32_t); |
| break; |
| case kExternalTypedDataInt64ArrayCid: |
| EXT_TYPED_DATA_WRITE(kTypedDataInt64ArrayCid, int64_t); |
| break; |
| case kExternalTypedDataUint64ArrayCid: |
| EXT_TYPED_DATA_WRITE(kTypedDataUint64ArrayCid, uint64_t); |
| break; |
| case kExternalTypedDataFloat32ArrayCid: |
| EXT_TYPED_DATA_WRITE(kTypedDataFloat32ArrayCid, float); // NOLINT. |
| break; |
| case kExternalTypedDataFloat64ArrayCid: |
| EXT_TYPED_DATA_WRITE(kTypedDataFloat64ArrayCid, double); // NOLINT. |
| break; |
| default: |
| UNREACHABLE(); |
| } |
| } |
| #undef TYPED_DATA_WRITE |
| #undef EXT_TYPED_DATA_WRITE |
| |
| |
| RawDartFunction* DartFunction::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); // DartFunction is an abstract class. |
| return DartFunction::null(); |
| } |
| |
| |
| void RawDartFunction::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| UNREACHABLE(); // DartFunction is an abstract class. |
| } |
| |
| |
| RawStacktrace* Stacktrace::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| if (kind == Snapshot::kFull) { |
| Stacktrace& result = Stacktrace::ZoneHandle(reader->isolate(), |
| reader->NewStacktrace()); |
| reader->AddBackRef(object_id, &result, kIsDeserialized); |
| |
| // There are no non object pointer fields. |
| |
| // Read all the object pointer fields. |
| Array& array = Array::Handle(reader->isolate()); |
| array ^= reader->ReadObjectRef(); |
| result.set_function_array(array); |
| array ^= reader->ReadObjectRef(); |
| result.set_code_array(array); |
| array ^= reader->ReadObjectRef(); |
| result.set_pc_offset_array(array); |
| |
| array ^= reader->ReadObjectRef(); |
| result.set_catch_func_array(array); |
| array ^= reader->ReadObjectRef(); |
| result.set_catch_code_array(array); |
| array ^= reader->ReadObjectRef(); |
| result.set_catch_pc_offset_array(array); |
| |
| return result.raw(); |
| } |
| UNREACHABLE(); // Stacktraces are not sent in a snapshot. |
| return Stacktrace::null(); |
| } |
| |
| |
| void RawStacktrace::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| if (kind == Snapshot::kFull) { |
| ASSERT(writer != NULL); |
| ASSERT(this == Isolate::Current()->object_store()-> |
| preallocated_stack_trace()); |
| |
| // Write out the serialization header value for this object. |
| writer->WriteInlinedObjectHeader(object_id); |
| |
| // Write out the class and tags information. |
| writer->WriteIndexedObject(kStacktraceCid); |
| writer->WriteIntptrValue(writer->GetObjectTags(this)); |
| |
| // There are no non object pointer fields. |
| |
| // Write out all the object pointer fields. |
| SnapshotWriterVisitor visitor(writer); |
| visitor.VisitPointers(from(), to()); |
| } else { |
| // Stacktraces are not allowed in other snapshot forms. |
| writer->SetWriteException(Exceptions::kArgument, |
| "Illegal argument in isolate message" |
| " : (object is a stacktrace)"); |
| } |
| } |
| |
| |
| RawJSRegExp* JSRegExp::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| ASSERT(kind == Snapshot::kMessage); |
| |
| // Read the length so that we can determine instance size to allocate. |
| intptr_t len = reader->ReadSmiValue(); |
| |
| // Allocate JSRegExp object. |
| JSRegExp& regex = JSRegExp::ZoneHandle( |
| reader->isolate(), JSRegExp::New(len, 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.raw_ptr()->num_bracket_expressions_ = reader->ReadAsSmi(); |
| *reader->StringHandle() ^= reader->ReadObjectImpl(); |
| regex.set_pattern(*reader->StringHandle()); |
| regex.raw_ptr()->type_ = reader->ReadIntptrValue(); |
| regex.raw_ptr()->flags_ = reader->ReadIntptrValue(); |
| |
| // TODO(5411462): Need to implement a way of recompiling the regex. |
| |
| return regex.raw(); |
| } |
| |
| |
| void RawJSRegExp::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| ASSERT(writer != NULL); |
| ASSERT(kind == Snapshot::kMessage); |
| |
| // Write out the serialization header value for this object. |
| writer->WriteInlinedObjectHeader(object_id); |
| |
| // Write out the class and tags information. |
| writer->WriteIndexedObject(kJSRegExpCid); |
| writer->WriteIntptrValue(writer->GetObjectTags(this)); |
| |
| // Write out the data length field. |
| writer->Write<RawObject*>(ptr()->data_length_); |
| |
| // Write out all the other fields. |
| writer->Write<RawObject*>(ptr()->num_bracket_expressions_); |
| writer->WriteObjectImpl(ptr()->pattern_); |
| writer->WriteIntptrValue(ptr()->type_); |
| writer->WriteIntptrValue(ptr()->flags_); |
| |
| // Do not write out the data part which is native. |
| } |
| |
| |
| RawWeakProperty* WeakProperty::ReadFrom(SnapshotReader* reader, |
| intptr_t object_id, |
| intptr_t tags, |
| Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| |
| // Allocate the weak property object. |
| WeakProperty& weak_property = WeakProperty::ZoneHandle( |
| reader->isolate(), 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. |
| weak_property.raw_ptr()->key_ = reader->ReadObjectRef(); |
| weak_property.raw_ptr()->value_ = reader->ReadObjectRef(); |
| |
| return weak_property.raw(); |
| } |
| |
| |
| void RawWeakProperty::WriteTo(SnapshotWriter* writer, |
| intptr_t object_id, |
| Snapshot::Kind kind) { |
| ASSERT(writer != NULL); |
| |
| // Write out the serialization header value for this object. |
| writer->WriteInlinedObjectHeader(object_id); |
| |
| // Write out the class and tags information. |
| writer->WriteIndexedObject(kWeakPropertyCid); |
| writer->WriteIntptrValue(writer->GetObjectTags(this)); |
| |
| // Write out all the other fields. |
| writer->Write<RawObject*>(ptr()->key_); |
| writer->Write<RawObject*>(ptr()->value_); |
| } |
| |
| } // namespace dart |