| // Copyright (c) 2021, 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/message_snapshot.h" |
| |
| #include <memory> |
| |
| #include "platform/assert.h" |
| #include "platform/unicode.h" |
| #include "vm/class_finalizer.h" |
| #include "vm/class_id.h" |
| #include "vm/dart_api_message.h" |
| #include "vm/dart_api_state.h" |
| #include "vm/dart_entry.h" |
| #include "vm/flags.h" |
| #include "vm/growable_array.h" |
| #include "vm/heap/heap.h" |
| #include "vm/heap/weak_table.h" |
| #include "vm/longjump.h" |
| #include "vm/object.h" |
| #include "vm/object_graph_copy.h" |
| #include "vm/object_store.h" |
| #include "vm/symbols.h" |
| #include "vm/type_testing_stubs.h" |
| |
| namespace dart { |
| |
| static Dart_CObject cobj_null = {.type = Dart_CObject_kNull, |
| .value = {.as_int64 = 0}}; |
| static Dart_CObject cobj_sentinel = {.type = Dart_CObject_kUnsupported}; |
| static Dart_CObject cobj_transition_sentinel = {.type = |
| Dart_CObject_kUnsupported}; |
| static Dart_CObject cobj_empty_array = { |
| .type = Dart_CObject_kArray, |
| .value = {.as_array = {.length = 0, .values = nullptr}}}; |
| static Dart_CObject cobj_zero_array_element = {.type = Dart_CObject_kInt32, |
| .value = {.as_int32 = 0}}; |
| static Dart_CObject* cobj_zero_array_values[1] = {&cobj_zero_array_element}; |
| static Dart_CObject cobj_zero_array = { |
| .type = Dart_CObject_kArray, |
| .value = {.as_array = {.length = 1, .values = &cobj_zero_array_values[0]}}}; |
| static Dart_CObject cobj_dynamic_type = {.type = Dart_CObject_kUnsupported}; |
| static Dart_CObject cobj_void_type = {.type = Dart_CObject_kUnsupported}; |
| static Dart_CObject cobj_empty_type_arguments = {.type = |
| Dart_CObject_kUnsupported}; |
| static Dart_CObject cobj_true = {.type = Dart_CObject_kBool, |
| .value = {.as_bool = true}}; |
| static Dart_CObject cobj_false = {.type = Dart_CObject_kBool, |
| .value = {.as_bool = false}}; |
| |
| enum class MessagePhase { |
| kBeforeTypes = 0, |
| kTypes = 1, |
| kCanonicalInstances = 2, |
| kNonCanonicalInstances = 3, |
| |
| kNumPhases = 4, |
| }; |
| |
| class MessageSerializer; |
| class MessageDeserializer; |
| class ApiMessageSerializer; |
| class ApiMessageDeserializer; |
| class WeakPropertyMessageSerializationCluster; |
| |
| class MessageSerializationCluster : public ZoneAllocated { |
| public: |
| explicit MessageSerializationCluster(const char* name, |
| MessagePhase phase, |
| intptr_t cid, |
| bool is_canonical = false) |
| : name_(name), phase_(phase), cid_(cid), is_canonical_(is_canonical) {} |
| virtual ~MessageSerializationCluster() {} |
| |
| virtual void Trace(MessageSerializer* s, Object* object) = 0; |
| virtual void WriteNodes(MessageSerializer* s) = 0; |
| virtual void WriteEdges(MessageSerializer* s) {} |
| |
| virtual void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {} |
| virtual void WriteNodesApi(ApiMessageSerializer* s) {} |
| virtual void WriteEdgesApi(ApiMessageSerializer* s) {} |
| |
| const char* name() const { return name_; } |
| MessagePhase phase() const { return phase_; } |
| intptr_t cid() const { return cid_; } |
| bool is_canonical() const { return is_canonical_; } |
| |
| protected: |
| const char* const name_; |
| const MessagePhase phase_; |
| const intptr_t cid_; |
| const bool is_canonical_; |
| |
| DISALLOW_COPY_AND_ASSIGN(MessageSerializationCluster); |
| }; |
| |
| class MessageDeserializationCluster : public ZoneAllocated { |
| public: |
| explicit MessageDeserializationCluster(const char* name, |
| bool is_canonical = false) |
| : name_(name), |
| is_canonical_(is_canonical), |
| start_index_(0), |
| stop_index_(0) {} |
| virtual ~MessageDeserializationCluster() {} |
| |
| virtual void ReadNodes(MessageDeserializer* d) = 0; |
| virtual void ReadEdges(MessageDeserializer* d) {} |
| virtual ObjectPtr PostLoad(MessageDeserializer* d) { return nullptr; } |
| virtual void ReadNodesApi(ApiMessageDeserializer* d) {} |
| virtual void ReadEdgesApi(ApiMessageDeserializer* d) {} |
| virtual void PostLoadApi(ApiMessageDeserializer* d) {} |
| |
| void ReadNodesWrapped(MessageDeserializer* d); |
| void ReadNodesWrappedApi(ApiMessageDeserializer* d); |
| |
| const char* name() const { return name_; } |
| bool is_canonical() const { return is_canonical_; } |
| |
| protected: |
| ObjectPtr PostLoadAbstractType(MessageDeserializer* d); |
| ObjectPtr PostLoadLinkedHash(MessageDeserializer* d); |
| |
| const char* const name_; |
| const bool is_canonical_; |
| // The range of the ref array that belongs to this cluster. |
| intptr_t start_index_; |
| intptr_t stop_index_; |
| |
| DISALLOW_COPY_AND_ASSIGN(MessageDeserializationCluster); |
| }; |
| |
| class BaseSerializer : public StackResource { |
| public: |
| BaseSerializer(Thread* thread, Zone* zone); |
| ~BaseSerializer(); |
| |
| // Writes raw data to the stream (basic type). |
| // sizeof(T) must be in {1,2,4,8}. |
| template <typename T> |
| void Write(T value) { |
| BaseWriteStream::Raw<sizeof(T), T>::Write(&stream_, value); |
| } |
| void WriteUnsigned(intptr_t value) { stream_.WriteUnsigned(value); } |
| void WriteWordWith32BitWrites(uword value) { |
| stream_.WriteWordWith32BitWrites(value); |
| } |
| void WriteBytes(const void* addr, intptr_t len) { |
| stream_.WriteBytes(addr, len); |
| } |
| void WriteAscii(const String& str) { |
| intptr_t len = str.Length(); |
| WriteUnsigned(len); |
| for (intptr_t i = 0; i < len; i++) { |
| int64_t c = str.CharAt(i); |
| ASSERT(c < 128); |
| Write<uint8_t>(c); |
| } |
| Write<uint8_t>(0); |
| } |
| |
| MessageSerializationCluster* NewClusterForClass(intptr_t cid, |
| bool is_canonical); |
| void WriteCluster(MessageSerializationCluster* cluster); |
| |
| std::unique_ptr<Message> Finish(Dart_Port dest_port, |
| Message::Priority priority) { |
| MessageFinalizableData* finalizable_data = finalizable_data_; |
| finalizable_data_ = nullptr; |
| finalizable_data->SerializationSucceeded(); |
| intptr_t size; |
| uint8_t* buffer = stream_.Steal(&size); |
| return Message::New(dest_port, buffer, size, finalizable_data, priority); |
| } |
| |
| Zone* zone() const { return zone_; } |
| MessageFinalizableData* finalizable_data() const { return finalizable_data_; } |
| intptr_t next_ref_index() const { return next_ref_index_; } |
| |
| protected: |
| Zone* const zone_; |
| MallocWriteStream stream_; |
| MessageFinalizableData* finalizable_data_; |
| GrowableArray<MessageSerializationCluster*> clusters_; |
| WeakPropertyMessageSerializationCluster* ephemeron_cluster_; |
| intptr_t num_base_objects_; |
| intptr_t num_written_objects_; |
| intptr_t next_ref_index_; |
| }; |
| |
| class MessageSerializer : public BaseSerializer { |
| public: |
| MessageSerializer(Thread* thread, bool can_send_any_object); |
| ~MessageSerializer(); |
| |
| bool MarkObjectId(ObjectPtr object, intptr_t id) { |
| ASSERT(id != WeakTable::kNoValue); |
| WeakTable* table; |
| if (!object->IsSmiOrOldObject()) { |
| table = isolate()->forward_table_new(); |
| } else { |
| table = isolate()->forward_table_old(); |
| } |
| return table->MarkValueExclusive(object, id); |
| } |
| |
| void SetObjectId(ObjectPtr object, intptr_t id) { |
| ASSERT(id != WeakTable::kNoValue); |
| WeakTable* table; |
| if (!object->IsSmiOrOldObject()) { |
| table = isolate()->forward_table_new(); |
| } else { |
| table = isolate()->forward_table_old(); |
| } |
| table->SetValueExclusive(object, id); |
| } |
| |
| intptr_t GetObjectId(ObjectPtr object) const { |
| const WeakTable* table; |
| if (!object->IsSmiOrOldObject()) { |
| table = isolate()->forward_table_new(); |
| } else { |
| table = isolate()->forward_table_old(); |
| } |
| return table->GetValueExclusive(object); |
| } |
| |
| DART_NOINLINE void AddBaseObject(ObjectPtr base_object) { |
| AssignRef(base_object); |
| num_base_objects_++; |
| } |
| DART_NOINLINE void AssignRef(ObjectPtr object) { |
| SetObjectId(object, next_ref_index_); |
| next_ref_index_++; |
| } |
| void AssignRef(Object* object) { AssignRef(object->ptr()); } |
| |
| void Push(ObjectPtr object); |
| |
| void Trace(Object* object); |
| |
| void IllegalObject(const Object& object, const char* message); |
| |
| void AddBaseObjects(); |
| void Serialize(const Object& root); |
| |
| DART_NOINLINE void WriteRef(ObjectPtr object) { |
| intptr_t index = GetObjectId(object); |
| ASSERT(index != WeakTable::kNoValue); |
| WriteUnsigned(index); |
| } |
| |
| bool can_send_any_object() const { return can_send_any_object_; } |
| const char* exception_message() const { return exception_message_; } |
| Thread* thread() const { |
| return static_cast<Thread*>(StackResource::thread()); |
| } |
| Isolate* isolate() const { return thread()->isolate(); } |
| IsolateGroup* isolate_group() const { return thread()->isolate_group(); } |
| |
| bool HasRef(ObjectPtr object) const { |
| return GetObjectId(object) != WeakTable::kNoValue; |
| } |
| |
| private: |
| WeakTable* forward_table_new_; |
| WeakTable* forward_table_old_; |
| GrowableArray<Object*> stack_; |
| bool const can_send_any_object_; |
| const char* exception_message_; |
| }; |
| |
| class ApiMessageSerializer : public BaseSerializer { |
| public: |
| explicit ApiMessageSerializer(Zone* zone); |
| ~ApiMessageSerializer(); |
| |
| bool MarkObjectId(Dart_CObject* object, intptr_t id) { |
| ASSERT(id != WeakTable::kNoValue); |
| return forward_table_.MarkValueExclusive( |
| static_cast<ObjectPtr>(reinterpret_cast<uword>(object)), id); |
| } |
| |
| void SetObjectId(Dart_CObject* object, intptr_t id) { |
| ASSERT(id != WeakTable::kNoValue); |
| forward_table_.SetValueExclusive( |
| static_cast<ObjectPtr>(reinterpret_cast<uword>(object)), id); |
| } |
| |
| intptr_t GetObjectId(Dart_CObject* object) const { |
| return forward_table_.GetValueExclusive( |
| static_cast<ObjectPtr>(reinterpret_cast<uword>(object))); |
| } |
| |
| DART_NOINLINE void AddBaseObject(Dart_CObject* base_object) { |
| AssignRef(base_object); |
| num_base_objects_++; |
| } |
| DART_NOINLINE intptr_t AssignRef(Dart_CObject* object) { |
| SetObjectId(object, next_ref_index_); |
| return next_ref_index_++; |
| } |
| void ForwardRef(Dart_CObject* old, Dart_CObject* nue) { |
| intptr_t id = GetObjectId(nue); |
| ASSERT(id != WeakTable::kNoValue); |
| SetObjectId(old, id); |
| num_written_objects_--; |
| } |
| |
| void Push(Dart_CObject* object); |
| |
| bool Trace(Dart_CObject* object); |
| |
| void AddBaseObjects(); |
| bool Serialize(Dart_CObject* root); |
| |
| void WriteRef(Dart_CObject* object) { |
| intptr_t index = GetObjectId(object); |
| ASSERT(index != WeakTable::kNoValue); |
| WriteUnsigned(index); |
| } |
| |
| bool Fail(const char* message) { |
| exception_message_ = message; |
| return false; |
| } |
| |
| private: |
| WeakTable forward_table_; |
| GrowableArray<Dart_CObject*> stack_; |
| const char* exception_message_; |
| }; |
| |
| class BaseDeserializer : public ValueObject { |
| public: |
| BaseDeserializer(Zone* zone, Message* message); |
| ~BaseDeserializer(); |
| |
| // Reads raw data (for basic types). |
| // sizeof(T) must be in {1,2,4,8}. |
| template <typename T> |
| T Read() { |
| return ReadStream::Raw<sizeof(T), T>::Read(&stream_); |
| } |
| intptr_t ReadUnsigned() { return stream_.ReadUnsigned(); } |
| uword ReadWordWith32BitReads() { return stream_.ReadWordWith32BitReads(); } |
| void ReadBytes(void* addr, intptr_t len) { stream_.ReadBytes(addr, len); } |
| const char* ReadAscii() { |
| intptr_t len = ReadUnsigned(); |
| const char* result = reinterpret_cast<const char*>(CurrentBufferAddress()); |
| Advance(len + 1); |
| return result; |
| } |
| |
| const uint8_t* CurrentBufferAddress() const { |
| return stream_.AddressOfCurrentPosition(); |
| } |
| |
| void Advance(intptr_t value) { stream_.Advance(value); } |
| |
| MessageDeserializationCluster* ReadCluster(); |
| |
| Zone* zone() const { return zone_; } |
| intptr_t next_index() const { return next_ref_index_; } |
| MessageFinalizableData* finalizable_data() const { return finalizable_data_; } |
| |
| protected: |
| Zone* zone_; |
| ReadStream stream_; |
| MessageFinalizableData* finalizable_data_; |
| intptr_t next_ref_index_; |
| }; |
| |
| class MessageDeserializer : public BaseDeserializer { |
| public: |
| MessageDeserializer(Thread* thread, Message* message) |
| : BaseDeserializer(thread->zone(), message), |
| thread_(thread), |
| refs_(Array::Handle(thread->zone())) {} |
| ~MessageDeserializer() {} |
| |
| DART_NOINLINE void AddBaseObject(ObjectPtr base_object) { |
| AssignRef(base_object); |
| } |
| void AssignRef(ObjectPtr object) { |
| refs_.untag()->set_element(next_ref_index_, object); |
| next_ref_index_++; |
| } |
| |
| ObjectPtr Ref(intptr_t index) const { |
| ASSERT(index > 0); |
| ASSERT(index <= next_ref_index_); |
| return refs_.At(index); |
| } |
| void UpdateRef(intptr_t index, const Object& new_object) { |
| ASSERT(index > 0); |
| ASSERT(index <= next_ref_index_); |
| refs_.SetAt(index, new_object); |
| } |
| |
| ObjectPtr ReadRef() { return Ref(ReadUnsigned()); } |
| |
| void AddBaseObjects(); |
| ObjectPtr Deserialize(); |
| |
| Thread* thread() const { return thread_; } |
| IsolateGroup* isolate_group() const { return thread_->isolate_group(); } |
| ArrayPtr refs() const { return refs_.ptr(); } |
| |
| private: |
| Thread* const thread_; |
| Array& refs_; |
| }; |
| |
| class ApiMessageDeserializer : public BaseDeserializer { |
| public: |
| ApiMessageDeserializer(Zone* zone, Message* message) |
| : BaseDeserializer(zone, message), refs_(nullptr) {} |
| ~ApiMessageDeserializer() {} |
| |
| void AddBaseObject(Dart_CObject* base_object) { AssignRef(base_object); } |
| void AssignRef(Dart_CObject* object) { |
| refs_[next_ref_index_] = object; |
| next_ref_index_++; |
| } |
| |
| Dart_CObject* Allocate(Dart_CObject_Type type) { |
| Dart_CObject* result = zone()->Alloc<Dart_CObject>(1); |
| result->type = type; |
| return result; |
| } |
| |
| Dart_CObject* Ref(intptr_t index) const { |
| ASSERT(index > 0); |
| ASSERT(index <= next_ref_index_); |
| return refs_[index]; |
| } |
| |
| Dart_CObject* ReadRef() { return Ref(ReadUnsigned()); } |
| |
| void AddBaseObjects(); |
| Dart_CObject* Deserialize(); |
| |
| private: |
| Dart_CObject** refs_; |
| }; |
| |
| void MessageDeserializationCluster::ReadNodesWrapped(MessageDeserializer* d) { |
| start_index_ = d->next_index(); |
| this->ReadNodes(d); |
| stop_index_ = d->next_index(); |
| } |
| |
| void MessageDeserializationCluster::ReadNodesWrappedApi( |
| ApiMessageDeserializer* d) { |
| start_index_ = d->next_index(); |
| this->ReadNodesApi(d); |
| stop_index_ = d->next_index(); |
| } |
| |
| ObjectPtr MessageDeserializationCluster::PostLoadAbstractType( |
| MessageDeserializer* d) { |
| ClassFinalizer::FinalizationKind finalization = |
| is_canonical() ? ClassFinalizer::kCanonicalize |
| : ClassFinalizer::kFinalize; |
| AbstractType& type = AbstractType::Handle(d->zone()); |
| Code& code = Code::Handle(d->zone()); |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| type ^= d->Ref(id); |
| |
| code = TypeTestingStubGenerator::DefaultCodeForType(type); |
| type.InitializeTypeTestingStubNonAtomic(code); |
| |
| type ^= ClassFinalizer::FinalizeType(type, finalization); |
| d->UpdateRef(id, type); |
| } |
| return nullptr; |
| } |
| |
| ObjectPtr MessageDeserializationCluster::PostLoadLinkedHash( |
| MessageDeserializer* d) { |
| ASSERT(!is_canonical()); |
| Array& maps = Array::Handle(d->zone(), d->refs()); |
| maps = maps.Slice(start_index_, stop_index_ - start_index_, |
| /*with_type_argument=*/false); |
| return DartLibraryCalls::RehashObjectsInDartCollection(d->thread(), maps); |
| } |
| |
| class ClassMessageSerializationCluster : public MessageSerializationCluster { |
| public: |
| ClassMessageSerializationCluster() |
| : MessageSerializationCluster("Class", |
| MessagePhase::kBeforeTypes, |
| kClassCid), |
| objects_() {} |
| ~ClassMessageSerializationCluster() {} |
| |
| void Trace(MessageSerializer* s, Object* object) { |
| Class* cls = static_cast<Class*>(object); |
| objects_.Add(cls); |
| } |
| |
| void WriteNodes(MessageSerializer* s) { |
| const intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| Library& lib = Library::Handle(s->zone()); |
| String& str = String::Handle(s->zone()); |
| for (intptr_t i = 0; i < count; i++) { |
| Class* cls = objects_[i]; |
| s->AssignRef(cls); |
| intptr_t cid = cls->id(); |
| if (cid < kNumPredefinedCids) { |
| ASSERT(cid != 0); |
| s->WriteUnsigned(cid); |
| } else { |
| s->WriteUnsigned(0); |
| lib = cls->library(); |
| str = lib.url(); |
| s->WriteAscii(str); |
| str = cls->Name(); |
| s->WriteAscii(str); |
| } |
| } |
| } |
| |
| private: |
| GrowableArray<Class*> objects_; |
| }; |
| |
| class ClassMessageDeserializationCluster |
| : public MessageDeserializationCluster { |
| public: |
| ClassMessageDeserializationCluster() |
| : MessageDeserializationCluster("Class") {} |
| ~ClassMessageDeserializationCluster() {} |
| |
| void ReadNodes(MessageDeserializer* d) { |
| auto* class_table = d->isolate_group()->class_table(); |
| String& str = String::Handle(d->zone()); |
| Library& lib = Library::Handle(d->zone()); |
| Class& cls = Class::Handle(d->zone()); |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| intptr_t cid = d->ReadUnsigned(); |
| if (cid != 0) { |
| cls = class_table->At(cid); |
| } else { |
| str = String::New(d->ReadAscii()); // Library URI. |
| lib = Library::LookupLibrary(d->thread(), str); |
| RELEASE_ASSERT(!lib.IsNull()); |
| str = String::New(d->ReadAscii()); // Class name. |
| if (str.Equals(Symbols::TopLevel())) { |
| cls = lib.toplevel_class(); |
| } else { |
| cls = lib.LookupClass(str); |
| } |
| RELEASE_ASSERT(!cls.IsNull()); |
| cls.EnsureIsFinalized(d->thread()); |
| } |
| d->AssignRef(cls.ptr()); |
| } |
| } |
| |
| void ReadNodesApi(ApiMessageDeserializer* d) { |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| intptr_t cid = d->ReadUnsigned(); |
| if (cid == 0) { |
| d->ReadAscii(); // Library URI. |
| d->ReadAscii(); // Class name. |
| } |
| d->AssignRef(nullptr); |
| } |
| } |
| }; |
| |
| class TypeArgumentsMessageSerializationCluster |
| : public MessageSerializationCluster { |
| public: |
| explicit TypeArgumentsMessageSerializationCluster(bool is_canonical) |
| : MessageSerializationCluster("TypeArguments", |
| MessagePhase::kTypes, |
| kTypeArgumentsCid, |
| is_canonical) {} |
| ~TypeArgumentsMessageSerializationCluster() {} |
| |
| void Trace(MessageSerializer* s, Object* object) { |
| TypeArguments* type_args = static_cast<TypeArguments*>(object); |
| objects_.Add(type_args); |
| |
| s->Push(type_args->untag()->instantiations()); |
| intptr_t length = Smi::Value(type_args->untag()->length()); |
| for (intptr_t i = 0; i < length; i++) { |
| s->Push(type_args->untag()->element(i)); |
| } |
| } |
| |
| void WriteNodes(MessageSerializer* s) { |
| const intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| TypeArguments* type_args = objects_[i]; |
| s->AssignRef(type_args); |
| intptr_t length = Smi::Value(type_args->untag()->length()); |
| s->WriteUnsigned(length); |
| } |
| } |
| |
| void WriteEdges(MessageSerializer* s) { |
| const intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| TypeArguments* type_args = objects_[i]; |
| intptr_t hash = Smi::Value(type_args->untag()->hash()); |
| s->Write<int32_t>(hash); |
| const intptr_t nullability = |
| Smi::Value(type_args->untag()->nullability()); |
| s->WriteUnsigned(nullability); |
| |
| intptr_t length = Smi::Value(type_args->untag()->length()); |
| s->WriteUnsigned(length); |
| for (intptr_t j = 0; j < length; j++) { |
| s->WriteRef(type_args->untag()->element(j)); |
| } |
| } |
| } |
| |
| private: |
| GrowableArray<TypeArguments*> objects_; |
| }; |
| |
| class TypeArgumentsMessageDeserializationCluster |
| : public MessageDeserializationCluster { |
| public: |
| explicit TypeArgumentsMessageDeserializationCluster(bool is_canonical) |
| : MessageDeserializationCluster("TypeArguments", is_canonical) {} |
| ~TypeArgumentsMessageDeserializationCluster() {} |
| |
| void ReadNodes(MessageDeserializer* d) { |
| const intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| intptr_t length = d->ReadUnsigned(); |
| d->AssignRef(TypeArguments::New(length)); |
| } |
| } |
| |
| void ReadEdges(MessageDeserializer* d) { |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| TypeArgumentsPtr type_args = static_cast<TypeArgumentsPtr>(d->Ref(id)); |
| |
| type_args->untag()->hash_ = Smi::New(d->Read<int32_t>()); |
| type_args->untag()->nullability_ = Smi::New(d->ReadUnsigned()); |
| |
| intptr_t length = d->ReadUnsigned(); |
| for (intptr_t j = 0; j < length; j++) { |
| type_args->untag()->types()[j] = |
| static_cast<AbstractTypePtr>(d->ReadRef()); |
| } |
| } |
| } |
| |
| ObjectPtr PostLoad(MessageDeserializer* d) { |
| if (is_canonical()) { |
| TypeArguments& type_args = TypeArguments::Handle(d->zone()); |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| type_args ^= d->Ref(id); |
| type_args ^= type_args.Canonicalize(d->thread()); |
| d->UpdateRef(id, type_args); |
| } |
| } |
| return nullptr; |
| } |
| |
| void ReadNodesApi(ApiMessageDeserializer* d) { |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| d->ReadUnsigned(); // Length. |
| d->AssignRef(nullptr); |
| } |
| } |
| |
| void ReadEdgesApi(ApiMessageDeserializer* d) { |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| d->Read<int32_t>(); // Hash. |
| d->ReadUnsigned(); // Nullability. |
| intptr_t length = d->ReadUnsigned(); |
| for (intptr_t j = 0; j < length; j++) { |
| d->ReadRef(); // Element. |
| } |
| } |
| } |
| }; |
| |
| class FunctionMessageSerializationCluster : public MessageSerializationCluster { |
| public: |
| FunctionMessageSerializationCluster() |
| : MessageSerializationCluster("Function", |
| MessagePhase::kBeforeTypes, |
| kFunctionCid) {} |
| ~FunctionMessageSerializationCluster() {} |
| |
| void Trace(MessageSerializer* s, Object* object) { |
| Function* func = static_cast<Function*>(object); |
| objects_.Add(func); |
| } |
| |
| void WriteNodes(MessageSerializer* s) { |
| const intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| Library& lib = Library::Handle(s->zone()); |
| Class& cls = Class::Handle(s->zone()); |
| String& str = String::Handle(s->zone()); |
| for (intptr_t i = 0; i < count; i++) { |
| Function* func = objects_[i]; |
| s->AssignRef(func); |
| cls ^= func->Owner(); |
| lib = cls.library(); |
| str = lib.url(); |
| s->WriteAscii(str); |
| str = cls.Name(); |
| s->WriteAscii(str); |
| str = func->name(); |
| s->WriteAscii(str); |
| } |
| } |
| |
| private: |
| GrowableArray<Function*> objects_; |
| }; |
| |
| class FunctionMessageDeserializationCluster |
| : public MessageDeserializationCluster { |
| public: |
| FunctionMessageDeserializationCluster() |
| : MessageDeserializationCluster("Function") {} |
| ~FunctionMessageDeserializationCluster() {} |
| |
| void ReadNodes(MessageDeserializer* d) { |
| const intptr_t count = d->ReadUnsigned(); |
| String& str = String::Handle(d->zone()); |
| Library& lib = Library::Handle(d->zone()); |
| Class& cls = Class::Handle(d->zone()); |
| Function& func = Function::Handle(d->zone()); |
| for (intptr_t i = 0; i < count; i++) { |
| str = String::New(d->ReadAscii()); // Library URI. |
| lib = Library::LookupLibrary(d->thread(), str); |
| RELEASE_ASSERT(!lib.IsNull()); |
| str = String::New(d->ReadAscii()); // Class name. |
| if (str.Equals(Symbols::TopLevel())) { |
| cls = lib.toplevel_class(); |
| } else { |
| cls = lib.LookupClass(str); |
| } |
| RELEASE_ASSERT(!cls.IsNull()); |
| cls.EnsureIsFinalized(d->thread()); |
| str = String::New(d->ReadAscii()); // Function name. |
| func = cls.LookupStaticFunction(str); |
| RELEASE_ASSERT(!func.IsNull()); |
| d->AssignRef(func.ptr()); |
| } |
| } |
| }; |
| |
| class InstanceMessageSerializationCluster : public MessageSerializationCluster { |
| public: |
| InstanceMessageSerializationCluster(bool is_canonical, intptr_t cid) |
| : MessageSerializationCluster("Instance", |
| is_canonical |
| ? MessagePhase::kCanonicalInstances |
| : MessagePhase::kNonCanonicalInstances, |
| cid, |
| is_canonical), |
| cls_(Class::Handle()) { |
| cls_ = IsolateGroup::Current()->class_table()->At(cid); |
| next_field_offset_ = cls_.host_next_field_offset(); |
| } |
| ~InstanceMessageSerializationCluster() {} |
| |
| void Trace(MessageSerializer* s, Object* object) { |
| Instance* instance = static_cast<Instance*>(object); |
| objects_.Add(instance); |
| |
| const intptr_t next_field_offset = next_field_offset_; |
| #if defined(DART_PRECOMPILED_RUNTIME) |
| const auto unboxed_fields_bitmap = |
| s->isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt(cid_); |
| #endif |
| for (intptr_t offset = Instance::NextFieldOffset(); |
| offset < next_field_offset; offset += kCompressedWordSize) { |
| #if defined(DART_PRECOMPILED_RUNTIME) |
| if (unboxed_fields_bitmap.Get(offset / kCompressedWordSize)) { |
| continue; |
| } |
| #endif |
| s->Push(reinterpret_cast<CompressedObjectPtr*>( |
| reinterpret_cast<uword>(instance->untag()) + offset) |
| ->Decompress(instance->untag()->heap_base())); |
| } |
| } |
| |
| void WriteNodes(MessageSerializer* s) { |
| s->WriteRef(cls_.ptr()); |
| |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| Instance* instance = objects_[i]; |
| s->AssignRef(instance); |
| } |
| } |
| |
| void WriteEdges(MessageSerializer* s) { |
| const intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| Instance* instance = objects_[i]; |
| |
| const intptr_t next_field_offset = next_field_offset_; |
| #if defined(DART_PRECOMPILED_RUNTIME) |
| const auto unboxed_fields_bitmap = |
| s->isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt(cid_); |
| #endif |
| for (intptr_t offset = Instance::NextFieldOffset(); |
| offset < next_field_offset; offset += kCompressedWordSize) { |
| #if defined(DART_PRECOMPILED_RUNTIME) |
| if (unboxed_fields_bitmap.Get(offset / kCompressedWordSize)) { |
| // Writes 32 bits of the unboxed value at a time |
| const uword value = *reinterpret_cast<compressed_uword*>( |
| reinterpret_cast<uword>(instance->untag()) + offset); |
| s->WriteWordWith32BitWrites(value); |
| continue; |
| } |
| #endif |
| s->WriteRef(reinterpret_cast<CompressedObjectPtr*>( |
| reinterpret_cast<uword>(instance->untag()) + offset) |
| ->Decompress(instance->untag()->heap_base())); |
| } |
| } |
| } |
| |
| private: |
| Class& cls_; |
| intptr_t next_field_offset_; |
| GrowableArray<Instance*> objects_; |
| }; |
| |
| class InstanceMessageDeserializationCluster |
| : public MessageDeserializationCluster { |
| public: |
| explicit InstanceMessageDeserializationCluster(bool is_canonical) |
| : MessageDeserializationCluster("Instance", is_canonical), |
| cls_(Class::Handle()), |
| field_stores_(GrowableObjectArray::Handle(GrowableObjectArray::New())) { |
| } |
| ~InstanceMessageDeserializationCluster() {} |
| |
| void ReadNodes(MessageDeserializer* d) { |
| cls_ ^= d->ReadRef(); |
| |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| d->AssignRef(Instance::New(cls_)); |
| } |
| } |
| |
| void ReadEdges(MessageDeserializer* d) { |
| const intptr_t next_field_offset = cls_.host_next_field_offset(); |
| #if defined(DART_PRECOMPILED_RUNTIME) |
| const auto unboxed_fields_bitmap = |
| d->isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt( |
| cls_.id()); |
| #else |
| const intptr_t type_argument_field_offset = |
| cls_.host_type_arguments_field_offset(); |
| const bool use_field_guards = d->isolate_group()->use_field_guards(); |
| const Array& field_map = Array::Handle(d->zone(), cls_.OffsetToFieldMap()); |
| Field& field = Field::Handle(d->zone()); |
| #endif |
| Instance& instance = Instance::Handle(d->zone()); |
| Object& value = Object::Handle(d->zone()); |
| |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| instance ^= d->Ref(id); |
| for (intptr_t offset = Instance::NextFieldOffset(); |
| offset < next_field_offset; offset += kCompressedWordSize) { |
| #if defined(DART_PRECOMPILED_RUNTIME) |
| if (unboxed_fields_bitmap.Get(offset / kCompressedWordSize)) { |
| compressed_uword* p = reinterpret_cast<compressed_uword*>( |
| reinterpret_cast<uword>(instance.untag()) + offset); |
| // Reads 32 bits of the unboxed value at a time |
| *p = d->ReadWordWith32BitReads(); |
| continue; |
| } |
| #endif |
| value = d->ReadRef(); |
| instance.SetFieldAtOffset(offset, value); |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| if (use_field_guards && (offset != type_argument_field_offset) && |
| (value.ptr() != Object::sentinel().ptr())) { |
| field ^= field_map.At(offset >> kCompressedWordSizeLog2); |
| ASSERT(!field.IsNull()); |
| ASSERT(field.HostOffset() == offset); |
| field_stores_.Add(field); |
| field_stores_.Add(value); |
| } |
| #endif |
| } |
| } |
| } |
| |
| ObjectPtr PostLoad(MessageDeserializer* d) { |
| if (is_canonical()) { |
| SafepointMutexLocker ml( |
| d->isolate_group()->constant_canonicalization_mutex()); |
| Instance& instance = Instance::Handle(d->zone()); |
| for (intptr_t i = start_index_; i < stop_index_; i++) { |
| instance ^= d->Ref(i); |
| instance = instance.CanonicalizeLocked(d->thread()); |
| d->UpdateRef(i, instance); |
| } |
| } |
| |
| if (cls_.ptr() == d->isolate_group()->object_store()->expando_class()) { |
| const auto& expandos = |
| Array::Handle(d->zone(), Array::New(stop_index_ - start_index_)); |
| auto& instance = Instance::Handle(d->zone()); |
| for (intptr_t i = start_index_, j = 0; i < stop_index_; i++, j++) { |
| instance ^= d->Ref(i); |
| expandos.SetAt(j, instance); |
| } |
| return DartLibraryCalls::RehashObjectsInDartCore(d->thread(), expandos); |
| } |
| |
| Field& field = Field::Handle(d->zone()); |
| Object& value = Object::Handle(d->zone()); |
| for (int i = 0; i < field_stores_.Length(); i += 2) { |
| field ^= field_stores_.At(i); |
| value = field_stores_.At(i + 1); |
| field.RecordStore(value); |
| } |
| |
| return nullptr; |
| } |
| |
| private: |
| Class& cls_; |
| GrowableObjectArray& field_stores_; |
| }; |
| |
| class TypeMessageSerializationCluster : public MessageSerializationCluster { |
| public: |
| explicit TypeMessageSerializationCluster(bool is_canonical) |
| : MessageSerializationCluster("Type", |
| MessagePhase::kTypes, |
| kTypeCid, |
| is_canonical) {} |
| ~TypeMessageSerializationCluster() {} |
| |
| void Trace(MessageSerializer* s, Object* object) { |
| Type* type = static_cast<Type*>(object); |
| objects_.Add(type); |
| |
| s->Push(type->type_class()); |
| s->Push(type->arguments()); |
| } |
| |
| void WriteNodes(MessageSerializer* s) { |
| const intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| Type* type = objects_[i]; |
| s->AssignRef(type); |
| } |
| } |
| |
| void WriteEdges(MessageSerializer* s) { |
| const intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| Type* type = objects_[i]; |
| s->WriteRef(type->type_class()); |
| s->WriteRef(type->arguments()); |
| s->Write<uint8_t>(static_cast<uint8_t>(type->nullability())); |
| } |
| } |
| |
| private: |
| GrowableArray<Type*> objects_; |
| }; |
| |
| class TypeMessageDeserializationCluster : public MessageDeserializationCluster { |
| public: |
| explicit TypeMessageDeserializationCluster(bool is_canonical) |
| : MessageDeserializationCluster("Type", is_canonical) {} |
| ~TypeMessageDeserializationCluster() {} |
| |
| void ReadNodes(MessageDeserializer* d) { |
| const intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| d->AssignRef(Type::New()); |
| } |
| } |
| |
| void ReadEdges(MessageDeserializer* d) { |
| Class& cls = Class::Handle(d->zone()); |
| Type& type = Type::Handle(d->zone()); |
| TypeArguments& type_args = TypeArguments::Handle(d->zone()); |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| type ^= d->Ref(id); |
| cls ^= d->ReadRef(); |
| type.set_type_class(cls); |
| type_args ^= d->ReadRef(); |
| type.set_arguments(type_args); |
| type.untag()->set_hash(Smi::New(0)); |
| type.set_nullability(static_cast<Nullability>(d->Read<uint8_t>())); |
| type.SetIsFinalized(); |
| } |
| } |
| |
| ObjectPtr PostLoad(MessageDeserializer* d) { return PostLoadAbstractType(d); } |
| |
| void ReadNodesApi(ApiMessageDeserializer* d) { |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| d->AssignRef(nullptr); |
| } |
| } |
| |
| void ReadEdgesApi(ApiMessageDeserializer* d) { |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| d->ReadRef(); // Class. |
| d->ReadRef(); // Type arguments. |
| d->Read<uint8_t>(); // Nullability. |
| } |
| } |
| }; |
| |
| class TypeRefMessageSerializationCluster : public MessageSerializationCluster { |
| public: |
| explicit TypeRefMessageSerializationCluster(bool is_canonical) |
| : MessageSerializationCluster("TypeRef", |
| MessagePhase::kTypes, |
| kTypeRefCid, |
| is_canonical) {} |
| ~TypeRefMessageSerializationCluster() {} |
| |
| void Trace(MessageSerializer* s, Object* object) { |
| TypeRef* type = static_cast<TypeRef*>(object); |
| objects_.Add(type); |
| |
| s->Push(type->type()); |
| } |
| |
| void WriteNodes(MessageSerializer* s) { |
| const intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| TypeRef* type = objects_[i]; |
| s->AssignRef(type); |
| } |
| } |
| |
| void WriteEdges(MessageSerializer* s) { |
| const intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| TypeRef* type = objects_[i]; |
| s->WriteRef(type->type()); |
| } |
| } |
| |
| private: |
| GrowableArray<TypeRef*> objects_; |
| }; |
| |
| class TypeRefMessageDeserializationCluster |
| : public MessageDeserializationCluster { |
| public: |
| explicit TypeRefMessageDeserializationCluster(bool is_canonical) |
| : MessageDeserializationCluster("TypeRef", is_canonical) {} |
| ~TypeRefMessageDeserializationCluster() {} |
| |
| void ReadNodes(MessageDeserializer* d) { |
| const intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| d->AssignRef(TypeRef::New()); |
| } |
| } |
| |
| void ReadEdges(MessageDeserializer* d) { |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| TypeRefPtr type = static_cast<TypeRefPtr>(d->Ref(id)); |
| type->untag()->set_type(static_cast<AbstractTypePtr>(d->ReadRef())); |
| } |
| } |
| |
| ObjectPtr PostLoad(MessageDeserializer* d) { |
| ClassFinalizer::FinalizationKind finalization = |
| is_canonical() ? ClassFinalizer::kCanonicalize |
| : ClassFinalizer::kFinalize; |
| Code& code = Code::Handle(d->zone()); |
| TypeRef& type = TypeRef::Handle(d->zone()); |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| type ^= d->Ref(id); |
| type ^= ClassFinalizer::FinalizeType(type, finalization); |
| d->UpdateRef(id, type); |
| |
| code = TypeTestingStubGenerator::DefaultCodeForType(type); |
| type.InitializeTypeTestingStubNonAtomic(code); |
| } |
| return nullptr; |
| } |
| |
| void ReadNodesApi(ApiMessageDeserializer* d) { |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| d->AssignRef(nullptr); |
| } |
| } |
| |
| void ReadEdgesApi(ApiMessageDeserializer* d) { |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| d->ReadRef(); // Type. |
| } |
| } |
| }; |
| |
| class ClosureMessageSerializationCluster : public MessageSerializationCluster { |
| public: |
| explicit ClosureMessageSerializationCluster(bool is_canonical) |
| : MessageSerializationCluster("Closure", |
| MessagePhase::kCanonicalInstances, |
| kClosureCid, |
| is_canonical) {} |
| ~ClosureMessageSerializationCluster() {} |
| |
| void Trace(MessageSerializer* s, Object* object) { |
| Closure* closure = static_cast<Closure*>(object); |
| |
| if (!s->can_send_any_object() || |
| !Function::IsImplicitStaticClosureFunction(closure->function())) { |
| const char* message = OS::SCreate( |
| s->zone(), |
| "Illegal argument in isolate message : (object is a closure - %s)", |
| Function::Handle(closure->function()).ToCString()); |
| s->IllegalObject(*object, message); |
| } |
| |
| objects_.Add(closure); |
| |
| s->Push(closure->function()); |
| s->Push(closure->delayed_type_arguments()); |
| } |
| |
| void WriteNodes(MessageSerializer* s) { |
| const intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| Closure* closure = objects_[i]; |
| s->AssignRef(closure); |
| s->WriteRef(closure->function()); |
| s->WriteRef(closure->delayed_type_arguments()); |
| } |
| } |
| |
| private: |
| GrowableArray<Closure*> objects_; |
| }; |
| |
| class ClosureMessageDeserializationCluster |
| : public MessageDeserializationCluster { |
| public: |
| explicit ClosureMessageDeserializationCluster(bool is_canonical) |
| : MessageDeserializationCluster("Closure", is_canonical) {} |
| ~ClosureMessageDeserializationCluster() {} |
| |
| void ReadNodes(MessageDeserializer* d) { |
| const Context& null_context = Context::Handle(d->zone()); |
| TypeArguments& delayed_type_arguments = TypeArguments::Handle(d->zone()); |
| Function& func = Function::Handle(d->zone()); |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| func ^= d->ReadRef(); |
| ASSERT(func.is_static()); |
| func = func.ImplicitClosureFunction(); |
| delayed_type_arguments ^= d->ReadRef(); |
| if (delayed_type_arguments.IsNull()) { |
| d->AssignRef(func.ImplicitStaticClosure()); |
| } else { |
| // If delayed type arguments were provided, create and return new |
| // closure with those, otherwise return associated implicit static |
| // closure. Note that static closures can't have instantiator or |
| // function types since statics can't refer to class type arguments, |
| // don't have outer functions. |
| d->AssignRef(Closure::New( |
| /*instantiator_type_arguments=*/Object::null_type_arguments(), |
| /*function_type_arguments=*/Object::null_type_arguments(), |
| delayed_type_arguments, func, null_context, Heap::kOld)); |
| } |
| } |
| } |
| }; |
| |
| class SmiMessageSerializationCluster : public MessageSerializationCluster { |
| public: |
| explicit SmiMessageSerializationCluster(Zone* zone) |
| : MessageSerializationCluster("Smi", |
| MessagePhase::kBeforeTypes, |
| kSmiCid, |
| true), |
| objects_(zone, 0) {} |
| ~SmiMessageSerializationCluster() {} |
| |
| void Trace(MessageSerializer* s, Object* object) { |
| Smi* smi = static_cast<Smi*>(object); |
| objects_.Add(smi); |
| } |
| |
| void WriteNodes(MessageSerializer* s) { |
| const intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| Smi* smi = static_cast<Smi*>(objects_[i]); |
| s->AssignRef(smi); |
| s->Write<intptr_t>(smi->Value()); |
| } |
| } |
| |
| void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) { |
| objects_.Add(reinterpret_cast<Smi*>(object)); |
| } |
| |
| void WriteNodesApi(ApiMessageSerializer* s) { |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| Dart_CObject* smi = reinterpret_cast<Dart_CObject*>(objects_[i]); |
| s->AssignRef(smi); |
| intptr_t value = smi->type == Dart_CObject_kInt32 ? smi->value.as_int32 |
| : smi->value.as_int64; |
| s->Write<intptr_t>(value); |
| } |
| } |
| |
| private: |
| GrowableArray<Smi*> objects_; |
| }; |
| |
| class SmiMessageDeserializationCluster : public MessageDeserializationCluster { |
| public: |
| SmiMessageDeserializationCluster() |
| : MessageDeserializationCluster("Smi", true) {} |
| ~SmiMessageDeserializationCluster() {} |
| |
| void ReadNodes(MessageDeserializer* d) { |
| const intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| d->AssignRef(Smi::New(d->Read<intptr_t>())); |
| } |
| } |
| |
| void ReadNodesApi(ApiMessageDeserializer* d) { |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| intptr_t value = d->Read<intptr_t>(); |
| Dart_CObject* smi; |
| if ((kMinInt32 <= value) && (value <= kMaxInt32)) { |
| smi = d->Allocate(Dart_CObject_kInt32); |
| smi->value.as_int32 = value; |
| } else { |
| smi = d->Allocate(Dart_CObject_kInt64); |
| smi->value.as_int64 = value; |
| } |
| d->AssignRef(smi); |
| } |
| } |
| }; |
| |
| class MintMessageSerializationCluster : public MessageSerializationCluster { |
| public: |
| explicit MintMessageSerializationCluster(Zone* zone, bool is_canonical) |
| : MessageSerializationCluster("Mint", |
| MessagePhase::kBeforeTypes, |
| kMintCid, |
| is_canonical), |
| objects_(zone, 0) {} |
| ~MintMessageSerializationCluster() {} |
| |
| void Trace(MessageSerializer* s, Object* object) { |
| Mint* mint = static_cast<Mint*>(object); |
| objects_.Add(mint); |
| } |
| |
| void WriteNodes(MessageSerializer* s) { |
| const intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| Mint* mint = static_cast<Mint*>(objects_[i]); |
| s->AssignRef(mint); |
| s->Write<int64_t>(mint->value()); |
| } |
| } |
| |
| void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) { |
| objects_.Add(reinterpret_cast<Mint*>(object)); |
| } |
| |
| void WriteNodesApi(ApiMessageSerializer* s) { |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| Dart_CObject* mint = reinterpret_cast<Dart_CObject*>(objects_[i]); |
| s->AssignRef(mint); |
| int64_t value = mint->type == Dart_CObject_kInt32 ? mint->value.as_int32 |
| : mint->value.as_int64; |
| s->Write<int64_t>(value); |
| } |
| } |
| |
| private: |
| GrowableArray<Mint*> objects_; |
| }; |
| |
| class MintMessageDeserializationCluster : public MessageDeserializationCluster { |
| public: |
| explicit MintMessageDeserializationCluster(bool is_canonical) |
| : MessageDeserializationCluster("int", is_canonical) {} |
| ~MintMessageDeserializationCluster() {} |
| |
| void ReadNodes(MessageDeserializer* d) { |
| const intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| int64_t value = d->Read<int64_t>(); |
| d->AssignRef(is_canonical() ? Mint::NewCanonical(value) |
| : Mint::New(value)); |
| } |
| } |
| |
| void ReadNodesApi(ApiMessageDeserializer* d) { |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| int64_t value = d->Read<int64_t>(); |
| Dart_CObject* mint; |
| if ((kMinInt32 <= value) && (value <= kMaxInt32)) { |
| mint = d->Allocate(Dart_CObject_kInt32); |
| mint->value.as_int32 = value; |
| } else { |
| mint = d->Allocate(Dart_CObject_kInt64); |
| mint->value.as_int64 = value; |
| } |
| d->AssignRef(mint); |
| } |
| } |
| }; |
| |
| class DoubleMessageSerializationCluster : public MessageSerializationCluster { |
| public: |
| explicit DoubleMessageSerializationCluster(Zone* zone, bool is_canonical) |
| : MessageSerializationCluster("double", |
| MessagePhase::kBeforeTypes, |
| kDoubleCid, |
| is_canonical), |
| objects_(zone, 0) {} |
| |
| ~DoubleMessageSerializationCluster() {} |
| |
| void Trace(MessageSerializer* s, Object* object) { |
| Double* dbl = static_cast<Double*>(object); |
| objects_.Add(dbl); |
| } |
| |
| void WriteNodes(MessageSerializer* s) { |
| const intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| Double* dbl = objects_[i]; |
| s->AssignRef(dbl); |
| s->Write<double>(dbl->untag()->value_); |
| } |
| } |
| |
| void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) { |
| objects_.Add(reinterpret_cast<Double*>(object)); |
| } |
| |
| void WriteNodesApi(ApiMessageSerializer* s) { |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| Dart_CObject* dbl = reinterpret_cast<Dart_CObject*>(objects_[i]); |
| s->AssignRef(dbl); |
| s->Write<double>(dbl->value.as_double); |
| } |
| } |
| |
| private: |
| GrowableArray<Double*> objects_; |
| }; |
| |
| class DoubleMessageDeserializationCluster |
| : public MessageDeserializationCluster { |
| public: |
| explicit DoubleMessageDeserializationCluster(bool is_canonical) |
| : MessageDeserializationCluster("double", is_canonical) {} |
| ~DoubleMessageDeserializationCluster() {} |
| |
| void ReadNodes(MessageDeserializer* d) { |
| const intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| double value = d->Read<double>(); |
| d->AssignRef(is_canonical() ? Double::NewCanonical(value) |
| : Double::New(value)); |
| } |
| } |
| |
| void ReadNodesApi(ApiMessageDeserializer* d) { |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| Dart_CObject* dbl = d->Allocate(Dart_CObject_kDouble); |
| dbl->value.as_double = d->Read<double>(); |
| d->AssignRef(dbl); |
| } |
| } |
| }; |
| |
| class GrowableObjectArrayMessageSerializationCluster |
| : public MessageSerializationCluster { |
| public: |
| GrowableObjectArrayMessageSerializationCluster() |
| : MessageSerializationCluster("GrowableObjectArray", |
| MessagePhase::kNonCanonicalInstances, |
| kGrowableObjectArrayCid) {} |
| ~GrowableObjectArrayMessageSerializationCluster() {} |
| |
| void Trace(MessageSerializer* s, Object* object) { |
| GrowableObjectArray* array = static_cast<GrowableObjectArray*>(object); |
| objects_.Add(array); |
| |
| s->Push(array->GetTypeArguments()); |
| for (intptr_t i = 0, n = array->Length(); i < n; i++) { |
| s->Push(array->At(i)); |
| } |
| } |
| |
| void WriteNodes(MessageSerializer* s) { |
| const intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| GrowableObjectArray* array = objects_[i]; |
| s->WriteUnsigned(array->Length()); |
| s->AssignRef(array); |
| } |
| } |
| |
| void WriteEdges(MessageSerializer* s) { |
| const intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| GrowableObjectArray* array = objects_[i]; |
| s->WriteRef(array->GetTypeArguments()); |
| for (intptr_t i = 0, n = array->Length(); i < n; i++) { |
| s->WriteRef(array->At(i)); |
| } |
| } |
| } |
| |
| private: |
| GrowableArray<GrowableObjectArray*> objects_; |
| }; |
| |
| class GrowableObjectArrayMessageDeserializationCluster |
| : public MessageDeserializationCluster { |
| public: |
| GrowableObjectArrayMessageDeserializationCluster() |
| : MessageDeserializationCluster("GrowableObjectArray") {} |
| ~GrowableObjectArrayMessageDeserializationCluster() {} |
| |
| void ReadNodes(MessageDeserializer* d) { |
| const intptr_t count = d->ReadUnsigned(); |
| GrowableObjectArray& array = GrowableObjectArray::Handle(d->zone()); |
| for (intptr_t i = 0; i < count; i++) { |
| intptr_t length = d->ReadUnsigned(); |
| array = GrowableObjectArray::New(length); // Here length is capacity. |
| array.SetLength(length); |
| d->AssignRef(array.ptr()); |
| } |
| } |
| |
| void ReadEdges(MessageDeserializer* d) { |
| GrowableObjectArray& array = GrowableObjectArray::Handle(d->zone()); |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| array ^= d->Ref(id); |
| array.untag()->set_type_arguments( |
| static_cast<TypeArgumentsPtr>(d->ReadRef())); |
| for (intptr_t i = 0, n = array.Length(); i < n; i++) { |
| array.untag()->data()->untag()->set_element(i, d->ReadRef()); |
| } |
| } |
| } |
| |
| ObjectPtr PostLoad(MessageDeserializer* d) { |
| ASSERT(!is_canonical()); |
| return nullptr; |
| } |
| |
| void ReadNodesApi(ApiMessageDeserializer* d) { |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| Dart_CObject* array = d->Allocate(Dart_CObject_kArray); |
| intptr_t length = d->ReadUnsigned(); |
| array->value.as_array.length = length; |
| if (length > 0) { |
| array->value.as_array.values = d->zone()->Alloc<Dart_CObject*>(length); |
| } else { |
| ASSERT(length == 0); |
| array->value.as_array.values = NULL; |
| } |
| d->AssignRef(array); |
| } |
| } |
| |
| void ReadEdgesApi(ApiMessageDeserializer* d) { |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| Dart_CObject* array = d->Ref(id); |
| intptr_t length = array->value.as_array.length; |
| d->ReadRef(); // type_arguments |
| for (intptr_t i = 0; i < length; i++) { |
| array->value.as_array.values[i] = d->ReadRef(); |
| } |
| } |
| } |
| }; |
| |
| class TypedDataMessageSerializationCluster |
| : public MessageSerializationCluster { |
| public: |
| explicit TypedDataMessageSerializationCluster(Zone* zone, intptr_t cid) |
| : MessageSerializationCluster("TypedData", |
| MessagePhase::kNonCanonicalInstances, |
| cid), |
| objects_(zone, 0) {} |
| ~TypedDataMessageSerializationCluster() {} |
| |
| void Trace(MessageSerializer* s, Object* object) { |
| TypedData* data = static_cast<TypedData*>(object); |
| objects_.Add(data); |
| } |
| |
| void WriteNodes(MessageSerializer* s) { |
| intptr_t element_size = TypedData::ElementSizeInBytes(cid_); |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| TypedData* data = objects_[i]; |
| s->AssignRef(data); |
| intptr_t length = data->Length(); |
| s->WriteUnsigned(length); |
| NoSafepointScope no_safepoint; |
| uint8_t* cdata = reinterpret_cast<uint8_t*>(data->untag()->data()); |
| s->WriteBytes(cdata, length * element_size); |
| } |
| } |
| |
| void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) { |
| objects_.Add(reinterpret_cast<TypedData*>(object)); |
| } |
| |
| void WriteNodesApi(ApiMessageSerializer* s) { |
| intptr_t element_size = TypedData::ElementSizeInBytes(cid_); |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| Dart_CObject* data = reinterpret_cast<Dart_CObject*>(objects_[i]); |
| s->AssignRef(data); |
| intptr_t length = data->value.as_external_typed_data.length; |
| s->WriteUnsigned(length); |
| uint8_t* cdata = |
| reinterpret_cast<uint8_t*>(data->value.as_typed_data.values); |
| s->WriteBytes(cdata, length * element_size); |
| } |
| } |
| |
| private: |
| GrowableArray<TypedData*> objects_; |
| }; |
| |
| class TypedDataMessageDeserializationCluster |
| : public MessageDeserializationCluster { |
| public: |
| explicit TypedDataMessageDeserializationCluster(intptr_t cid) |
| : MessageDeserializationCluster("TypedData"), cid_(cid) {} |
| ~TypedDataMessageDeserializationCluster() {} |
| |
| void ReadNodes(MessageDeserializer* d) { |
| intptr_t element_size = TypedData::ElementSizeInBytes(cid_); |
| intptr_t count = d->ReadUnsigned(); |
| TypedData& data = TypedData::Handle(d->zone()); |
| for (intptr_t i = 0; i < count; i++) { |
| intptr_t length = d->ReadUnsigned(); |
| data = TypedData::New(cid_, length); |
| d->AssignRef(data.ptr()); |
| const intptr_t length_in_bytes = length * element_size; |
| NoSafepointScope no_safepoint; |
| d->ReadBytes(data.untag()->data(), length_in_bytes); |
| } |
| } |
| |
| void ReadNodesApi(ApiMessageDeserializer* d) { |
| Dart_TypedData_Type type; |
| switch (cid_) { |
| case kTypedDataInt8ArrayCid: |
| type = Dart_TypedData_kInt8; |
| break; |
| case kTypedDataUint8ArrayCid: |
| type = Dart_TypedData_kUint8; |
| break; |
| case kTypedDataUint8ClampedArrayCid: |
| type = Dart_TypedData_kUint8Clamped; |
| break; |
| case kTypedDataInt16ArrayCid: |
| type = Dart_TypedData_kInt16; |
| break; |
| case kTypedDataUint16ArrayCid: |
| type = Dart_TypedData_kUint16; |
| break; |
| case kTypedDataInt32ArrayCid: |
| type = Dart_TypedData_kInt32; |
| break; |
| case kTypedDataUint32ArrayCid: |
| type = Dart_TypedData_kUint32; |
| break; |
| case kTypedDataInt64ArrayCid: |
| type = Dart_TypedData_kInt64; |
| break; |
| case kTypedDataUint64ArrayCid: |
| type = Dart_TypedData_kUint64; |
| break; |
| case kTypedDataFloat32ArrayCid: |
| type = Dart_TypedData_kFloat32; |
| break; |
| case kTypedDataFloat64ArrayCid: |
| type = Dart_TypedData_kFloat64; |
| break; |
| case kTypedDataInt32x4ArrayCid: |
| type = Dart_TypedData_kInt32x4; |
| break; |
| case kTypedDataFloat32x4ArrayCid: |
| type = Dart_TypedData_kFloat32x4; |
| break; |
| case kTypedDataFloat64x2ArrayCid: |
| type = Dart_TypedData_kFloat64x2; |
| break; |
| default: |
| UNREACHABLE(); |
| } |
| |
| intptr_t element_size = TypedData::ElementSizeInBytes(cid_); |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| Dart_CObject* data = d->Allocate(Dart_CObject_kTypedData); |
| intptr_t length = d->ReadUnsigned(); |
| data->value.as_typed_data.type = type; |
| data->value.as_typed_data.length = length; |
| if (length == 0) { |
| data->value.as_typed_data.values = NULL; |
| } else { |
| data->value.as_typed_data.values = |
| const_cast<uint8_t*>(d->CurrentBufferAddress()); |
| d->Advance(length * element_size); |
| } |
| d->AssignRef(data); |
| } |
| } |
| |
| private: |
| const intptr_t cid_; |
| }; |
| |
| // This function's name can appear in Observatory. |
| static void IsolateMessageTypedDataFinalizer(void* isolate_callback_data, |
| void* buffer) { |
| free(buffer); |
| } |
| |
| class ExternalTypedDataMessageSerializationCluster |
| : public MessageSerializationCluster { |
| public: |
| explicit ExternalTypedDataMessageSerializationCluster(Zone* zone, |
| intptr_t cid) |
| : MessageSerializationCluster("ExternalTypedData", |
| MessagePhase::kNonCanonicalInstances, |
| cid), |
| objects_(zone, 0) {} |
| ~ExternalTypedDataMessageSerializationCluster() {} |
| |
| void Trace(MessageSerializer* s, Object* object) { |
| ExternalTypedData* data = static_cast<ExternalTypedData*>(object); |
| objects_.Add(data); |
| } |
| |
| void WriteNodes(MessageSerializer* s) { |
| intptr_t element_size = ExternalTypedData::ElementSizeInBytes(cid_); |
| |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| ExternalTypedData* data = objects_[i]; |
| s->AssignRef(data); |
| intptr_t length = Smi::Value(data->untag()->length_); |
| s->WriteUnsigned(length); |
| |
| intptr_t length_in_bytes = length * element_size; |
| void* passed_data = malloc(length_in_bytes); |
| memmove(passed_data, data->untag()->data_, length_in_bytes); |
| s->finalizable_data()->Put(length_in_bytes, |
| passed_data, // data |
| passed_data, // peer, |
| IsolateMessageTypedDataFinalizer); |
| } |
| } |
| |
| void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) { |
| objects_.Add(reinterpret_cast<ExternalTypedData*>(object)); |
| } |
| |
| void WriteNodesApi(ApiMessageSerializer* s) { |
| intptr_t element_size = ExternalTypedData::ElementSizeInBytes(cid_); |
| |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| Dart_CObject* data = reinterpret_cast<Dart_CObject*>(objects_[i]); |
| s->AssignRef(data); |
| |
| intptr_t length = data->value.as_external_typed_data.length; |
| s->WriteUnsigned(length); |
| |
| s->finalizable_data()->Put(length * element_size, |
| data->value.as_external_typed_data.data, |
| data->value.as_external_typed_data.peer, |
| data->value.as_external_typed_data.callback); |
| } |
| } |
| |
| private: |
| GrowableArray<ExternalTypedData*> objects_; |
| }; |
| |
| class ExternalTypedDataMessageDeserializationCluster |
| : public MessageDeserializationCluster { |
| public: |
| explicit ExternalTypedDataMessageDeserializationCluster(intptr_t cid) |
| : MessageDeserializationCluster("ExternalTypedData"), cid_(cid) {} |
| ~ExternalTypedDataMessageDeserializationCluster() {} |
| |
| void ReadNodes(MessageDeserializer* d) { |
| intptr_t element_size = ExternalTypedData::ElementSizeInBytes(cid_); |
| intptr_t count = d->ReadUnsigned(); |
| ExternalTypedData& data = ExternalTypedData::Handle(d->zone()); |
| for (intptr_t i = 0; i < count; i++) { |
| intptr_t length = d->ReadUnsigned(); |
| FinalizableData finalizable_data = d->finalizable_data()->Take(); |
| data = ExternalTypedData::New( |
| cid_, reinterpret_cast<uint8_t*>(finalizable_data.data), length); |
| intptr_t external_size = length * element_size; |
| data.AddFinalizer(finalizable_data.peer, finalizable_data.callback, |
| external_size); |
| d->AssignRef(data.ptr()); |
| } |
| } |
| |
| void ReadNodesApi(ApiMessageDeserializer* d) { |
| Dart_TypedData_Type type; |
| switch (cid_) { |
| case kExternalTypedDataInt8ArrayCid: |
| type = Dart_TypedData_kInt8; |
| break; |
| case kExternalTypedDataUint8ArrayCid: |
| type = Dart_TypedData_kUint8; |
| break; |
| case kExternalTypedDataUint8ClampedArrayCid: |
| type = Dart_TypedData_kUint8Clamped; |
| break; |
| case kExternalTypedDataInt16ArrayCid: |
| type = Dart_TypedData_kInt16; |
| break; |
| case kExternalTypedDataUint16ArrayCid: |
| type = Dart_TypedData_kUint16; |
| break; |
| case kExternalTypedDataInt32ArrayCid: |
| type = Dart_TypedData_kInt32; |
| break; |
| case kExternalTypedDataUint32ArrayCid: |
| type = Dart_TypedData_kUint32; |
| break; |
| case kExternalTypedDataInt64ArrayCid: |
| type = Dart_TypedData_kInt64; |
| break; |
| case kExternalTypedDataUint64ArrayCid: |
| type = Dart_TypedData_kUint64; |
| break; |
| case kExternalTypedDataFloat32ArrayCid: |
| type = Dart_TypedData_kFloat32; |
| break; |
| case kExternalTypedDataFloat64ArrayCid: |
| type = Dart_TypedData_kFloat64; |
| break; |
| case kExternalTypedDataInt32x4ArrayCid: |
| type = Dart_TypedData_kInt32x4; |
| break; |
| case kExternalTypedDataFloat32x4ArrayCid: |
| type = Dart_TypedData_kFloat32x4; |
| break; |
| case kExternalTypedDataFloat64x2ArrayCid: |
| type = Dart_TypedData_kFloat64x2; |
| break; |
| default: |
| UNREACHABLE(); |
| } |
| |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| Dart_CObject* data = d->Allocate(Dart_CObject_kTypedData); |
| intptr_t length = d->ReadUnsigned(); |
| FinalizableData finalizable_data = d->finalizable_data()->Get(); |
| data->value.as_typed_data.type = type; |
| data->value.as_typed_data.length = length; |
| data->value.as_typed_data.values = |
| reinterpret_cast<uint8_t*>(finalizable_data.data); |
| d->AssignRef(data); |
| } |
| } |
| |
| private: |
| const intptr_t cid_; |
| }; |
| |
| class NativePointerMessageSerializationCluster |
| : public MessageSerializationCluster { |
| public: |
| explicit NativePointerMessageSerializationCluster(Zone* zone) |
| : MessageSerializationCluster("NativePointer", |
| MessagePhase::kNonCanonicalInstances, |
| kNativePointer), |
| objects_(zone, 0) {} |
| ~NativePointerMessageSerializationCluster() {} |
| |
| void Trace(MessageSerializer* s, Object* object) { UNREACHABLE(); } |
| |
| void WriteNodes(MessageSerializer* s) { UNREACHABLE(); } |
| |
| void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) { |
| objects_.Add(object); |
| } |
| |
| void WriteNodesApi(ApiMessageSerializer* s) { |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| Dart_CObject* data = objects_[i]; |
| s->AssignRef(data); |
| |
| s->finalizable_data()->Put( |
| data->value.as_native_pointer.size, |
| reinterpret_cast<void*>(data->value.as_native_pointer.ptr), |
| reinterpret_cast<void*>(data->value.as_native_pointer.ptr), |
| data->value.as_native_pointer.callback); |
| } |
| } |
| |
| private: |
| GrowableArray<Dart_CObject*> objects_; |
| }; |
| |
| class NativePointerMessageDeserializationCluster |
| : public MessageDeserializationCluster { |
| public: |
| NativePointerMessageDeserializationCluster() |
| : MessageDeserializationCluster("NativePointer"), cid_(kNativePointer) {} |
| ~NativePointerMessageDeserializationCluster() {} |
| |
| void ReadNodes(MessageDeserializer* d) { |
| const intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| FinalizableData finalizable_data = d->finalizable_data()->Take(); |
| intptr_t ptr = reinterpret_cast<intptr_t>(finalizable_data.data); |
| d->AssignRef(Integer::New(ptr)); |
| } |
| } |
| |
| void ReadNodesApi(ApiMessageDeserializer* d) { UNREACHABLE(); } |
| |
| private: |
| const intptr_t cid_; |
| }; |
| |
| class TypedDataViewMessageSerializationCluster |
| : public MessageSerializationCluster { |
| public: |
| explicit TypedDataViewMessageSerializationCluster(Zone* zone, intptr_t cid) |
| : MessageSerializationCluster("TypedDataView", |
| MessagePhase::kNonCanonicalInstances, |
| cid), |
| objects_(zone, 0) {} |
| ~TypedDataViewMessageSerializationCluster() {} |
| |
| void Trace(MessageSerializer* s, Object* object) { |
| TypedDataView* view = static_cast<TypedDataView*>(object); |
| objects_.Add(view); |
| |
| s->Push(view->untag()->length()); |
| s->Push(view->untag()->typed_data()); |
| s->Push(view->untag()->offset_in_bytes()); |
| } |
| |
| void WriteNodes(MessageSerializer* s) { |
| const intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| TypedDataView* view = objects_[i]; |
| s->AssignRef(view); |
| } |
| } |
| |
| void WriteEdges(MessageSerializer* s) { |
| const intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| TypedDataView* view = objects_[i]; |
| s->WriteRef(view->untag()->length()); |
| s->WriteRef(view->untag()->typed_data()); |
| s->WriteRef(view->untag()->offset_in_bytes()); |
| } |
| } |
| |
| private: |
| GrowableArray<TypedDataView*> objects_; |
| }; |
| |
| class TypedDataViewMessageDeserializationCluster |
| : public MessageDeserializationCluster { |
| public: |
| explicit TypedDataViewMessageDeserializationCluster(intptr_t cid) |
| : MessageDeserializationCluster("TypedDataView"), cid_(cid) {} |
| ~TypedDataViewMessageDeserializationCluster() {} |
| |
| void ReadNodes(MessageDeserializer* d) { |
| const intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| d->AssignRef(TypedDataView::New(cid_)); |
| } |
| } |
| |
| void ReadEdges(MessageDeserializer* d) { |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| TypedDataViewPtr view = static_cast<TypedDataViewPtr>(d->Ref(id)); |
| view->untag()->set_length(static_cast<SmiPtr>(d->ReadRef())); |
| view->untag()->set_typed_data( |
| static_cast<TypedDataBasePtr>(d->ReadRef())); |
| view->untag()->set_offset_in_bytes(static_cast<SmiPtr>(d->ReadRef())); |
| } |
| } |
| |
| ObjectPtr PostLoad(MessageDeserializer* d) { |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| TypedDataViewPtr view = static_cast<TypedDataViewPtr>(d->Ref(id)); |
| view->untag()->RecomputeDataField(); |
| } |
| return nullptr; |
| } |
| |
| struct Dart_CTypedDataView : public Dart_CObject { |
| Dart_CObject* length; |
| Dart_CObject* typed_data; |
| Dart_CObject* offset_in_bytes; |
| }; |
| |
| void ReadNodesApi(ApiMessageDeserializer* d) { |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| Dart_CTypedDataView* view = d->zone()->Alloc<Dart_CTypedDataView>(1); |
| d->AssignRef(view); |
| } |
| } |
| |
| void ReadEdgesApi(ApiMessageDeserializer* d) { |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| Dart_CTypedDataView* view = static_cast<Dart_CTypedDataView*>(d->Ref(id)); |
| view->length = d->ReadRef(); |
| view->typed_data = d->ReadRef(); |
| view->offset_in_bytes = d->ReadRef(); |
| } |
| } |
| |
| void PostLoadApi(ApiMessageDeserializer* d) { |
| Dart_TypedData_Type type; |
| switch (cid_) { |
| case kTypedDataInt8ArrayViewCid: |
| type = Dart_TypedData_kInt8; |
| break; |
| case kTypedDataUint8ArrayViewCid: |
| type = Dart_TypedData_kUint8; |
| break; |
| case kTypedDataUint8ClampedArrayViewCid: |
| type = Dart_TypedData_kUint8Clamped; |
| break; |
| case kTypedDataInt16ArrayViewCid: |
| type = Dart_TypedData_kInt16; |
| break; |
| case kTypedDataUint16ArrayViewCid: |
| type = Dart_TypedData_kUint16; |
| break; |
| case kTypedDataInt32ArrayViewCid: |
| type = Dart_TypedData_kInt32; |
| break; |
| case kTypedDataUint32ArrayViewCid: |
| type = Dart_TypedData_kUint32; |
| break; |
| case kTypedDataInt64ArrayViewCid: |
| type = Dart_TypedData_kInt64; |
| break; |
| case kTypedDataUint64ArrayViewCid: |
| type = Dart_TypedData_kUint64; |
| break; |
| case kTypedDataFloat32ArrayViewCid: |
| type = Dart_TypedData_kFloat32; |
| break; |
| case kTypedDataFloat64ArrayViewCid: |
| type = Dart_TypedData_kFloat64; |
| break; |
| case kTypedDataInt32x4ArrayViewCid: |
| type = Dart_TypedData_kInt32x4; |
| break; |
| case kTypedDataFloat32x4ArrayViewCid: |
| type = Dart_TypedData_kFloat32x4; |
| break; |
| case kTypedDataFloat64x2ArrayViewCid: |
| type = Dart_TypedData_kFloat64x2; |
| break; |
| default: |
| UNREACHABLE(); |
| } |
| |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| Dart_CTypedDataView* view = static_cast<Dart_CTypedDataView*>(d->Ref(id)); |
| if (view->typed_data->type == Dart_CObject_kTypedData) { |
| view->type = Dart_CObject_kTypedData; |
| view->value.as_typed_data.type = type; |
| view->value.as_typed_data.length = view->length->value.as_int32; |
| view->value.as_typed_data.values = |
| view->typed_data->value.as_typed_data.values + |
| view->offset_in_bytes->value.as_int32; |
| } else { |
| UNREACHABLE(); |
| } |
| } |
| } |
| |
| private: |
| const intptr_t cid_; |
| }; |
| |
| class TransferableTypedDataMessageSerializationCluster |
| : public MessageSerializationCluster { |
| public: |
| TransferableTypedDataMessageSerializationCluster() |
| : MessageSerializationCluster("TransferableTypedData", |
| MessagePhase::kNonCanonicalInstances, |
| kTransferableTypedDataCid) {} |
| ~TransferableTypedDataMessageSerializationCluster() {} |
| |
| void Trace(MessageSerializer* s, Object* object) { |
| TransferableTypedData* transferable = |
| static_cast<TransferableTypedData*>(object); |
| objects_.Add(transferable); |
| |
| void* peer = s->thread()->heap()->GetPeer(transferable->ptr()); |
| // Assume that object's Peer is only used to track transferrability state. |
| ASSERT(peer != nullptr); |
| TransferableTypedDataPeer* tpeer = |
| reinterpret_cast<TransferableTypedDataPeer*>(peer); |
| if (tpeer->data() == nullptr) { |
| s->IllegalObject( |
| *object, |
| "Illegal argument in isolate message" |
| " : (TransferableTypedData has been transferred already)"); |
| } |
| } |
| |
| void WriteNodes(MessageSerializer* s) { |
| const intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| TransferableTypedData* transferable = objects_[i]; |
| s->AssignRef(transferable); |
| |
| void* peer = s->thread()->heap()->GetPeer(transferable->ptr()); |
| // Assume that object's Peer is only used to track transferrability state. |
| ASSERT(peer != nullptr); |
| TransferableTypedDataPeer* tpeer = |
| reinterpret_cast<TransferableTypedDataPeer*>(peer); |
| intptr_t length = tpeer->length(); // In bytes. |
| void* data = tpeer->data(); |
| ASSERT(data != nullptr); |
| s->WriteUnsigned(length); |
| s->finalizable_data()->Put( |
| length, data, tpeer, |
| // Finalizer does nothing - in case of failure to serialize, |
| // [data] remains wrapped in sender's [TransferableTypedData]. |
| [](void* data, void* peer) {}, |
| // This is invoked on successful serialization of the message |
| [](void* data, void* peer) { |
| TransferableTypedDataPeer* ttpeer = |
| reinterpret_cast<TransferableTypedDataPeer*>(peer); |
| ttpeer->handle()->EnsureFreedExternal(IsolateGroup::Current()); |
| ttpeer->ClearData(); |
| }); |
| } |
| } |
| |
| private: |
| GrowableArray<TransferableTypedData*> objects_; |
| }; |
| |
| class TransferableTypedDataMessageDeserializationCluster |
| : public MessageDeserializationCluster { |
| public: |
| TransferableTypedDataMessageDeserializationCluster() |
| : MessageDeserializationCluster("TransferableTypedData") {} |
| ~TransferableTypedDataMessageDeserializationCluster() {} |
| |
| void ReadNodes(MessageDeserializer* d) { |
| const intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| intptr_t length = d->ReadUnsigned(); |
| const FinalizableData finalizable_data = d->finalizable_data()->Take(); |
| d->AssignRef(TransferableTypedData::New( |
| reinterpret_cast<uint8_t*>(finalizable_data.data), length)); |
| } |
| } |
| |
| void ReadNodesApi(ApiMessageDeserializer* d) { |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| Dart_CObject* data = d->Allocate(Dart_CObject_kTypedData); |
| data->value.as_typed_data.length = d->ReadUnsigned(); |
| data->value.as_typed_data.type = Dart_TypedData_kUint8; |
| FinalizableData finalizable_data = d->finalizable_data()->Get(); |
| data->value.as_typed_data.values = |
| reinterpret_cast<uint8_t*>(finalizable_data.data); |
| d->AssignRef(data); |
| } |
| } |
| }; |
| |
| class Simd128MessageSerializationCluster : public MessageSerializationCluster { |
| public: |
| explicit Simd128MessageSerializationCluster(intptr_t cid) |
| : MessageSerializationCluster("Simd128", |
| MessagePhase::kBeforeTypes, |
| cid) {} |
| ~Simd128MessageSerializationCluster() {} |
| |
| void Trace(MessageSerializer* s, Object* object) { objects_.Add(object); } |
| |
| void WriteNodes(MessageSerializer* s) { |
| const intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| Object* vector = objects_[i]; |
| s->AssignRef(vector); |
| ASSERT_EQUAL(Int32x4::value_offset(), Float32x4::value_offset()); |
| ASSERT_EQUAL(Int32x4::value_offset(), Float64x2::value_offset()); |
| s->WriteBytes(&(static_cast<Int32x4Ptr>(vector->ptr())->untag()->value_), |
| sizeof(simd128_value_t)); |
| } |
| } |
| |
| private: |
| GrowableArray<Object*> objects_; |
| }; |
| |
| class Simd128MessageDeserializationCluster |
| : public MessageDeserializationCluster { |
| public: |
| explicit Simd128MessageDeserializationCluster(intptr_t cid) |
| : MessageDeserializationCluster("Simd128"), cid_(cid) {} |
| ~Simd128MessageDeserializationCluster() {} |
| |
| void ReadNodes(MessageDeserializer* d) { |
| const intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| ASSERT_EQUAL(Int32x4::InstanceSize(), Float32x4::InstanceSize()); |
| ASSERT_EQUAL(Int32x4::InstanceSize(), Float64x2::InstanceSize()); |
| ObjectPtr vector = |
| Object::Allocate(cid_, Int32x4::InstanceSize(), Heap::kNew, |
| Int32x4::ContainsCompressedPointers()); |
| d->AssignRef(vector); |
| ASSERT_EQUAL(Int32x4::value_offset(), Float32x4::value_offset()); |
| ASSERT_EQUAL(Int32x4::value_offset(), Float64x2::value_offset()); |
| d->ReadBytes(&(static_cast<Int32x4Ptr>(vector)->untag()->value_), |
| sizeof(simd128_value_t)); |
| } |
| } |
| |
| private: |
| const intptr_t cid_; |
| }; |
| |
| class RegExpMessageSerializationCluster : public MessageSerializationCluster { |
| public: |
| RegExpMessageSerializationCluster() |
| : MessageSerializationCluster("RegExp", |
| MessagePhase::kNonCanonicalInstances, |
| kRegExpCid) {} |
| ~RegExpMessageSerializationCluster() {} |
| |
| void Trace(MessageSerializer* s, Object* object) { |
| RegExp* regexp = static_cast<RegExp*>(object); |
| objects_.Add(regexp); |
| |
| s->Push(regexp->capture_name_map()); |
| s->Push(regexp->pattern()); |
| } |
| |
| void WriteNodes(MessageSerializer* s) { |
| const intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| RegExp* regexp = objects_[i]; |
| s->AssignRef(regexp); |
| s->WriteRef(regexp->capture_name_map()); |
| s->WriteRef(regexp->pattern()); |
| s->Write<int32_t>(regexp->num_bracket_expressions()); |
| s->Write<int32_t>(regexp->num_registers(true)); |
| s->Write<int32_t>(regexp->num_registers(false)); |
| s->Write<int>(regexp->flags().value()); |
| } |
| } |
| |
| private: |
| GrowableArray<RegExp*> objects_; |
| }; |
| |
| class RegExpMessageDeserializationCluster |
| : public MessageDeserializationCluster { |
| public: |
| RegExpMessageDeserializationCluster() |
| : MessageDeserializationCluster("RegExp") {} |
| ~RegExpMessageDeserializationCluster() {} |
| |
| void ReadNodes(MessageDeserializer* d) { |
| RegExp& regexp = RegExp::Handle(d->zone()); |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| regexp = RegExp::New(d->zone()); |
| d->AssignRef(regexp.ptr()); |
| regexp.untag()->set_capture_name_map(static_cast<ArrayPtr>(d->ReadRef())); |
| regexp.untag()->set_pattern(static_cast<StringPtr>(d->ReadRef())); |
| regexp.set_num_bracket_expressions(d->Read<int32_t>()); |
| regexp.set_num_registers(true, d->Read<int32_t>()); |
| regexp.set_num_registers(false, d->Read<int32_t>()); |
| regexp.set_flags(RegExpFlags(d->Read<int>())); |
| } |
| } |
| }; |
| |
| class SendPortMessageSerializationCluster : public MessageSerializationCluster { |
| public: |
| explicit SendPortMessageSerializationCluster(Zone* zone) |
| : MessageSerializationCluster("SendPort", |
| MessagePhase::kNonCanonicalInstances, |
| kSendPortCid), |
| objects_(zone, 0) {} |
| ~SendPortMessageSerializationCluster() {} |
| |
| void Trace(MessageSerializer* s, Object* object) { |
| SendPort* port = static_cast<SendPort*>(object); |
| objects_.Add(port); |
| } |
| |
| void WriteNodes(MessageSerializer* s) { |
| const intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| SendPort* port = objects_[i]; |
| s->AssignRef(port); |
| s->Write<Dart_Port>(port->untag()->id_); |
| s->Write<Dart_Port>(port->untag()->origin_id_); |
| } |
| } |
| |
| void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) { |
| objects_.Add(reinterpret_cast<SendPort*>(object)); |
| } |
| |
| void WriteNodesApi(ApiMessageSerializer* s) { |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| Dart_CObject* port = reinterpret_cast<Dart_CObject*>(objects_[i]); |
| s->AssignRef(port); |
| s->Write<Dart_Port>(port->value.as_send_port.id); |
| s->Write<Dart_Port>(port->value.as_send_port.origin_id); |
| } |
| } |
| |
| private: |
| GrowableArray<SendPort*> objects_; |
| }; |
| |
| class SendPortMessageDeserializationCluster |
| : public MessageDeserializationCluster { |
| public: |
| SendPortMessageDeserializationCluster() |
| : MessageDeserializationCluster("SendPort") {} |
| ~SendPortMessageDeserializationCluster() {} |
| |
| void ReadNodes(MessageDeserializer* d) { |
| const intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| Dart_Port id = d->Read<Dart_Port>(); |
| Dart_Port origin_id = d->Read<Dart_Port>(); |
| d->AssignRef(SendPort::New(id, origin_id)); |
| } |
| } |
| |
| void ReadNodesApi(ApiMessageDeserializer* d) { |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| Dart_CObject* port = d->Allocate(Dart_CObject_kSendPort); |
| port->value.as_send_port.id = d->Read<Dart_Port>(); |
| port->value.as_send_port.origin_id = d->Read<Dart_Port>(); |
| d->AssignRef(port); |
| } |
| } |
| }; |
| |
| class CapabilityMessageSerializationCluster |
| : public MessageSerializationCluster { |
| public: |
| explicit CapabilityMessageSerializationCluster(Zone* zone) |
| : MessageSerializationCluster("Capability", |
| MessagePhase::kNonCanonicalInstances, |
| kCapabilityCid), |
| objects_(zone, 0) {} |
| ~CapabilityMessageSerializationCluster() {} |
| |
| void Trace(MessageSerializer* s, Object* object) { |
| Capability* cap = static_cast<Capability*>(object); |
| objects_.Add(cap); |
| } |
| |
| void WriteNodes(MessageSerializer* s) { |
| const intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| Capability* cap = objects_[i]; |
| s->AssignRef(cap); |
| s->Write<uint64_t>(cap->untag()->id_); |
| } |
| } |
| |
| void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) { |
| objects_.Add(reinterpret_cast<Capability*>(object)); |
| } |
| |
| void WriteNodesApi(ApiMessageSerializer* s) { |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| Dart_CObject* cap = reinterpret_cast<Dart_CObject*>(objects_[i]); |
| s->AssignRef(cap); |
| s->Write<Dart_Port>(cap->value.as_capability.id); |
| } |
| } |
| |
| private: |
| GrowableArray<Capability*> objects_; |
| }; |
| |
| class CapabilityMessageDeserializationCluster |
| : public MessageDeserializationCluster { |
| public: |
| CapabilityMessageDeserializationCluster() |
| : MessageDeserializationCluster("Capability") {} |
| ~CapabilityMessageDeserializationCluster() {} |
| |
| void ReadNodes(MessageDeserializer* d) { |
| const intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| uint64_t id = d->Read<uint64_t>(); |
| d->AssignRef(Capability::New(id)); |
| } |
| } |
| |
| void ReadNodesApi(ApiMessageDeserializer* d) { |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| Dart_CObject* cap = d->Allocate(Dart_CObject_kCapability); |
| cap->value.as_capability.id = d->Read<uint64_t>(); |
| d->AssignRef(cap); |
| } |
| } |
| }; |
| |
| class WeakPropertyMessageSerializationCluster |
| : public MessageSerializationCluster { |
| public: |
| WeakPropertyMessageSerializationCluster() |
| : MessageSerializationCluster("WeakProperty", |
| MessagePhase::kNonCanonicalInstances, |
| kWeakPropertyCid) {} |
| ~WeakPropertyMessageSerializationCluster() {} |
| |
| void Trace(MessageSerializer* s, Object* object) { |
| WeakProperty* property = static_cast<WeakProperty*>(object); |
| objects_.Add(property); |
| } |
| |
| void RetraceEphemerons(MessageSerializer* s) { |
| for (intptr_t i = 0; i < objects_.length(); i++) { |
| WeakProperty* property = objects_[i]; |
| if (s->HasRef(property->untag()->key())) { |
| s->Push(property->untag()->value()); |
| } |
| } |
| } |
| |
| void WriteNodes(MessageSerializer* s) { |
| const intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| WeakProperty* property = objects_[i]; |
| s->AssignRef(property); |
| } |
| } |
| |
| void WriteEdges(MessageSerializer* s) { |
| const intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| WeakProperty* property = objects_[i]; |
| if (s->HasRef(property->untag()->key())) { |
| s->WriteRef(property->untag()->key()); |
| s->WriteRef(property->untag()->value()); |
| } else { |
| s->WriteRef(Object::null()); |
| s->WriteRef(Object::null()); |
| } |
| } |
| } |
| |
| private: |
| GrowableArray<WeakProperty*> objects_; |
| }; |
| |
| class WeakPropertyMessageDeserializationCluster |
| : public MessageDeserializationCluster { |
| public: |
| WeakPropertyMessageDeserializationCluster() |
| : MessageDeserializationCluster("WeakProperty") {} |
| ~WeakPropertyMessageDeserializationCluster() {} |
| |
| void ReadNodes(MessageDeserializer* d) { |
| const intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| d->AssignRef(WeakProperty::New()); |
| } |
| } |
| |
| void ReadEdges(MessageDeserializer* d) { |
| ASSERT(!is_canonical()); // Never canonical. |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| WeakPropertyPtr property = static_cast<WeakPropertyPtr>(d->Ref(id)); |
| property->untag()->set_key(d->ReadRef()); |
| property->untag()->set_value(d->ReadRef()); |
| } |
| } |
| }; |
| |
| class WeakReferenceMessageSerializationCluster |
| : public MessageSerializationCluster { |
| public: |
| WeakReferenceMessageSerializationCluster() |
| : MessageSerializationCluster("WeakReference", |
| MessagePhase::kNonCanonicalInstances, |
| kWeakReferenceCid) {} |
| ~WeakReferenceMessageSerializationCluster() {} |
| |
| void Trace(MessageSerializer* s, Object* object) { |
| WeakReference* reference = static_cast<WeakReference*>(object); |
| objects_.Add(reference); |
| |
| s->Push(reference->untag()->type_arguments()); |
| } |
| |
| void WriteNodes(MessageSerializer* s) { |
| const intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| WeakReference* reference = objects_[i]; |
| s->AssignRef(reference); |
| } |
| } |
| |
| void WriteEdges(MessageSerializer* s) { |
| const intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| WeakReference* reference = objects_[i]; |
| if (s->HasRef(reference->untag()->target())) { |
| s->WriteRef(reference->untag()->target()); |
| } else { |
| s->WriteRef(Object::null()); |
| } |
| s->WriteRef(reference->untag()->type_arguments()); |
| } |
| } |
| |
| private: |
| GrowableArray<WeakReference*> objects_; |
| }; |
| |
| class WeakReferenceMessageDeserializationCluster |
| : public MessageDeserializationCluster { |
| public: |
| WeakReferenceMessageDeserializationCluster() |
| : MessageDeserializationCluster("WeakReference") {} |
| ~WeakReferenceMessageDeserializationCluster() {} |
| |
| void ReadNodes(MessageDeserializer* d) { |
| const intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| d->AssignRef(WeakReference::New()); |
| } |
| } |
| |
| void ReadEdges(MessageDeserializer* d) { |
| ASSERT(!is_canonical()); // Never canonical. |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| WeakReferencePtr reference = static_cast<WeakReferencePtr>(d->Ref(id)); |
| reference->untag()->set_target(d->ReadRef()); |
| reference->untag()->set_type_arguments( |
| static_cast<TypeArgumentsPtr>(d->ReadRef())); |
| } |
| } |
| }; |
| |
| class LinkedHashMapMessageSerializationCluster |
| : public MessageSerializationCluster { |
| public: |
| LinkedHashMapMessageSerializationCluster(Zone* zone, |
| bool is_canonical, |
| intptr_t cid) |
| : MessageSerializationCluster("LinkedHashMap", |
| is_canonical |
| ? MessagePhase::kCanonicalInstances |
| : MessagePhase::kNonCanonicalInstances, |
| cid, |
| is_canonical), |
| objects_(zone, 0) {} |
| ~LinkedHashMapMessageSerializationCluster() {} |
| |
| void Trace(MessageSerializer* s, Object* object) { |
| LinkedHashMap* map = static_cast<LinkedHashMap*>(object); |
| objects_.Add(map); |
| |
| s->Push(map->untag()->type_arguments()); |
| s->Push(map->untag()->data()); |
| s->Push(map->untag()->used_data()); |
| } |
| |
| void WriteNodes(MessageSerializer* s) { |
| const intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| LinkedHashMap* map = objects_[i]; |
| s->AssignRef(map); |
| } |
| } |
| |
| void WriteEdges(MessageSerializer* s) { |
| const intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| LinkedHashMap* map = objects_[i]; |
| s->WriteRef(map->untag()->type_arguments()); |
| s->WriteRef(map->untag()->data()); |
| s->WriteRef(map->untag()->used_data()); |
| } |
| } |
| |
| private: |
| GrowableArray<LinkedHashMap*> objects_; |
| }; |
| |
| class LinkedHashMapMessageDeserializationCluster |
| : public MessageDeserializationCluster { |
| public: |
| LinkedHashMapMessageDeserializationCluster(bool is_canonical, intptr_t cid) |
| : MessageDeserializationCluster("LinkedHashMap", is_canonical), |
| cid_(cid) {} |
| ~LinkedHashMapMessageDeserializationCluster() {} |
| |
| void ReadNodes(MessageDeserializer* d) { |
| const intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| d->AssignRef(LinkedHashMap::NewUninitialized(cid_)); |
| } |
| } |
| |
| void ReadEdges(MessageDeserializer* d) { |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| LinkedHashMapPtr map = static_cast<LinkedHashMapPtr>(d->Ref(id)); |
| map->untag()->set_hash_mask(Smi::New(0)); |
| map->untag()->set_type_arguments( |
| static_cast<TypeArgumentsPtr>(d->ReadRef())); |
| map->untag()->set_data(static_cast<ArrayPtr>(d->ReadRef())); |
| map->untag()->set_used_data(static_cast<SmiPtr>(d->ReadRef())); |
| map->untag()->set_deleted_keys(Smi::New(0)); |
| } |
| } |
| |
| ObjectPtr PostLoad(MessageDeserializer* d) { |
| if (!is_canonical()) { |
| ASSERT(cid_ == kLinkedHashMapCid); |
| return PostLoadLinkedHash(d); |
| } |
| |
| ASSERT(cid_ == kImmutableLinkedHashMapCid); |
| SafepointMutexLocker ml( |
| d->isolate_group()->constant_canonicalization_mutex()); |
| LinkedHashMap& instance = LinkedHashMap::Handle(d->zone()); |
| for (intptr_t i = start_index_; i < stop_index_; i++) { |
| instance ^= d->Ref(i); |
| instance ^= instance.CanonicalizeLocked(d->thread()); |
| d->UpdateRef(i, instance); |
| } |
| return nullptr; |
| } |
| |
| private: |
| const intptr_t cid_; |
| }; |
| |
| class LinkedHashSetMessageSerializationCluster |
| : public MessageSerializationCluster { |
| public: |
| LinkedHashSetMessageSerializationCluster(Zone* zone, |
| bool is_canonical, |
| intptr_t cid) |
| : MessageSerializationCluster("LinkedHashSet", |
| is_canonical |
| ? MessagePhase::kCanonicalInstances |
| : MessagePhase::kNonCanonicalInstances, |
| cid, |
| is_canonical), |
| objects_(zone, 0) {} |
| ~LinkedHashSetMessageSerializationCluster() {} |
| |
| void Trace(MessageSerializer* s, Object* object) { |
| LinkedHashSet* map = static_cast<LinkedHashSet*>(object); |
| objects_.Add(map); |
| |
| s->Push(map->untag()->type_arguments()); |
| s->Push(map->untag()->data()); |
| s->Push(map->untag()->used_data()); |
| } |
| |
| void WriteNodes(MessageSerializer* s) { |
| const intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| LinkedHashSet* map = objects_[i]; |
| s->AssignRef(map); |
| } |
| } |
| |
| void WriteEdges(MessageSerializer* s) { |
| const intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| LinkedHashSet* map = objects_[i]; |
| s->WriteRef(map->untag()->type_arguments()); |
| s->WriteRef(map->untag()->data()); |
| s->WriteRef(map->untag()->used_data()); |
| } |
| } |
| |
| private: |
| GrowableArray<LinkedHashSet*> objects_; |
| }; |
| |
| class LinkedHashSetMessageDeserializationCluster |
| : public MessageDeserializationCluster { |
| public: |
| LinkedHashSetMessageDeserializationCluster(bool is_canonical, intptr_t cid) |
| : MessageDeserializationCluster("LinkedHashSet", is_canonical), |
| cid_(cid) {} |
| ~LinkedHashSetMessageDeserializationCluster() {} |
| |
| void ReadNodes(MessageDeserializer* d) { |
| const intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| d->AssignRef(LinkedHashSet::NewUninitialized(cid_)); |
| } |
| } |
| |
| void ReadEdges(MessageDeserializer* d) { |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| LinkedHashSetPtr map = static_cast<LinkedHashSetPtr>(d->Ref(id)); |
| map->untag()->set_hash_mask(Smi::New(0)); |
| map->untag()->set_type_arguments( |
| static_cast<TypeArgumentsPtr>(d->ReadRef())); |
| map->untag()->set_data(static_cast<ArrayPtr>(d->ReadRef())); |
| map->untag()->set_used_data(static_cast<SmiPtr>(d->ReadRef())); |
| map->untag()->set_deleted_keys(Sm
|