| // Copyright (c) 2016, 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/clustered_snapshot.h" |
| |
| #include "platform/assert.h" |
| #include "vm/bootstrap.h" |
| #include "vm/compiler/backend/code_statistics.h" |
| #include "vm/compiler/relocation.h" |
| #include "vm/dart.h" |
| #include "vm/heap/heap.h" |
| #include "vm/image_snapshot.h" |
| #include "vm/native_entry.h" |
| #include "vm/object.h" |
| #include "vm/object_store.h" |
| #include "vm/program_visitor.h" |
| #include "vm/stub_code.h" |
| #include "vm/symbols.h" |
| #include "vm/timeline.h" |
| #include "vm/version.h" |
| |
| #define LOG_SECTION_BOUNDARIES false |
| |
| namespace dart { |
| |
| #if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32) && \ |
| !defined(TARGET_ARCH_DBC) |
| |
| static void RelocateCodeObjects( |
| bool is_vm, |
| GrowableArray<RawCode*>* code_objects, |
| GrowableArray<ImageWriterCommand>* image_writer_commands) { |
| auto thread = Thread::Current(); |
| auto isolate = is_vm ? Dart::vm_isolate() : thread->isolate(); |
| |
| WritableCodePages writable_code_pages(thread, isolate); |
| CodeRelocator::Relocate(thread, code_objects, image_writer_commands, is_vm); |
| } |
| |
| class RawCodeKeyValueTrait { |
| public: |
| // Typedefs needed for the DirectChainedHashMap template. |
| typedef const RawCode* Key; |
| typedef const RawCode* Value; |
| typedef const RawCode* Pair; |
| |
| static Key KeyOf(Pair kv) { return kv; } |
| static Value ValueOf(Pair kv) { return kv; } |
| static inline intptr_t Hashcode(Key key) { |
| return reinterpret_cast<intptr_t>(key); |
| } |
| |
| static inline bool IsKeyEqual(Pair pair, Key key) { return pair == key; } |
| }; |
| |
| typedef DirectChainedHashMap<RawCodeKeyValueTrait> RawCodeSet; |
| |
| #endif // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32) && \ |
| // !defined(TARGET_ARCH_DBC) |
| |
| static RawObject* AllocateUninitialized(PageSpace* old_space, intptr_t size) { |
| ASSERT(Utils::IsAligned(size, kObjectAlignment)); |
| uword address = old_space->TryAllocateDataBumpLocked(size); |
| if (address == 0) { |
| OUT_OF_MEMORY(); |
| } |
| return RawObject::FromAddr(address); |
| } |
| |
| void Deserializer::InitializeHeader(RawObject* raw, |
| intptr_t class_id, |
| intptr_t size, |
| bool is_canonical) { |
| ASSERT(Utils::IsAligned(size, kObjectAlignment)); |
| uint32_t tags = 0; |
| tags = RawObject::ClassIdTag::update(class_id, tags); |
| tags = RawObject::SizeTag::update(size, tags); |
| tags = RawObject::CanonicalBit::update(is_canonical, tags); |
| tags = RawObject::OldBit::update(true, tags); |
| tags = RawObject::OldAndNotMarkedBit::update(true, tags); |
| tags = RawObject::OldAndNotRememberedBit::update(true, tags); |
| tags = RawObject::NewBit::update(false, tags); |
| raw->ptr()->tags_ = tags; |
| #if defined(HASH_IN_OBJECT_HEADER) |
| raw->ptr()->hash_ = 0; |
| #endif |
| } |
| |
| void SerializationCluster::WriteAndMeasureAlloc(Serializer* serializer) { |
| if (LOG_SECTION_BOUNDARIES) { |
| OS::PrintErr("Data + %" Px ": Alloc %s\n", serializer->bytes_written(), |
| name_); |
| } |
| intptr_t start_size = serializer->bytes_written() + serializer->GetDataSize(); |
| intptr_t start_objects = serializer->next_ref_index(); |
| WriteAlloc(serializer); |
| intptr_t stop_size = serializer->bytes_written() + serializer->GetDataSize(); |
| intptr_t stop_objects = serializer->next_ref_index(); |
| size_ += (stop_size - start_size); |
| num_objects_ += (stop_objects - start_objects); |
| } |
| |
| void SerializationCluster::WriteAndMeasureFill(Serializer* serializer) { |
| if (LOG_SECTION_BOUNDARIES) { |
| OS::PrintErr("Data + %" Px ": Fill %s\n", serializer->bytes_written(), |
| name_); |
| } |
| intptr_t start = serializer->bytes_written(); |
| WriteFill(serializer); |
| intptr_t stop = serializer->bytes_written(); |
| size_ += (stop - start); |
| } |
| |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| class ClassSerializationCluster : public SerializationCluster { |
| public: |
| explicit ClassSerializationCluster(intptr_t num_cids) |
| : SerializationCluster("Class"), |
| predefined_(kNumPredefinedCids), |
| objects_(num_cids) {} |
| ~ClassSerializationCluster() {} |
| |
| void Trace(Serializer* s, RawObject* object) { |
| RawClass* cls = Class::RawCast(object); |
| intptr_t class_id = cls->ptr()->id_; |
| |
| if (class_id < kNumPredefinedCids) { |
| // These classes are allocated by Object::Init or Object::InitOnce, so the |
| // deserializer must find them in the class table instead of allocating |
| // them. |
| predefined_.Add(cls); |
| } else { |
| objects_.Add(cls); |
| } |
| |
| PushFromTo(cls); |
| } |
| |
| void WriteAlloc(Serializer* s) { |
| s->WriteCid(kClassCid); |
| intptr_t count = predefined_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| RawClass* cls = predefined_[i]; |
| s->AssignRef(cls); |
| AutoTraceObject(cls); |
| intptr_t class_id = cls->ptr()->id_; |
| s->WriteCid(class_id); |
| } |
| count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| RawClass* cls = objects_[i]; |
| s->AssignRef(cls); |
| } |
| } |
| |
| void WriteFill(Serializer* s) { |
| intptr_t count = predefined_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| WriteClass(s, predefined_[i]); |
| } |
| count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| WriteClass(s, objects_[i]); |
| } |
| } |
| |
| void WriteClass(Serializer* s, RawClass* cls) { |
| AutoTraceObjectName(cls, cls->ptr()->name_); |
| WriteFromTo(cls); |
| intptr_t class_id = cls->ptr()->id_; |
| if (class_id == kIllegalCid) { |
| s->UnexpectedObject(cls, "Class with illegal cid"); |
| } |
| s->WriteCid(class_id); |
| if (s->kind() != Snapshot::kFullAOT) { |
| s->Write<int32_t>(cls->ptr()->kernel_offset_); |
| } |
| s->Write<int32_t>(cls->ptr()->instance_size_in_words_); |
| s->Write<int32_t>(cls->ptr()->next_field_offset_in_words_); |
| s->Write<int32_t>(cls->ptr()->type_arguments_field_offset_in_words_); |
| s->Write<uint16_t>(cls->ptr()->num_type_arguments_); |
| s->Write<uint16_t>(cls->ptr()->has_pragma_and_num_own_type_arguments_); |
| s->Write<uint16_t>(cls->ptr()->num_native_fields_); |
| s->WriteTokenPosition(cls->ptr()->token_pos_); |
| s->Write<uint16_t>(cls->ptr()->state_bits_); |
| } |
| |
| private: |
| GrowableArray<RawClass*> predefined_; |
| GrowableArray<RawClass*> objects_; |
| }; |
| #endif // !DART_PRECOMPILED_RUNTIME |
| |
| class ClassDeserializationCluster : public DeserializationCluster { |
| public: |
| ClassDeserializationCluster() {} |
| ~ClassDeserializationCluster() {} |
| |
| void ReadAlloc(Deserializer* d) { |
| predefined_start_index_ = d->next_index(); |
| PageSpace* old_space = d->heap()->old_space(); |
| intptr_t count = d->ReadUnsigned(); |
| ClassTable* table = d->isolate()->class_table(); |
| for (intptr_t i = 0; i < count; i++) { |
| intptr_t class_id = d->ReadCid(); |
| ASSERT(table->HasValidClassAt(class_id)); |
| RawClass* cls = table->At(class_id); |
| ASSERT(cls != NULL); |
| d->AssignRef(cls); |
| } |
| predefined_stop_index_ = d->next_index(); |
| |
| start_index_ = d->next_index(); |
| count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| d->AssignRef(AllocateUninitialized(old_space, Class::InstanceSize())); |
| } |
| stop_index_ = d->next_index(); |
| } |
| |
| void ReadFill(Deserializer* d) { |
| ClassTable* table = d->isolate()->class_table(); |
| |
| for (intptr_t id = predefined_start_index_; id < predefined_stop_index_; |
| id++) { |
| RawClass* cls = reinterpret_cast<RawClass*>(d->Ref(id)); |
| ReadFromTo(cls); |
| intptr_t class_id = d->ReadCid(); |
| cls->ptr()->id_ = class_id; |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| if (d->kind() != Snapshot::kFullAOT) { |
| cls->ptr()->kernel_offset_ = d->Read<int32_t>(); |
| } |
| #endif |
| if (!RawObject::IsInternalVMdefinedClassId(class_id)) { |
| cls->ptr()->instance_size_in_words_ = d->Read<int32_t>(); |
| cls->ptr()->next_field_offset_in_words_ = d->Read<int32_t>(); |
| } else { |
| d->Read<int32_t>(); // Skip. |
| d->Read<int32_t>(); // Skip. |
| } |
| cls->ptr()->type_arguments_field_offset_in_words_ = d->Read<int32_t>(); |
| cls->ptr()->num_type_arguments_ = d->Read<uint16_t>(); |
| cls->ptr()->has_pragma_and_num_own_type_arguments_ = d->Read<uint16_t>(); |
| cls->ptr()->num_native_fields_ = d->Read<uint16_t>(); |
| cls->ptr()->token_pos_ = d->ReadTokenPosition(); |
| cls->ptr()->state_bits_ = d->Read<uint16_t>(); |
| } |
| |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| RawClass* cls = reinterpret_cast<RawClass*>(d->Ref(id)); |
| Deserializer::InitializeHeader(cls, kClassCid, Class::InstanceSize()); |
| ReadFromTo(cls); |
| |
| intptr_t class_id = d->ReadCid(); |
| |
| ASSERT(class_id >= kNumPredefinedCids); |
| Instance fake; |
| cls->ptr()->handle_vtable_ = fake.vtable(); |
| |
| cls->ptr()->id_ = class_id; |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| if (d->kind() != Snapshot::kFullAOT) { |
| cls->ptr()->kernel_offset_ = d->Read<int32_t>(); |
| } |
| #endif |
| cls->ptr()->instance_size_in_words_ = d->Read<int32_t>(); |
| cls->ptr()->next_field_offset_in_words_ = d->Read<int32_t>(); |
| cls->ptr()->type_arguments_field_offset_in_words_ = d->Read<int32_t>(); |
| cls->ptr()->num_type_arguments_ = d->Read<uint16_t>(); |
| cls->ptr()->has_pragma_and_num_own_type_arguments_ = d->Read<uint16_t>(); |
| cls->ptr()->num_native_fields_ = d->Read<uint16_t>(); |
| cls->ptr()->token_pos_ = d->ReadTokenPosition(); |
| cls->ptr()->state_bits_ = d->Read<uint16_t>(); |
| |
| table->AllocateIndex(class_id); |
| table->SetAt(class_id, cls); |
| } |
| } |
| |
| private: |
| intptr_t predefined_start_index_; |
| intptr_t predefined_stop_index_; |
| }; |
| |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| class TypeArgumentsSerializationCluster : public SerializationCluster { |
| public: |
| TypeArgumentsSerializationCluster() : SerializationCluster("TypeArguments") {} |
| ~TypeArgumentsSerializationCluster() {} |
| |
| void Trace(Serializer* s, RawObject* object) { |
| RawTypeArguments* type_args = TypeArguments::RawCast(object); |
| objects_.Add(type_args); |
| |
| s->Push(type_args->ptr()->instantiations_); |
| intptr_t length = Smi::Value(type_args->ptr()->length_); |
| for (intptr_t i = 0; i < length; i++) { |
| s->Push(type_args->ptr()->types()[i]); |
| } |
| } |
| |
| void WriteAlloc(Serializer* s) { |
| s->WriteCid(kTypeArgumentsCid); |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| RawTypeArguments* type_args = objects_[i]; |
| s->AssignRef(type_args); |
| AutoTraceObject(type_args); |
| intptr_t length = Smi::Value(type_args->ptr()->length_); |
| s->WriteUnsigned(length); |
| } |
| } |
| |
| void WriteFill(Serializer* s) { |
| intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| RawTypeArguments* type_args = objects_[i]; |
| AutoTraceObject(type_args); |
| intptr_t length = Smi::Value(type_args->ptr()->length_); |
| s->WriteUnsigned(length); |
| s->Write<bool>(type_args->IsCanonical()); |
| intptr_t hash = Smi::Value(type_args->ptr()->hash_); |
| s->Write<int32_t>(hash); |
| WriteField(type_args, instantiations_); |
| for (intptr_t j = 0; j < length; j++) { |
| s->WriteElementRef(type_args->ptr()->types()[j], j); |
| } |
| } |
| } |
| |
| private: |
| GrowableArray<RawTypeArguments*> objects_; |
| }; |
| #endif // !DART_PRECOMPILED_RUNTIME |
| |
| class TypeArgumentsDeserializationCluster : public DeserializationCluster { |
| public: |
| TypeArgumentsDeserializationCluster() {} |
| ~TypeArgumentsDeserializationCluster() {} |
| |
| void ReadAlloc(Deserializer* d) { |
| start_index_ = d->next_index(); |
| PageSpace* old_space = d->heap()->old_space(); |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| intptr_t length = d->ReadUnsigned(); |
| d->AssignRef(AllocateUninitialized(old_space, |
| TypeArguments::InstanceSize(length))); |
| } |
| stop_index_ = d->next_index(); |
| } |
| |
| void ReadFill(Deserializer* d) { |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| RawTypeArguments* type_args = |
| reinterpret_cast<RawTypeArguments*>(d->Ref(id)); |
| intptr_t length = d->ReadUnsigned(); |
| bool is_canonical = d->Read<bool>(); |
| Deserializer::InitializeHeader(type_args, kTypeArgumentsCid, |
| TypeArguments::InstanceSize(length), |
| is_canonical); |
| type_args->ptr()->length_ = Smi::New(length); |
| type_args->ptr()->hash_ = Smi::New(d->Read<int32_t>()); |
| type_args->ptr()->instantiations_ = |
| reinterpret_cast<RawArray*>(d->ReadRef()); |
| for (intptr_t j = 0; j < length; j++) { |
| type_args->ptr()->types()[j] = |
| reinterpret_cast<RawAbstractType*>(d->ReadRef()); |
| } |
| } |
| } |
| }; |
| |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| class PatchClassSerializationCluster : public SerializationCluster { |
| public: |
| PatchClassSerializationCluster() : SerializationCluster("PatchClass") {} |
| ~PatchClassSerializationCluster() {} |
| |
| void Trace(Serializer* s, RawObject* object) { |
| RawPatchClass* cls = PatchClass::RawCast(object); |
| objects_.Add(cls); |
| PushFromTo(cls); |
| } |
| |
| void WriteAlloc(Serializer* s) { |
| s->WriteCid(kPatchClassCid); |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| RawPatchClass* cls = objects_[i]; |
| s->AssignRef(cls); |
| } |
| } |
| |
| void WriteFill(Serializer* s) { |
| intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| RawPatchClass* cls = objects_[i]; |
| AutoTraceObject(cls); |
| WriteFromTo(cls); |
| if (s->kind() != Snapshot::kFullAOT) { |
| s->Write<int32_t>(cls->ptr()->library_kernel_offset_); |
| } |
| } |
| } |
| |
| private: |
| GrowableArray<RawPatchClass*> objects_; |
| }; |
| #endif // !DART_PRECOMPILED_RUNTIME |
| |
| class PatchClassDeserializationCluster : public DeserializationCluster { |
| public: |
| PatchClassDeserializationCluster() {} |
| ~PatchClassDeserializationCluster() {} |
| |
| void ReadAlloc(Deserializer* d) { |
| start_index_ = d->next_index(); |
| PageSpace* old_space = d->heap()->old_space(); |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| d->AssignRef( |
| AllocateUninitialized(old_space, PatchClass::InstanceSize())); |
| } |
| stop_index_ = d->next_index(); |
| } |
| |
| void ReadFill(Deserializer* d) { |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| RawPatchClass* cls = reinterpret_cast<RawPatchClass*>(d->Ref(id)); |
| Deserializer::InitializeHeader(cls, kPatchClassCid, |
| PatchClass::InstanceSize()); |
| ReadFromTo(cls); |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| if (d->kind() != Snapshot::kFullAOT) { |
| cls->ptr()->library_kernel_offset_ = d->Read<int32_t>(); |
| } |
| #endif |
| } |
| } |
| }; |
| |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| class FunctionSerializationCluster : public SerializationCluster { |
| public: |
| FunctionSerializationCluster() : SerializationCluster("Function") {} |
| ~FunctionSerializationCluster() {} |
| |
| void Trace(Serializer* s, RawObject* object) { |
| Snapshot::Kind kind = s->kind(); |
| RawFunction* func = Function::RawCast(object); |
| objects_.Add(func); |
| |
| PushFromTo(func); |
| if (kind == Snapshot::kFull) { |
| NOT_IN_PRECOMPILED(s->Push(func->ptr()->bytecode_)); |
| } else if (kind == Snapshot::kFullAOT) { |
| s->Push(func->ptr()->code_); |
| } else if (kind == Snapshot::kFullJIT) { |
| NOT_IN_PRECOMPILED(s->Push(func->ptr()->unoptimized_code_)); |
| NOT_IN_PRECOMPILED(s->Push(func->ptr()->bytecode_)); |
| s->Push(func->ptr()->code_); |
| s->Push(func->ptr()->ic_data_array_); |
| } |
| } |
| |
| void WriteAlloc(Serializer* s) { |
| s->WriteCid(kFunctionCid); |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| RawFunction* func = objects_[i]; |
| s->AssignRef(func); |
| } |
| } |
| |
| void WriteFill(Serializer* s) { |
| Snapshot::Kind kind = s->kind(); |
| intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| RawFunction* func = objects_[i]; |
| AutoTraceObjectName(func, func->ptr()->name_); |
| WriteFromTo(func); |
| if (kind == Snapshot::kFull) { |
| NOT_IN_PRECOMPILED(WriteField(func, bytecode_)); |
| } else if (kind == Snapshot::kFullAOT) { |
| WriteField(func, code_); |
| } else if (s->kind() == Snapshot::kFullJIT) { |
| NOT_IN_PRECOMPILED(WriteField(func, unoptimized_code_)); |
| NOT_IN_PRECOMPILED(WriteField(func, bytecode_)); |
| WriteField(func, code_); |
| WriteField(func, ic_data_array_); |
| } |
| |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| if (kind != Snapshot::kFullAOT) { |
| s->WriteTokenPosition(func->ptr()->token_pos_); |
| s->WriteTokenPosition(func->ptr()->end_token_pos_); |
| s->Write<uint32_t>(func->ptr()->binary_declaration_); |
| } |
| #endif |
| s->Write<uint32_t>(func->ptr()->packed_fields_); |
| s->Write<uint32_t>(func->ptr()->kind_tag_); |
| } |
| } |
| |
| private: |
| GrowableArray<RawFunction*> objects_; |
| }; |
| #endif // !DART_PRECOMPILED_RUNTIME |
| |
| class FunctionDeserializationCluster : public DeserializationCluster { |
| public: |
| FunctionDeserializationCluster() {} |
| ~FunctionDeserializationCluster() {} |
| |
| void ReadAlloc(Deserializer* d) { |
| start_index_ = d->next_index(); |
| PageSpace* old_space = d->heap()->old_space(); |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| d->AssignRef(AllocateUninitialized(old_space, Function::InstanceSize())); |
| } |
| stop_index_ = d->next_index(); |
| } |
| |
| void ReadFill(Deserializer* d) { |
| Snapshot::Kind kind = d->kind(); |
| |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| RawFunction* func = reinterpret_cast<RawFunction*>(d->Ref(id)); |
| Deserializer::InitializeHeader(func, kFunctionCid, |
| Function::InstanceSize()); |
| ReadFromTo(func); |
| |
| if (kind == Snapshot::kFull) { |
| NOT_IN_PRECOMPILED(func->ptr()->bytecode_ = |
| reinterpret_cast<RawBytecode*>(d->ReadRef())); |
| } else if (kind == Snapshot::kFullAOT) { |
| func->ptr()->code_ = reinterpret_cast<RawCode*>(d->ReadRef()); |
| } else if (kind == Snapshot::kFullJIT) { |
| NOT_IN_PRECOMPILED(func->ptr()->unoptimized_code_ = |
| reinterpret_cast<RawCode*>(d->ReadRef())); |
| NOT_IN_PRECOMPILED(func->ptr()->bytecode_ = |
| reinterpret_cast<RawBytecode*>(d->ReadRef())); |
| func->ptr()->code_ = reinterpret_cast<RawCode*>(d->ReadRef()); |
| func->ptr()->ic_data_array_ = reinterpret_cast<RawArray*>(d->ReadRef()); |
| } |
| |
| #if defined(DEBUG) |
| func->ptr()->entry_point_ = 0; |
| func->ptr()->unchecked_entry_point_ = 0; |
| #endif |
| |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| if (kind != Snapshot::kFullAOT) { |
| func->ptr()->token_pos_ = d->ReadTokenPosition(); |
| func->ptr()->end_token_pos_ = d->ReadTokenPosition(); |
| func->ptr()->binary_declaration_ = d->Read<uint32_t>(); |
| } |
| #endif |
| func->ptr()->packed_fields_ = d->Read<uint32_t>(); |
| func->ptr()->kind_tag_ = d->Read<uint32_t>(); |
| if (kind == Snapshot::kFullAOT) { |
| // Omit fields used to support de/reoptimization. |
| } else { |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| func->ptr()->usage_counter_ = 0; |
| func->ptr()->optimized_instruction_count_ = 0; |
| func->ptr()->optimized_call_site_count_ = 0; |
| func->ptr()->deoptimization_counter_ = 0; |
| func->ptr()->state_bits_ = 0; |
| func->ptr()->inlining_depth_ = 0; |
| #endif |
| } |
| } |
| } |
| |
| void PostLoad(const Array& refs, Snapshot::Kind kind, Zone* zone) { |
| if (kind == Snapshot::kFullAOT) { |
| Function& func = Function::Handle(zone); |
| for (intptr_t i = start_index_; i < stop_index_; i++) { |
| func ^= refs.At(i); |
| ASSERT(func.raw()->ptr()->code_->IsCode()); |
| uword entry_point = func.raw()->ptr()->code_->ptr()->entry_point_; |
| ASSERT(entry_point != 0); |
| func.raw()->ptr()->entry_point_ = entry_point; |
| uword unchecked_entry_point = |
| func.raw()->ptr()->code_->ptr()->unchecked_entry_point_; |
| ASSERT(unchecked_entry_point != 0); |
| func.raw()->ptr()->unchecked_entry_point_ = unchecked_entry_point; |
| } |
| } else if (kind == Snapshot::kFullJIT) { |
| Function& func = Function::Handle(zone); |
| Code& code = Code::Handle(zone); |
| for (intptr_t i = start_index_; i < stop_index_; i++) { |
| func ^= refs.At(i); |
| code ^= func.CurrentCode(); |
| if (func.HasCode() && !code.IsDisabled()) { |
| func.SetInstructions(code); // Set entrypoint. |
| func.SetWasCompiled(true); |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| } else if (FLAG_enable_interpreter && func.HasBytecode()) { |
| // Set the code entry_point to InterpretCall stub. |
| func.SetInstructions(StubCode::InterpretCall()); |
| } else if (FLAG_use_bytecode_compiler && func.HasBytecode()) { |
| func.SetInstructions(StubCode::LazyCompile()); |
| #endif // !defined(DART_PRECOMPILED_RUNTIME) |
| } else { |
| func.ClearCode(); // Set code and entrypoint to lazy compile stub. |
| } |
| } |
| } else { |
| Function& func = Function::Handle(zone); |
| for (intptr_t i = start_index_; i < stop_index_; i++) { |
| func ^= refs.At(i); |
| func.ClearCode(); // Set code and entrypoint to lazy compile stub. |
| } |
| } |
| } |
| }; |
| |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| class ClosureDataSerializationCluster : public SerializationCluster { |
| public: |
| ClosureDataSerializationCluster() : SerializationCluster("ClosureData") {} |
| ~ClosureDataSerializationCluster() {} |
| |
| void Trace(Serializer* s, RawObject* object) { |
| RawClosureData* data = ClosureData::RawCast(object); |
| objects_.Add(data); |
| |
| if (s->kind() != Snapshot::kFullAOT) { |
| s->Push(data->ptr()->context_scope_); |
| } |
| s->Push(data->ptr()->parent_function_); |
| s->Push(data->ptr()->signature_type_); |
| s->Push(data->ptr()->closure_); |
| } |
| |
| void WriteAlloc(Serializer* s) { |
| s->WriteCid(kClosureDataCid); |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| RawClosureData* data = objects_[i]; |
| s->AssignRef(data); |
| } |
| } |
| |
| void WriteFill(Serializer* s) { |
| intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| RawClosureData* data = objects_[i]; |
| AutoTraceObject(data); |
| if (s->kind() != Snapshot::kFullAOT) { |
| WriteField(data, context_scope_); |
| } |
| WriteField(data, parent_function_); |
| WriteField(data, signature_type_); |
| WriteField(data, closure_); |
| } |
| } |
| |
| private: |
| GrowableArray<RawClosureData*> objects_; |
| }; |
| #endif // !DART_PRECOMPILED_RUNTIME |
| |
| class ClosureDataDeserializationCluster : public DeserializationCluster { |
| public: |
| ClosureDataDeserializationCluster() {} |
| ~ClosureDataDeserializationCluster() {} |
| |
| void ReadAlloc(Deserializer* d) { |
| start_index_ = d->next_index(); |
| PageSpace* old_space = d->heap()->old_space(); |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| d->AssignRef( |
| AllocateUninitialized(old_space, ClosureData::InstanceSize())); |
| } |
| stop_index_ = d->next_index(); |
| } |
| |
| void ReadFill(Deserializer* d) { |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| RawClosureData* data = reinterpret_cast<RawClosureData*>(d->Ref(id)); |
| Deserializer::InitializeHeader(data, kClosureDataCid, |
| ClosureData::InstanceSize()); |
| if (d->kind() == Snapshot::kFullAOT) { |
| data->ptr()->context_scope_ = ContextScope::null(); |
| } else { |
| data->ptr()->context_scope_ = |
| static_cast<RawContextScope*>(d->ReadRef()); |
| } |
| data->ptr()->parent_function_ = static_cast<RawFunction*>(d->ReadRef()); |
| data->ptr()->signature_type_ = static_cast<RawType*>(d->ReadRef()); |
| data->ptr()->closure_ = static_cast<RawInstance*>(d->ReadRef()); |
| } |
| } |
| }; |
| |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| class SignatureDataSerializationCluster : public SerializationCluster { |
| public: |
| SignatureDataSerializationCluster() : SerializationCluster("SignatureData") {} |
| ~SignatureDataSerializationCluster() {} |
| |
| void Trace(Serializer* s, RawObject* object) { |
| RawSignatureData* data = SignatureData::RawCast(object); |
| objects_.Add(data); |
| PushFromTo(data); |
| } |
| |
| void WriteAlloc(Serializer* s) { |
| s->WriteCid(kSignatureDataCid); |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| RawSignatureData* data = objects_[i]; |
| s->AssignRef(data); |
| } |
| } |
| |
| void WriteFill(Serializer* s) { |
| intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| RawSignatureData* data = objects_[i]; |
| AutoTraceObject(data); |
| WriteFromTo(data); |
| } |
| } |
| |
| private: |
| GrowableArray<RawSignatureData*> objects_; |
| }; |
| #endif // !DART_PRECOMPILED_RUNTIME |
| |
| class SignatureDataDeserializationCluster : public DeserializationCluster { |
| public: |
| SignatureDataDeserializationCluster() {} |
| ~SignatureDataDeserializationCluster() {} |
| |
| void ReadAlloc(Deserializer* d) { |
| start_index_ = d->next_index(); |
| PageSpace* old_space = d->heap()->old_space(); |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| d->AssignRef( |
| AllocateUninitialized(old_space, SignatureData::InstanceSize())); |
| } |
| stop_index_ = d->next_index(); |
| } |
| |
| void ReadFill(Deserializer* d) { |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| RawSignatureData* data = reinterpret_cast<RawSignatureData*>(d->Ref(id)); |
| Deserializer::InitializeHeader(data, kSignatureDataCid, |
| SignatureData::InstanceSize()); |
| ReadFromTo(data); |
| } |
| } |
| }; |
| |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| class RedirectionDataSerializationCluster : public SerializationCluster { |
| public: |
| RedirectionDataSerializationCluster() |
| : SerializationCluster("RedirectionData") {} |
| ~RedirectionDataSerializationCluster() {} |
| |
| void Trace(Serializer* s, RawObject* object) { |
| RawRedirectionData* data = RedirectionData::RawCast(object); |
| objects_.Add(data); |
| PushFromTo(data); |
| } |
| |
| void WriteAlloc(Serializer* s) { |
| s->WriteCid(kRedirectionDataCid); |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| RawRedirectionData* data = objects_[i]; |
| s->AssignRef(data); |
| } |
| } |
| |
| void WriteFill(Serializer* s) { |
| intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| RawRedirectionData* data = objects_[i]; |
| AutoTraceObject(data); |
| WriteFromTo(data); |
| } |
| } |
| |
| private: |
| GrowableArray<RawRedirectionData*> objects_; |
| }; |
| #endif // !DART_PRECOMPILED_RUNTIME |
| |
| class RedirectionDataDeserializationCluster : public DeserializationCluster { |
| public: |
| RedirectionDataDeserializationCluster() {} |
| ~RedirectionDataDeserializationCluster() {} |
| |
| void ReadAlloc(Deserializer* d) { |
| start_index_ = d->next_index(); |
| PageSpace* old_space = d->heap()->old_space(); |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| d->AssignRef( |
| AllocateUninitialized(old_space, RedirectionData::InstanceSize())); |
| } |
| stop_index_ = d->next_index(); |
| } |
| |
| void ReadFill(Deserializer* d) { |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| RawRedirectionData* data = |
| reinterpret_cast<RawRedirectionData*>(d->Ref(id)); |
| Deserializer::InitializeHeader(data, kRedirectionDataCid, |
| RedirectionData::InstanceSize()); |
| ReadFromTo(data); |
| } |
| } |
| }; |
| |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| class FieldSerializationCluster : public SerializationCluster { |
| public: |
| FieldSerializationCluster() : SerializationCluster("Field") {} |
| ~FieldSerializationCluster() {} |
| |
| void Trace(Serializer* s, RawObject* object) { |
| RawField* field = Field::RawCast(object); |
| objects_.Add(field); |
| |
| Snapshot::Kind kind = s->kind(); |
| |
| s->Push(field->ptr()->name_); |
| s->Push(field->ptr()->owner_); |
| s->Push(field->ptr()->type_); |
| // Write out the initial static value or field offset. |
| if (Field::StaticBit::decode(field->ptr()->kind_bits_)) { |
| if (kind == Snapshot::kFullAOT) { |
| // For precompiled static fields, the value was already reset and |
| // initializer_ now contains a Function. |
| s->Push(field->ptr()->value_.static_value_); |
| } else if (Field::ConstBit::decode(field->ptr()->kind_bits_)) { |
| // Do not reset const fields. |
| s->Push(field->ptr()->value_.static_value_); |
| } else { |
| // Otherwise, for static fields we write out the initial static value. |
| s->Push(field->ptr()->saved_initial_value_); |
| } |
| } else { |
| s->Push(field->ptr()->value_.offset_); |
| } |
| // Write out the initializer function |
| s->Push(field->ptr()->initializer_function_); |
| if (kind != Snapshot::kFullAOT) { |
| // Write out the saved initial value |
| s->Push(field->ptr()->saved_initial_value_); |
| } |
| if (kind != Snapshot::kFullAOT) { |
| // Write out the guarded list length. |
| s->Push(field->ptr()->guarded_list_length_); |
| } |
| if (kind == Snapshot::kFullJIT) { |
| s->Push(field->ptr()->dependent_code_); |
| } |
| } |
| |
| void WriteAlloc(Serializer* s) { |
| s->WriteCid(kFieldCid); |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| RawField* field = objects_[i]; |
| s->AssignRef(field); |
| } |
| } |
| |
| void WriteFill(Serializer* s) { |
| Snapshot::Kind kind = s->kind(); |
| intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| RawField* field = objects_[i]; |
| AutoTraceObjectName(field, field->ptr()->name_); |
| |
| WriteField(field, name_); |
| WriteField(field, owner_); |
| WriteField(field, type_); |
| // Write out the initial static value or field offset. |
| if (Field::StaticBit::decode(field->ptr()->kind_bits_)) { |
| if (kind == Snapshot::kFullAOT) { |
| // For precompiled static fields, the value was already reset and |
| // initializer_ now contains a Function. |
| WriteField(field, value_.static_value_); |
| } else if (Field::ConstBit::decode(field->ptr()->kind_bits_)) { |
| // Do not reset const fields. |
| WriteField(field, value_.static_value_); |
| } else { |
| // Otherwise, for static fields we write out the initial static value. |
| WriteField(field, saved_initial_value_); |
| } |
| } else { |
| WriteField(field, value_.offset_); |
| } |
| // Write out the initializer function and initial value if not in AOT. |
| WriteField(field, initializer_function_); |
| if (kind != Snapshot::kFullAOT) { |
| WriteField(field, saved_initial_value_); |
| } |
| if (kind != Snapshot::kFullAOT) { |
| // Write out the guarded list length. |
| WriteField(field, guarded_list_length_); |
| } |
| if (kind == Snapshot::kFullJIT) { |
| WriteField(field, dependent_code_); |
| } |
| |
| if (kind != Snapshot::kFullAOT) { |
| s->WriteTokenPosition(field->ptr()->token_pos_); |
| s->WriteTokenPosition(field->ptr()->end_token_pos_); |
| s->WriteCid(field->ptr()->guarded_cid_); |
| s->WriteCid(field->ptr()->is_nullable_); |
| s->Write<int8_t>(field->ptr()->static_type_exactness_state_); |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| s->Write<uint32_t>(field->ptr()->binary_declaration_); |
| #endif |
| } |
| s->Write<uint16_t>(field->ptr()->kind_bits_); |
| } |
| } |
| |
| private: |
| GrowableArray<RawField*> objects_; |
| }; |
| #endif // !DART_PRECOMPILED_RUNTIME |
| |
| class FieldDeserializationCluster : public DeserializationCluster { |
| public: |
| FieldDeserializationCluster() {} |
| ~FieldDeserializationCluster() {} |
| |
| void ReadAlloc(Deserializer* d) { |
| start_index_ = d->next_index(); |
| PageSpace* old_space = d->heap()->old_space(); |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| d->AssignRef(AllocateUninitialized(old_space, Field::InstanceSize())); |
| } |
| stop_index_ = d->next_index(); |
| } |
| |
| void ReadFill(Deserializer* d) { |
| Snapshot::Kind kind = d->kind(); |
| |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| RawField* field = reinterpret_cast<RawField*>(d->Ref(id)); |
| Deserializer::InitializeHeader(field, kFieldCid, Field::InstanceSize()); |
| ReadFromTo(field); |
| if (kind != Snapshot::kFullAOT) { |
| field->ptr()->token_pos_ = d->ReadTokenPosition(); |
| field->ptr()->end_token_pos_ = d->ReadTokenPosition(); |
| field->ptr()->guarded_cid_ = d->ReadCid(); |
| field->ptr()->is_nullable_ = d->ReadCid(); |
| field->ptr()->static_type_exactness_state_ = d->Read<int8_t>(); |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| field->ptr()->binary_declaration_ = d->Read<uint32_t>(); |
| #endif |
| } |
| field->ptr()->kind_bits_ = d->Read<uint16_t>(); |
| } |
| } |
| |
| void PostLoad(const Array& refs, Snapshot::Kind kind, Zone* zone) { |
| Field& field = Field::Handle(zone); |
| if (!Isolate::Current()->use_field_guards()) { |
| for (intptr_t i = start_index_; i < stop_index_; i++) { |
| field ^= refs.At(i); |
| field.set_guarded_cid(kDynamicCid); |
| field.set_is_nullable(true); |
| field.set_guarded_list_length(Field::kNoFixedLength); |
| field.set_guarded_list_length_in_object_offset( |
| Field::kUnknownLengthOffset); |
| field.set_static_type_exactness_state( |
| StaticTypeExactnessState::NotTracking()); |
| } |
| } else { |
| for (intptr_t i = start_index_; i < stop_index_; i++) { |
| field ^= refs.At(i); |
| field.InitializeGuardedListLengthInObjectOffset(); |
| } |
| } |
| } |
| }; |
| |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| class ScriptSerializationCluster : public SerializationCluster { |
| public: |
| ScriptSerializationCluster() : SerializationCluster("Script") {} |
| ~ScriptSerializationCluster() {} |
| |
| void Trace(Serializer* s, RawObject* object) { |
| RawScript* script = Script::RawCast(object); |
| objects_.Add(script); |
| PushFromTo(script); |
| } |
| |
| void WriteAlloc(Serializer* s) { |
| s->WriteCid(kScriptCid); |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| RawScript* script = objects_[i]; |
| s->AssignRef(script); |
| } |
| } |
| |
| void WriteFill(Serializer* s) { |
| intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| RawScript* script = objects_[i]; |
| AutoTraceObjectName(script, script->ptr()->url_); |
| WriteFromTo(script); |
| s->Write<int32_t>(script->ptr()->line_offset_); |
| s->Write<int32_t>(script->ptr()->col_offset_); |
| s->Write<int8_t>(script->ptr()->kind_); |
| s->Write<int32_t>(script->ptr()->kernel_script_index_); |
| } |
| } |
| |
| private: |
| GrowableArray<RawScript*> objects_; |
| }; |
| #endif // !DART_PRECOMPILED_RUNTIME |
| |
| class ScriptDeserializationCluster : public DeserializationCluster { |
| public: |
| ScriptDeserializationCluster() {} |
| ~ScriptDeserializationCluster() {} |
| |
| void ReadAlloc(Deserializer* d) { |
| start_index_ = d->next_index(); |
| PageSpace* old_space = d->heap()->old_space(); |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| d->AssignRef(AllocateUninitialized(old_space, Script::InstanceSize())); |
| } |
| stop_index_ = d->next_index(); |
| } |
| |
| void ReadFill(Deserializer* d) { |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| RawScript* script = reinterpret_cast<RawScript*>(d->Ref(id)); |
| Deserializer::InitializeHeader(script, kScriptCid, |
| Script::InstanceSize()); |
| ReadFromTo(script); |
| script->ptr()->line_offset_ = d->Read<int32_t>(); |
| script->ptr()->col_offset_ = d->Read<int32_t>(); |
| script->ptr()->kind_ = d->Read<int8_t>(); |
| script->ptr()->kernel_script_index_ = d->Read<int32_t>(); |
| script->ptr()->load_timestamp_ = 0; |
| } |
| } |
| }; |
| |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| class LibrarySerializationCluster : public SerializationCluster { |
| public: |
| LibrarySerializationCluster() : SerializationCluster("Library") {} |
| ~LibrarySerializationCluster() {} |
| |
| void Trace(Serializer* s, RawObject* object) { |
| RawLibrary* lib = Library::RawCast(object); |
| objects_.Add(lib); |
| PushFromTo(lib); |
| } |
| |
| void WriteAlloc(Serializer* s) { |
| s->WriteCid(kLibraryCid); |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| RawLibrary* lib = objects_[i]; |
| s->AssignRef(lib); |
| } |
| } |
| |
| void WriteFill(Serializer* s) { |
| intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| RawLibrary* lib = objects_[i]; |
| AutoTraceObjectName(lib, lib->ptr()->url_); |
| WriteFromTo(lib); |
| s->Write<int32_t>(lib->ptr()->index_); |
| s->Write<uint16_t>(lib->ptr()->num_imports_); |
| s->Write<int8_t>(lib->ptr()->load_state_); |
| s->Write<bool>(lib->ptr()->is_dart_scheme_); |
| s->Write<bool>(lib->ptr()->debuggable_); |
| if (s->kind() != Snapshot::kFullAOT) { |
| s->Write<int32_t>(lib->ptr()->kernel_offset_); |
| } |
| } |
| } |
| |
| private: |
| GrowableArray<RawLibrary*> objects_; |
| }; |
| #endif // !DART_PRECOMPILED_RUNTIME |
| |
| class LibraryDeserializationCluster : public DeserializationCluster { |
| public: |
| LibraryDeserializationCluster() {} |
| ~LibraryDeserializationCluster() {} |
| |
| void ReadAlloc(Deserializer* d) { |
| start_index_ = d->next_index(); |
| PageSpace* old_space = d->heap()->old_space(); |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| d->AssignRef(AllocateUninitialized(old_space, Library::InstanceSize())); |
| } |
| stop_index_ = d->next_index(); |
| } |
| |
| void ReadFill(Deserializer* d) { |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| RawLibrary* lib = reinterpret_cast<RawLibrary*>(d->Ref(id)); |
| Deserializer::InitializeHeader(lib, kLibraryCid, Library::InstanceSize()); |
| ReadFromTo(lib); |
| lib->ptr()->native_entry_resolver_ = NULL; |
| lib->ptr()->native_entry_symbol_resolver_ = NULL; |
| lib->ptr()->index_ = d->Read<int32_t>(); |
| lib->ptr()->num_imports_ = d->Read<uint16_t>(); |
| lib->ptr()->load_state_ = d->Read<int8_t>(); |
| lib->ptr()->is_dart_scheme_ = d->Read<bool>(); |
| lib->ptr()->debuggable_ = d->Read<bool>(); |
| lib->ptr()->is_in_fullsnapshot_ = true; |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| if (d->kind() != Snapshot::kFullAOT) { |
| lib->ptr()->kernel_offset_ = d->Read<int32_t>(); |
| } |
| #endif |
| } |
| } |
| }; |
| |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| class NamespaceSerializationCluster : public SerializationCluster { |
| public: |
| NamespaceSerializationCluster() : SerializationCluster("Namespace") {} |
| ~NamespaceSerializationCluster() {} |
| |
| void Trace(Serializer* s, RawObject* object) { |
| RawNamespace* ns = Namespace::RawCast(object); |
| objects_.Add(ns); |
| PushFromTo(ns); |
| } |
| |
| void WriteAlloc(Serializer* s) { |
| s->WriteCid(kNamespaceCid); |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| RawNamespace* ns = objects_[i]; |
| s->AssignRef(ns); |
| } |
| } |
| |
| void WriteFill(Serializer* s) { |
| intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| RawNamespace* ns = objects_[i]; |
| AutoTraceObject(ns); |
| WriteFromTo(ns); |
| } |
| } |
| |
| private: |
| GrowableArray<RawNamespace*> objects_; |
| }; |
| #endif // !DART_PRECOMPILED_RUNTIME |
| |
| class NamespaceDeserializationCluster : public DeserializationCluster { |
| public: |
| NamespaceDeserializationCluster() {} |
| ~NamespaceDeserializationCluster() {} |
| |
| void ReadAlloc(Deserializer* d) { |
| start_index_ = d->next_index(); |
| PageSpace* old_space = d->heap()->old_space(); |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| d->AssignRef(AllocateUninitialized(old_space, Namespace::InstanceSize())); |
| } |
| stop_index_ = d->next_index(); |
| } |
| |
| void ReadFill(Deserializer* d) { |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| RawNamespace* ns = reinterpret_cast<RawNamespace*>(d->Ref(id)); |
| Deserializer::InitializeHeader(ns, kNamespaceCid, |
| Namespace::InstanceSize()); |
| ReadFromTo(ns); |
| } |
| } |
| }; |
| |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| // KernelProgramInfo objects are not written into a full AOT snapshot. |
| class KernelProgramInfoSerializationCluster : public SerializationCluster { |
| public: |
| KernelProgramInfoSerializationCluster() |
| : SerializationCluster("KernelProgramInfo") {} |
| ~KernelProgramInfoSerializationCluster() {} |
| |
| void Trace(Serializer* s, RawObject* object) { |
| RawKernelProgramInfo* info = KernelProgramInfo::RawCast(object); |
| objects_.Add(info); |
| PushFromTo(info); |
| } |
| |
| void WriteAlloc(Serializer* s) { |
| s->WriteCid(kKernelProgramInfoCid); |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| RawKernelProgramInfo* info = objects_[i]; |
| s->AssignRef(info); |
| } |
| } |
| |
| void WriteFill(Serializer* s) { |
| intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| RawKernelProgramInfo* info = objects_[i]; |
| AutoTraceObject(info); |
| WriteFromTo(info); |
| } |
| } |
| |
| private: |
| GrowableArray<RawKernelProgramInfo*> objects_; |
| }; |
| |
| // Since KernelProgramInfo objects are not written into full AOT snapshots, |
| // one will never need to read them from a full AOT snapshot. |
| class KernelProgramInfoDeserializationCluster : public DeserializationCluster { |
| public: |
| KernelProgramInfoDeserializationCluster() {} |
| ~KernelProgramInfoDeserializationCluster() {} |
| |
| void ReadAlloc(Deserializer* d) { |
| start_index_ = d->next_index(); |
| PageSpace* old_space = d->heap()->old_space(); |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| d->AssignRef( |
| AllocateUninitialized(old_space, KernelProgramInfo::InstanceSize())); |
| } |
| stop_index_ = d->next_index(); |
| } |
| |
| void ReadFill(Deserializer* d) { |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| RawKernelProgramInfo* info = |
| reinterpret_cast<RawKernelProgramInfo*>(d->Ref(id)); |
| Deserializer::InitializeHeader(info, kKernelProgramInfoCid, |
| KernelProgramInfo::InstanceSize()); |
| ReadFromTo(info); |
| } |
| } |
| |
| void PostLoad(const Array& refs, Snapshot::Kind kind, Zone* zone) { |
| Array& array = Array::Handle(zone); |
| KernelProgramInfo& info = KernelProgramInfo::Handle(zone); |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| info ^= refs.At(id); |
| array = HashTables::New<UnorderedHashMap<SmiTraits>>(16, Heap::kOld); |
| info.set_libraries_cache(array); |
| array = HashTables::New<UnorderedHashMap<SmiTraits>>(16, Heap::kOld); |
| info.set_classes_cache(array); |
| } |
| } |
| }; |
| |
| class CodeSerializationCluster : public SerializationCluster { |
| public: |
| CodeSerializationCluster() : SerializationCluster("Code") {} |
| ~CodeSerializationCluster() {} |
| |
| void Trace(Serializer* s, RawObject* object) { |
| RawCode* code = Code::RawCast(object); |
| objects_.Add(code); |
| |
| s->Push(code->ptr()->object_pool_); |
| s->Push(code->ptr()->owner_); |
| s->Push(code->ptr()->exception_handlers_); |
| s->Push(code->ptr()->pc_descriptors_); |
| #if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER) |
| s->Push(code->ptr()->catch_entry_.catch_entry_moves_maps_); |
| #else |
| s->Push(code->ptr()->catch_entry_.variables_); |
| #endif |
| s->Push(code->ptr()->stackmaps_); |
| if (!FLAG_dwarf_stack_traces) { |
| s->Push(code->ptr()->inlined_id_to_function_); |
| s->Push(code->ptr()->code_source_map_); |
| } |
| if (s->kind() == Snapshot::kFullJIT) { |
| s->Push(code->ptr()->deopt_info_array_); |
| s->Push(code->ptr()->static_calls_target_table_); |
| } |
| NOT_IN_PRODUCT(s->Push(code->ptr()->await_token_positions_)); |
| NOT_IN_PRODUCT(s->Push(code->ptr()->return_address_metadata_)); |
| } |
| |
| void WriteAlloc(Serializer* s) { |
| s->WriteCid(kCodeCid); |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| RawCode* code = objects_[i]; |
| s->AssignRef(code); |
| } |
| } |
| |
| void WriteFill(Serializer* s) { |
| Snapshot::Kind kind = s->kind(); |
| intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| RawCode* code = objects_[i]; |
| AutoTraceObject(code); |
| |
| intptr_t pointer_offsets_length = |
| Code::PtrOffBits::decode(code->ptr()->state_bits_); |
| if (pointer_offsets_length != 0) { |
| FATAL("Cannot serialize code with embedded pointers"); |
| } |
| if (kind == Snapshot::kFullAOT) { |
| if (code->ptr()->instructions_ != code->ptr()->active_instructions_) { |
| // Disabled code is fatal in AOT since we cannot recompile. |
| s->UnexpectedObject(code, "Disabled code"); |
| } |
| } |
| |
| s->WriteInstructions(code->ptr()->instructions_, code); |
| if (kind == Snapshot::kFullJIT) { |
| // TODO(rmacnak): Fix references to disabled code before serializing. |
| // For now, we may write the FixCallersTarget or equivalent stub. This |
| // will cause a fixup if this code is called. |
| s->WriteInstructions(code->ptr()->active_instructions_, code); |
| } |
| |
| WriteField(code, object_pool_); |
| WriteField(code, owner_); |
| WriteField(code, exception_handlers_); |
| WriteField(code, pc_descriptors_); |
| #if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER) |
| WriteField(code, catch_entry_.catch_entry_moves_maps_); |
| #else |
| WriteField(code, catch_entry_.variables_); |
| #endif |
| WriteField(code, stackmaps_); |
| if (FLAG_dwarf_stack_traces) { |
| WriteFieldValue(inlined_id_to_function_, Array::null()); |
| WriteFieldValue(code_source_map_, CodeSourceMap::null()); |
| } else { |
| WriteField(code, inlined_id_to_function_); |
| WriteField(code, code_source_map_); |
| } |
| if (kind == Snapshot::kFullJIT) { |
| WriteField(code, deopt_info_array_); |
| WriteField(code, static_calls_target_table_); |
| } |
| NOT_IN_PRODUCT(WriteField(code, await_token_positions_)); |
| NOT_IN_PRODUCT(WriteField(code, return_address_metadata_)); |
| |
| s->Write<int32_t>(code->ptr()->state_bits_); |
| } |
| } |
| |
| GrowableArray<RawCode*>* discovered_objects() { return &objects_; } |
| |
| private: |
| GrowableArray<RawCode*> objects_; |
| }; |
| #endif // !DART_PRECOMPILED_RUNTIME |
| |
| class CodeDeserializationCluster : public DeserializationCluster { |
| public: |
| CodeDeserializationCluster() {} |
| ~CodeDeserializationCluster() {} |
| |
| void ReadAlloc(Deserializer* d) { |
| start_index_ = d->next_index(); |
| PageSpace* old_space = d->heap()->old_space(); |
| const intptr_t count = d->ReadUnsigned(); |
| |
| // Build an array of code objects representing the order in which the |
| // [Code]'s instructions will be located in memory. |
| const bool build_code_order = |
| FLAG_precompiled_mode && FLAG_use_bare_instructions; |
| RawArray* code_order = nullptr; |
| const intptr_t code_order_length = d->code_order_length(); |
| if (build_code_order) { |
| code_order = static_cast<RawArray*>( |
| AllocateUninitialized(old_space, Array::InstanceSize(count))); |
| Deserializer::InitializeHeader(code_order, kArrayCid, |
| Array::InstanceSize(count), |
| /*is_canonical=*/false); |
| code_order->ptr()->type_arguments_ = TypeArguments::null(); |
| code_order->ptr()->length_ = Smi::New(code_order_length); |
| } |
| |
| for (intptr_t i = 0; i < count; i++) { |
| auto code = AllocateUninitialized(old_space, Code::InstanceSize(0)); |
| d->AssignRef(code); |
| if (code_order != nullptr && i < code_order_length) { |
| code_order->ptr()->data()[i] = code; |
| } |
| } |
| |
| if (code_order != nullptr) { |
| const auto& code_order_table = Array::Handle(code_order); |
| d->isolate()->object_store()->set_code_order_table(code_order_table); |
| } |
| |
| stop_index_ = d->next_index(); |
| } |
| |
| void ReadFill(Deserializer* d) { |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| RawCode* code = reinterpret_cast<RawCode*>(d->Ref(id)); |
| Deserializer::InitializeHeader(code, kCodeCid, Code::InstanceSize(0)); |
| |
| RawInstructions* instr = d->ReadInstructions(); |
| |
| code->ptr()->entry_point_ = Instructions::EntryPoint(instr); |
| code->ptr()->monomorphic_entry_point_ = |
| Instructions::MonomorphicEntryPoint(instr); |
| code->ptr()->unchecked_entry_point_ = |
| Instructions::UncheckedEntryPoint(instr); |
| code->ptr()->monomorphic_unchecked_entry_point_ = |
| Instructions::MonomorphicUncheckedEntryPoint(instr); |
| NOT_IN_PRECOMPILED(code->ptr()->active_instructions_ = instr); |
| code->ptr()->instructions_ = instr; |
| |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| if (d->kind() == Snapshot::kFullJIT) { |
| RawInstructions* instr = d->ReadInstructions(); |
| code->ptr()->active_instructions_ = instr; |
| code->ptr()->entry_point_ = Instructions::EntryPoint(instr); |
| code->ptr()->monomorphic_entry_point_ = |
| Instructions::MonomorphicEntryPoint(instr); |
| code->ptr()->unchecked_entry_point_ = |
| Instructions::UncheckedEntryPoint(instr); |
| } |
| #endif // !DART_PRECOMPILED_RUNTIME |
| |
| code->ptr()->object_pool_ = |
| reinterpret_cast<RawObjectPool*>(d->ReadRef()); |
| code->ptr()->owner_ = d->ReadRef(); |
| code->ptr()->exception_handlers_ = |
| reinterpret_cast<RawExceptionHandlers*>(d->ReadRef()); |
| code->ptr()->pc_descriptors_ = |
| reinterpret_cast<RawPcDescriptors*>(d->ReadRef()); |
| #if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER) |
| code->ptr()->catch_entry_.catch_entry_moves_maps_ = |
| reinterpret_cast<RawTypedData*>(d->ReadRef()); |
| #else |
| code->ptr()->catch_entry_.variables_ = |
| reinterpret_cast<RawSmi*>(d->ReadRef()); |
| #endif |
| code->ptr()->stackmaps_ = reinterpret_cast<RawArray*>(d->ReadRef()); |
| code->ptr()->inlined_id_to_function_ = |
| reinterpret_cast<RawArray*>(d->ReadRef()); |
| code->ptr()->code_source_map_ = |
| reinterpret_cast<RawCodeSourceMap*>(d->ReadRef()); |
| |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| if (d->kind() == Snapshot::kFullJIT) { |
| code->ptr()->deopt_info_array_ = |
| reinterpret_cast<RawArray*>(d->ReadRef()); |
| code->ptr()->static_calls_target_table_ = |
| reinterpret_cast<RawArray*>(d->ReadRef()); |
| } |
| #endif // !DART_PRECOMPILED_RUNTIME |
| |
| #if !defined(PRODUCT) |
| code->ptr()->await_token_positions_ = |
| reinterpret_cast<RawArray*>(d->ReadRef()); |
| code->ptr()->return_address_metadata_ = d->ReadRef(); |
| code->ptr()->var_descriptors_ = LocalVarDescriptors::null(); |
| code->ptr()->comments_ = Array::null(); |
| code->ptr()->compile_timestamp_ = 0; |
| #endif |
| |
| code->ptr()->state_bits_ = d->Read<int32_t>(); |
| } |
| } |
| }; |
| |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| class BytecodeSerializationCluster : public SerializationCluster { |
| public: |
| BytecodeSerializationCluster() : SerializationCluster("Bytecode") {} |
| virtual ~BytecodeSerializationCluster() {} |
| |
| void Trace(Serializer* s, RawObject* object) { |
| RawBytecode* bytecode = Bytecode::RawCast(object); |
| objects_.Add(bytecode); |
| PushFromTo(bytecode); |
| } |
| |
| void WriteAlloc(Serializer* s) { |
| s->WriteCid(kBytecodeCid); |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| RawBytecode* bytecode = objects_[i]; |
| s->AssignRef(bytecode); |
| } |
| } |
| |
| void WriteFill(Serializer* s) { |
| ASSERT(s->kind() == Snapshot::kFullJIT); |
| intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| RawBytecode* bytecode = objects_[i]; |
| s->Write<int32_t>(bytecode->ptr()->instructions_size_); |
| WriteFromTo(bytecode); |
| s->Write<int32_t>(bytecode->ptr()->instructions_binary_offset_); |
| s->Write<int32_t>(bytecode->ptr()->source_positions_binary_offset_); |
| } |
| } |
| |
| private: |
| GrowableArray<RawBytecode*> objects_; |
| }; |
| |
| class BytecodeDeserializationCluster : public DeserializationCluster { |
| public: |
| BytecodeDeserializationCluster() {} |
| virtual ~BytecodeDeserializationCluster() {} |
| |
| void ReadAlloc(Deserializer* d) { |
| start_index_ = d->next_index(); |
| PageSpace* old_space = d->heap()->old_space(); |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| d->AssignRef(AllocateUninitialized(old_space, Bytecode::InstanceSize())); |
| } |
| stop_index_ = d->next_index(); |
| } |
| |
| void ReadFill(Deserializer* d) { |
| ASSERT(d->kind() == Snapshot::kFullJIT); |
| |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| RawBytecode* bytecode = reinterpret_cast<RawBytecode*>(d->Ref(id)); |
| Deserializer::InitializeHeader(bytecode, kBytecodeCid, |
| Bytecode::InstanceSize()); |
| bytecode->ptr()->instructions_ = 0; |
| bytecode->ptr()->instructions_size_ = d->Read<int32_t>(); |
| ReadFromTo(bytecode); |
| bytecode->ptr()->instructions_binary_offset_ = d->Read<int32_t>(); |
| bytecode->ptr()->source_positions_binary_offset_ = d->Read<int32_t>(); |
| } |
| } |
| |
| void PostLoad(const Array& refs, Snapshot::Kind kind, Zone* zone) { |
| Bytecode& bytecode = Bytecode::Handle(zone); |
| ExternalTypedData& binary = ExternalTypedData::Handle(zone); |
| |
| for (intptr_t i = start_index_; i < stop_index_; i++) { |
| bytecode ^= refs.At(i); |
| binary = bytecode.GetBinary(zone); |
| bytecode.set_instructions(reinterpret_cast<uword>( |
| binary.DataAddr(bytecode.instructions_binary_offset()))); |
| } |
| } |
| }; |
| |
| class ObjectPoolSerializationCluster : public SerializationCluster { |
| public: |
| ObjectPoolSerializationCluster() : SerializationCluster("ObjectPool") {} |
| ~ObjectPoolSerializationCluster() {} |
| |
| void Trace(Serializer* s, RawObject* object) { |
| RawObjectPool* pool = ObjectPool::RawCast(object); |
| objects_.Add(pool); |
| |
| intptr_t length = pool->ptr()->length_; |
| uint8_t* entry_bits = pool->ptr()->entry_bits(); |
| for (intptr_t i = 0; i < length; i++) { |
| auto entry_type = ObjectPool::TypeBits::decode(entry_bits[i]); |
| if ((entry_type == ObjectPool::EntryType::kTaggedObject) || |
| (entry_type == ObjectPool::EntryType::kNativeEntryData)) { |
| s->Push(pool->ptr()->data()[i].raw_obj_); |
| } |
| } |
| } |
| |
| void WriteAlloc(Serializer* s) { |
| s->WriteCid(kObjectPoolCid); |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| RawObjectPool* pool = objects_[i]; |
| s->AssignRef(pool); |
| AutoTraceObject(pool); |
| intptr_t length = pool->ptr()->length_; |
| s->WriteUnsigned(length); |
| } |
| } |
| |
| void WriteFill(Serializer* s) { |
| intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| RawObjectPool* pool = objects_[i]; |
| AutoTraceObject(pool); |
| intptr_t length = pool->ptr()->length_; |
| s->WriteUnsigned(length); |
| uint8_t* entry_bits = pool->ptr()->entry_bits(); |
| for (intptr_t j = 0; j < length; j++) { |
| s->Write<uint8_t>(entry_bits[j]); |
| RawObjectPool::Entry& entry = pool->ptr()->data()[j]; |
| switch (ObjectPool::TypeBits::decode(entry_bits[j])) { |
| case ObjectPool::EntryType::kTaggedObject: { |
| #if !defined(TARGET_ARCH_DBC) |
| if ((entry.raw_obj_ == StubCode::CallNoScopeNative().raw()) || |
| (entry.raw_obj_ == StubCode::CallAutoScopeNative().raw())) { |
| // Natives can run while precompiling, becoming linked and |
| // switching their stub. Reset to the initial stub used for |
| // lazy-linking. |
| s->WriteElementRef(StubCode::CallBootstrapNative().raw(), j); |
| break; |
| } |
| #endif |
| s->WriteElementRef(entry.raw_obj_, j); |
| break; |
| } |
| case ObjectPool::EntryType::kImmediate: { |
| s->Write<intptr_t>(entry.raw_value_); |
| break; |
| } |
| case ObjectPool::EntryType::kNativeEntryData: { |
| RawObject* raw = entry.raw_obj_; |
| RawTypedData* raw_data = reinterpret_cast<RawTypedData*>(raw); |
| // kNativeEntryData object pool entries are for linking natives for |
| // the interpreter. Before writing these entries into the snapshot, |
| // we need to unlink them by nulling out the 'trampoline' and |
| // 'native_function' fields. |
| NativeEntryData::Payload* payload = |
| NativeEntryData::FromTypedArray(raw_data); |
| if (payload->kind == MethodRecognizer::kUnknown) { |
| payload->trampoline = NULL; |
| payload->native_function = NULL; |
| } |
| s->WriteElementRef(raw, j); |
| break; |
| } |
| case ObjectPool::EntryType::kNativeFunction: |
| case ObjectPool::EntryType::kNativeFunctionWrapper: { |
| // Write nothing. Will initialize with the lazy link entry. |
| break; |
| } |
| default: |
| UNREACHABLE(); |
| } |
| } |
| } |
| } |
| |
| private: |
| GrowableArray<RawObjectPool*> objects_; |
| }; |
| #endif // !DART_PRECOMPILED_RUNTIME |
| |
| class ObjectPoolDeserializationCluster : public DeserializationCluster { |
| public: |
| ObjectPoolDeserializationCluster() {} |
| ~ObjectPoolDeserializationCluster() {} |
| |
| void ReadAlloc(Deserializer* d) { |
| start_index_ = d->next_index(); |
| PageSpace* old_space = d->heap()->old_space(); |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| intptr_t length = d->ReadUnsigned(); |
| d->AssignRef( |
| AllocateUninitialized(old_space, ObjectPool::InstanceSize(length))); |
| } |
| stop_index_ = d->next_index(); |
| } |
| |
| void ReadFill(Deserializer* d) { |
| for (intptr_t id = start_index_; id < stop_index_; id += 1) { |
| intptr_t length = d->ReadUnsigned(); |
| RawObjectPool* pool = reinterpret_cast<RawObjectPool*>(d->Ref(id + 0)); |
| Deserializer::InitializeHeader(pool, kObjectPoolCid, |
| ObjectPool::InstanceSize(length)); |
| pool->ptr()->length_ = length; |
| for (intptr_t j = 0; j < length; j++) { |
| const uint8_t entry_bits = d->Read<uint8_t>(); |
| pool->ptr()->entry_bits()[j] = entry_bits; |
| RawObjectPool::Entry& entry = pool->ptr()->data()[j]; |
| switch (ObjectPool::TypeBits::decode(entry_bits)) { |
| case ObjectPool::EntryType::kNativeEntryData: |
| case ObjectPool::EntryType::kTaggedObject: |
| entry.raw_obj_ = d->ReadRef(); |
| break; |
| case ObjectPool::EntryType::kImmediate: |
| entry.raw_value_ = d->Read<intptr_t>(); |
| break; |
| case ObjectPool::EntryType::kNativeFunction: { |
| // Read nothing. Initialize with the lazy link entry. |
| uword new_entry = NativeEntry::LinkNativeCallEntry(); |
| entry.raw_value_ = static_cast<intptr_t>(new_entry); |
| break; |
| } |
| #if defined(TARGET_ARCH_DBC) |
| case ObjectPool::EntryType::kNativeFunctionWrapper: { |
| // Read nothing. Initialize with the lazy link entry. |
| uword new_entry = NativeEntry::BootstrapNativeCallWrapperEntry(); |
| entry.raw_value_ = static_cast<intptr_t>(new_entry); |
| break; |
| } |
| #endif |
| default: |
| UNREACHABLE(); |
| } |
| } |
| } |
| } |
| }; |
| |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| // PcDescriptor, StackMap, OneByteString, TwoByteString |
| class RODataSerializationCluster : public SerializationCluster { |
| public: |
| RODataSerializationCluster(const char* name, intptr_t cid) |
| : SerializationCluster(name), cid_(cid) {} |
| ~RODataSerializationCluster() {} |
| |
| void Trace(Serializer* s, RawObject* object) { |
| // A string's hash must already be computed when we write it because it |
| // will be loaded into read-only memory. Extra bytes due to allocation |
| // rounding need to be deterministically set for reliable deduplication in |
| // shared images. |
| if (object->InVMIsolateHeap() || |
| s->isolate()->heap()->old_space()->IsObjectFromImagePages(object)) { |
| // This object is already read-only. |
| } else { |
| Object::FinalizeReadOnlyObject(object); |
| } |
| |
| uint32_t ignored; |
| if (s->GetSharedDataOffset(object, &ignored)) { |
| shared_objects_.Add(object); |
| } else { |
| objects_.Add(object); |
| } |
| } |
| |
| void WriteAlloc(Serializer* s) { |
| s->WriteCid(cid_); |
| intptr_t count = shared_objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| RawObject* object = shared_objects_[i]; |
| s->AssignRef(object); |
| AutoTraceObject(object); |
| uint32_t offset; |
| if (!s->GetSharedDataOffset(object, &offset)) { |
| UNREACHABLE(); |
| } |
| s->WriteUnsigned(offset); |
| } |
| |
| count = objects_.length(); |
| s->WriteUnsigned(count); |
| uint32_t running_offset = 0; |
| for (intptr_t i = 0; i < count; i++) { |
| RawObject* object = objects_[i]; |
| s->AssignRef(object); |
| if (cid_ == kOneByteStringCid || cid_ == kTwoByteStringCid) { |
| s->TraceStartWritingObject(name(), object, String::RawCast(object)); |
| } else { |
| s->TraceStartWritingObject(name(), object, nullptr); |
| } |
| uint32_t offset = s->GetDataOffset(object); |
| s->TraceDataOffset(offset); |
| ASSERT(Utils::IsAligned(offset, kObjectAlignment)); |
| ASSERT(offset > running_offset); |
| s->WriteUnsigned((offset - running_offset) >> kObjectAlignmentLog2); |
| running_offset = offset; |
| s->TraceEndWritingObject(); |
| } |
| } |
| |
| void WriteFill(Serializer* s) { |
| // No-op. |
| } |
| |
| private: |
| const intptr_t cid_; |
| GrowableArray<RawObject*> objects_; |
| GrowableArray<RawObject*> shared_objects_; |
| }; |
| #endif // !DART_PRECOMPILED_RUNTIME |
| |
| class RODataDeserializationCluster : public DeserializationCluster { |
| public: |
| RODataDeserializationCluster() {} |
| ~RODataDeserializationCluster() {} |
| |
| void ReadAlloc(Deserializer* d) { |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| uint32_t offset = d->ReadUnsigned(); |
| d->AssignRef(d->GetSharedObjectAt(offset)); |
| } |
| |
| count = d->ReadUnsigned(); |
| uint32_t running_offset = 0; |
| for (intptr_t i = 0; i < count; i++) { |
| running_offset += d->ReadUnsigned() << kObjectAlignmentLog2; |
| d->AssignRef(d->GetObjectAt(running_offset)); |
| } |
| } |
| |
| void ReadFill(Deserializer* d) { |
| // No-op. |
| } |
| }; |
| |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| class ExceptionHandlersSerializationCluster : public SerializationCluster { |
| public: |
| ExceptionHandlersSerializationCluster() |
| : SerializationCluster("ExceptionHandlers") {} |
| ~ExceptionHandlersSerializationCluster() {} |
| |
| void Trace(Serializer* s, RawObject* object) { |
| RawExceptionHandlers* handlers = ExceptionHandlers::RawCast(object); |
| objects_.Add(handlers); |
| |
| s->Push(handlers->ptr()->handled_types_data_); |
| } |
| |
| void WriteAlloc(Serializer* s) { |
| s->WriteCid(kExceptionHandlersCid); |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| RawExceptionHandlers* handlers = objects_[i]; |
| s->AssignRef(handlers); |
| AutoTraceObject(handlers); |
| intptr_t length = handlers->ptr()->num_entries_; |
| s->WriteUnsigned(length); |
| } |
| } |
| |
| void WriteFill(Serializer* s) { |
| intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| RawExceptionHandlers* handlers = objects_[i]; |
| AutoTraceObject(handlers); |
| intptr_t length = handlers->ptr()->num_entries_; |
| s->WriteUnsigned(length); |
| WriteField(handlers, handled_types_data_); |
| for (intptr_t j = 0; j < length; j++) { |
| const ExceptionHandlerInfo& info = handlers->ptr()->data()[j]; |
| s->Write<uint32_t>(info.handler_pc_offset); |
| s->Write<int16_t>(info.outer_try_index); |
| s->Write<int8_t>(info.needs_stacktrace); |
| s->Write<int8_t>(info.has_catch_all); |
| s->Write<int8_t>(info.is_generated); |
| } |
| } |
| } |
| |
| private: |
| GrowableArray<RawExceptionHandlers*> objects_; |
| }; |
| #endif // !DART_PRECOMPILED_RUNTIME |
| |
| class ExceptionHandlersDeserializationCluster : public DeserializationCluster { |
| public: |
| ExceptionHandlersDeserializationCluster() {} |
| ~ExceptionHandlersDeserializationCluster() {} |
| |
| void ReadAlloc(Deserializer* d) { |
| start_index_ = d->next_index(); |
| PageSpace* old_space = d->heap()->old_space(); |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| intptr_t length = d->ReadUnsigned(); |
| d->AssignRef(AllocateUninitialized( |
| old_space, ExceptionHandlers::InstanceSize(length))); |
| } |
| stop_index_ = d->next_index(); |
| } |
| |
| void ReadFill(Deserializer* d) { |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| RawExceptionHandlers* handlers = |
| reinterpret_cast<RawExceptionHandlers*>(d->Ref(id)); |
| intptr_t length = d->ReadUnsigned(); |
| Deserializer::InitializeHeader(handlers, kExceptionHandlersCid, |
| ExceptionHandlers::InstanceSize(length)); |
| handlers->ptr()->num_entries_ = length; |
| handlers->ptr()->handled_types_data_ = |
| reinterpret_cast<RawArray*>(d->ReadRef()); |
| for (intptr_t j = 0; j < length; j++) { |
| ExceptionHandlerInfo& info = handlers->ptr()->data()[j]; |
| info.handler_pc_offset = d->Read<uint32_t>(); |
| info.outer_try_index = d->Read<int16_t>(); |
| info.needs_stacktrace = d->Read<int8_t>(); |
| info.has_catch_all = d->Read<int8_t>(); |
| info.is_generated = d->Read<int8_t>(); |
| } |
| } |
| } |
| }; |
| |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| class ContextSerializationCluster : public SerializationCluster { |
| public: |
| ContextSerializationCluster() : SerializationCluster("Context") {} |
| ~ContextSerializationCluster() {} |
| |
| void Trace(Serializer* s, RawObject* object) { |
| RawContext* context = Context::RawCast(object); |
| objects_.Add(context); |
| |
| s->Push(context->ptr()->parent_); |
| intptr_t length = context->ptr()->num_variables_; |
| for (intptr_t i = 0; i < length; i++) { |
| s->Push(context->ptr()->data()[i]); |
| } |
| } |
| |
| void WriteAlloc(Serializer* s) { |
| s->WriteCid(kContextCid); |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| RawContext* context = objects_[i]; |
| s->AssignRef(context); |
| AutoTraceObject(context); |
| intptr_t length = context->ptr()->num_variables_; |
| s->WriteUnsigned(length); |
| } |
| } |
| |
| void WriteFill(Serializer* s) { |
| intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| RawContext* context = objects_[i]; |
| AutoTraceObject(context); |
| intptr_t length = context->ptr()->num_variables_; |
| s->WriteUnsigned(length); |
| WriteField(context, parent_); |
| for (intptr_t j = 0; j < length; j++) { |
| s->WriteElementRef(context->ptr()->data()[j], j); |
| } |
| } |
| } |
| |
| private: |
| GrowableArray<RawContext*> objects_; |
| }; |
| #endif // !DART_PRECOMPILED_RUNTIME |
| |
| class ContextDeserializationCluster : public DeserializationCluster { |
| public: |
| ContextDeserializationCluster() {} |
| ~ContextDeserializationCluster() {} |
| |
| void ReadAlloc(Deserializer* d) { |
| start_index_ = d->next_index(); |
| PageSpace* old_space = d->heap()->old_space(); |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| intptr_t length = d->ReadUnsigned(); |
| d->AssignRef( |
| AllocateUninitialized(old_space, Context::InstanceSize(length))); |
| } |
| stop_index_ = d->next_index(); |
| } |
| |
| void ReadFill(Deserializer* d) { |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| RawContext* context = reinterpret_cast<RawContext*>(d->Ref(id)); |
| intptr_t length = d->ReadUnsigned(); |
| Deserializer::InitializeHeader(context, kContextCid, |
| Context::InstanceSize(length)); |
| context->ptr()->num_variables_ = length; |
| context->ptr()->parent_ = reinterpret_cast<RawContext*>(d->ReadRef()); |
| for (intptr_t j = 0; j < length; j++) { |
| context->ptr()->data()[j] = d->ReadRef(); |
| } |
| } |
| } |
| }; |
| |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| class ContextScopeSerializationCluster : public SerializationCluster { |
| public: |
| ContextScopeSerializationCluster() : SerializationCluster("ContextScope") {} |
| ~ContextScopeSerializationCluster() {} |
| |
| void Trace(Serializer* s, RawObject* object) { |
| RawContextScope* scope = ContextScope::RawCast(object); |
| objects_.Add(scope); |
| |
| intptr_t length = scope->ptr()->num_variables_; |
| PushFromTo(scope, length); |
| } |
| |
| void WriteAlloc(Serializer* s) { |
| s->WriteCid(kContextScopeCid); |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| RawContextScope* scope = objects_[i]; |
| s->AssignRef(scope); |
| AutoTraceObject(scope); |
| intptr_t length = scope->ptr()->num_variables_; |
| s->WriteUnsigned(length); |
| } |
| } |
| |
| void WriteFill(Serializer* s) { |
| intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| RawContextScope* scope = objects_[i]; |
| AutoTraceObject(scope); |
| intptr_t length = scope->ptr()->num_variables_; |
| s->WriteUnsigned(length); |
| s->Write<bool>(scope->ptr()->is_implicit_); |
| WriteFromTo(scope, length); |
| } |
| } |
| |
| private: |
| GrowableArray<RawContextScope*> objects_; |
| }; |
| #endif // !DART_PRECOMPILED_RUNTIME |
| |
| class ContextScopeDeserializationCluster : public DeserializationCluster { |
| public: |
| ContextScopeDeserializationCluster() {} |
| ~ContextScopeDeserializationCluster() {} |
| |
| void ReadAlloc(Deserializer* d) { |
| start_index_ = d->next_index(); |
| PageSpace* old_space = d->heap()->old_space(); |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| intptr_t length = d->ReadUnsigned(); |
| d->AssignRef( |
| AllocateUninitialized(old_space, ContextScope::InstanceSize(length))); |
| } |
| stop_index_ = d->next_index(); |
| } |
| |
| void ReadFill(Deserializer* d) { |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| RawContextScope* scope = reinterpret_cast<RawContextScope*>(d->Ref(id)); |
| intptr_t length = d->ReadUnsigned(); |
| Deserializer::InitializeHeader(scope, kContextScopeCid, |
| ContextScope::InstanceSize(length)); |
| scope->ptr()->num_variables_ = length; |
| scope->ptr()->is_implicit_ = d->Read<bool>(); |
| ReadFromTo(scope, length); |
| } |
| } |
| }; |
| |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| class UnlinkedCallSerializationCluster : public SerializationCluster { |
| public: |
| UnlinkedCallSerializationCluster() : SerializationCluster("UnlinkedCall") {} |
| ~UnlinkedCallSerializationCluster() {} |
| |
| void Trace(Serializer* s, RawObject* object) { |
| RawUnlinkedCall* unlinked = UnlinkedCall::RawCast(object); |
| objects_.Add(unlinked); |
| PushFromTo(unlinked); |
| } |
| |
| void WriteAlloc(Serializer* s) { |
| s->WriteCid(kUnlinkedCallCid); |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| RawUnlinkedCall* unlinked = objects_[i]; |
| s->AssignRef(unlinked); |
| } |
| } |
| |
| void WriteFill(Serializer* s) { |
| intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| RawUnlinkedCall* unlinked = objects_[i]; |
| AutoTraceObjectName(unlinked, unlinked->ptr()->target_name_); |
| WriteFromTo(unlinked); |
| } |
| } |
| |
| private: |
| GrowableArray<RawUnlinkedCall*> objects_; |
| }; |
| #endif // !DART_PRECOMPILED_RUNTIME |
| |
| class UnlinkedCallDeserializationCluster : public DeserializationCluster { |
| public: |
| UnlinkedCallDeserializationCluster() {} |
| ~UnlinkedCallDeserializationCluster() {} |
| |
| void ReadAlloc(Deserializer* d) { |
| start_index_ = d->next_index(); |
| PageSpace* old_space = d->heap()->old_space(); |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| d->AssignRef( |
| AllocateUninitialized(old_space, UnlinkedCall::InstanceSize())); |
| } |
| stop_index_ = d->next_index(); |
| } |
| |
| void ReadFill(Deserializer* d) { |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| RawUnlinkedCall* unlinked = |
| reinterpret_cast<RawUnlinkedCall*>(d->Ref(id)); |
| Deserializer::InitializeHeader(unlinked, kUnlinkedCallCid, |
| UnlinkedCall::InstanceSize()); |
| ReadFromTo(unlinked); |
| } |
| } |
| }; |
| |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| class ICDataSerializationCluster : public SerializationCluster { |
| public: |
| ICDataSerializationCluster() : SerializationCluster("ICData") {} |
| ~ICDataSerializationCluster() {} |
| |
| void Trace(Serializer* s, RawObject* object) { |
| RawICData* ic = ICData::RawCast(object); |
| objects_.Add(ic); |
| PushFromTo(ic); |
| } |
| |
| void WriteAlloc(Serializer* s) { |
| s->WriteCid(kICDataCid); |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| RawICData* ic = objects_[i]; |
| s->AssignRef(ic); |
| } |
| } |
| |
| void WriteFill(Serializer* s) { |
| Snapshot::Kind kind = s->kind(); |
| intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| RawICData* ic = objects_[i]; |
| AutoTraceObjectName(ic, ic->ptr()->target_name_); |
| WriteFromTo(ic); |
| if (kind != Snapshot::kFullAOT) { |
| NOT_IN_PRECOMPILED(s->Write<int32_t>(ic->ptr()->deopt_id_)); |
| } |
| s->Write<uint32_t>(ic->ptr()->state_bits_); |
| } |
| } |
| |
| private: |
| GrowableArray<RawICData*> objects_; |
| }; |
| #endif // !DART_PRECOMPILED_RUNTIME |
| |
| class ICDataDeserializationCluster : public DeserializationCluster { |
| public: |
| ICDataDeserializationCluster() {} |
| ~ICDataDeserializationCluster() {} |
| |
| void ReadAlloc(Deserializer* d) { |
| start_index_ = d->next_index(); |
| PageSpace* old_space = d->heap()->old_space(); |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| d->AssignRef(AllocateUninitialized(old_space, ICData::InstanceSize())); |
| } |
| stop_index_ = d->next_index(); |
| } |
| |
| void ReadFill(Deserializer* d) { |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| RawICData* ic = reinterpret_cast<RawICData*>(d->Ref(id)); |
| Deserializer::InitializeHeader(ic, kICDataCid, ICData::InstanceSize()); |
| ReadFromTo(ic); |
| NOT_IN_PRECOMPILED(ic->ptr()->deopt_id_ = d->Read<int32_t>()); |
| ic->ptr()->state_bits_ = d->Read<int32_t>(); |
| } |
| } |
| }; |
| |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| class MegamorphicCacheSerializationCluster : public SerializationCluster { |
| public: |
| MegamorphicCacheSerializationCluster() |
| : SerializationCluster("MegamorphicCache") {} |
| ~MegamorphicCacheSerializationCluster() {} |
| |
| void Trace(Serializer* s, RawObject* object) { |
| RawMegamorphicCache* cache = MegamorphicCache::RawCast(object); |
| objects_.Add(cache); |
| PushFromTo(cache); |
| } |
| |
| void WriteAlloc(Serializer* s) { |
| s->WriteCid(kMegamorphicCacheCid); |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| RawMegamorphicCache* cache = objects_[i]; |
| s->AssignRef(cache); |
| } |
| } |
| |
| void WriteFill(Serializer* s) { |
| intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| RawMegamorphicCache* cache = objects_[i]; |
| AutoTraceObjectName(cache, cache->ptr()->target_name_); |
| WriteFromTo(cache); |
| s->Write<int32_t>(cache->ptr()->filled_entry_count_); |
| } |
| } |
| |
| private: |
| GrowableArray<RawMegamorphicCache*> objects_; |
| }; |
| #endif // !DART_PRECOMPILED_RUNTIME |
| |
| class MegamorphicCacheDeserializationCluster : public DeserializationCluster { |
| public: |
| MegamorphicCacheDeserializationCluster() {} |
| ~MegamorphicCacheDeserializationCluster() {} |
| |
| void ReadAlloc(Deserializer* d) { |
| start_index_ = d->next_index(); |
| PageSpace* old_space = d->heap()->old_space(); |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| d->AssignRef( |
| AllocateUninitialized(old_space, MegamorphicCache::InstanceSize())); |
| } |
| stop_index_ = d->next_index(); |
| } |
| |
| void ReadFill(Deserializer* d) { |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| RawMegamorphicCache* cache = |
| reinterpret_cast<RawMegamorphicCache*>(d->Ref(id)); |
| Deserializer::InitializeHeader(cache, kMegamorphicCacheCid, |
| MegamorphicCache::InstanceSize()); |
| ReadFromTo(cache); |
| cache->ptr()->filled_entry_count_ = d->Read<int32_t>(); |
| } |
| } |
| |
| void PostLoad(const Array& refs, Snapshot::Kind kind, Zone* zone) { |
| #if defined(DART_PRECOMPILED_RUNTIME) |
| if (FLAG_use_bare_instructions) { |
| // By default, every megamorphic call site will load the target |
| // [Function] from the hash table and call indirectly via loading the |
| // entrypoint from the function. |
| // |
| // In --use-bare-instruction we reduce the extra indirection via the |
| // [Function] object by storing the entry point directly into the hashmap. |
| // |
| // Currently our AOT compiler will emit megamorphic calls in certain |
| // situations (namely in slow-path code of CheckedSmi* instructions). |
| // |
| // TODO(compiler-team): Change the CheckedSmi* slow path code to use |
| // normal switchable calls instead of megamorphic calls. (This is also a |
| // memory balance beause [MegamorphicCache]s are per-selector while |
| // [ICData] are per-callsite.) |
| auto& cache = MegamorphicCache::Handle(zone); |
| for (intptr_t i = start_index_; i < stop_index_; ++i) { |
| cache ^= refs.At(i); |
| cache.SwitchToBareInstructions(); |
| } |
| } |
| #endif // defined(DART_PRECOMPILED_RUNTIME) |
| } |
| }; |
| |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| class SubtypeTestCacheSerializationCluster : public SerializationCluster { |
| public: |
| SubtypeTestCacheSerializationCluster() |
| : SerializationCluster("SubtypeTestCache") {} |
| ~SubtypeTestCacheSerializationCluster() {} |
| |
| void Trace(Serializer* s, RawObject* object) { |
| RawSubtypeTestCache* cache = SubtypeTestCache::RawCast(object); |
| objects_.Add(cache); |
| s->Push(cache->ptr()->cache_); |
| } |
| |
| void WriteAlloc(Serializer* s) { |
| s->WriteCid(kSubtypeTestCacheCid); |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| RawSubtypeTestCache* cache = objects_[i]; |
| s->AssignRef(cache); |
| } |
| } |
| |
| void WriteFill(Serializer* s) { |
| intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| RawSubtypeTestCache* cache = objects_[i]; |
| AutoTraceObject(cache); |
| WriteField(cache, cache_); |
| } |
| } |
| |
| private: |
| GrowableArray<RawSubtypeTestCache*> objects_; |
| }; |
| #endif // !DART_PRECOMPILED_RUNTIME |
| |
| class SubtypeTestCacheDeserializationCluster : public DeserializationCluster { |
| public: |
| SubtypeTestCacheDeserializationCluster() {} |
| ~SubtypeTestCacheDeserializationCluster() {} |
| |
| void ReadAlloc(Deserializer* d) { |
| start_index_ = d->next_index(); |
| PageSpace* old_space = d->heap()->old_space(); |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| d->AssignRef( |
| AllocateUninitialized(old_space, SubtypeTestCache::InstanceSize())); |
| } |
| stop_index_ = d->next_index(); |
| } |
| |
| void ReadFill(Deserializer* d) { |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| RawSubtypeTestCache* cache = |
| reinterpret_cast<RawSubtypeTestCache*>(d->Ref(id)); |
| Deserializer::InitializeHeader(cache, kSubtypeTestCacheCid, |
| SubtypeTestCache::InstanceSize()); |
| cache->ptr()->cache_ = reinterpret_cast<RawArray*>(d->ReadRef()); |
| } |
| } |
| }; |
| |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| class LanguageErrorSerializationCluster : public SerializationCluster { |
| public: |
| LanguageErrorSerializationCluster() : SerializationCluster("LanguageError") {} |
| ~LanguageErrorSerializationCluster() {} |
| |
| void Trace(Serializer* s, RawObject* object) { |
| RawLanguageError* error = LanguageError::RawCast(object); |
| objects_.Add(error); |
| PushFromTo(error); |
| } |
| |
| void WriteAlloc(Serializer* s) { |
| s->WriteCid(kLanguageErrorCid); |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| RawLanguageError* error = objects_[i]; |
| s->AssignRef(error); |
| } |
| } |
| |
| void WriteFill(Serializer* s) { |
| intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| RawLanguageError* error = objects_[i]; |
| AutoTraceObject(error); |
| WriteFromTo(error); |
| s->WriteTokenPosition(error->ptr()->token_pos_); |
| s->Write<bool>(error->ptr()->report_after_token_); |
| s->Write<int8_t>(error->ptr()->kind_); |
| } |
| } |
| |
| private: |
| GrowableArray<RawLanguageError*> objects_; |
| }; |
| #endif // !DART_PRECOMPILED_RUNTIME |
| |
| class LanguageErrorDeserializationCluster : public DeserializationCluster { |
| public: |
| LanguageErrorDeserializationCluster() {} |
| ~LanguageErrorDeserializationCluster() {} |
| |
| void ReadAlloc(Deserializer* d) { |
| start_index_ = d->next_index(); |
| PageSpace* old_space = d->heap()->old_space(); |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| d->AssignRef( |
| AllocateUninitialized(old_space, LanguageError::InstanceSize())); |
| } |
| stop_index_ = d->next_index(); |
| } |
| |
| void ReadFill(Deserializer* d) { |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| RawLanguageError* error = reinterpret_cast<RawLanguageError*>(d->Ref(id)); |
| Deserializer::InitializeHeader(error, kLanguageErrorCid, |
| LanguageError::InstanceSize()); |
| ReadFromTo(error); |
| error->ptr()->token_pos_ = d->ReadTokenPosition(); |
| error->ptr()->report_after_token_ = d->Read<bool>(); |
| error->ptr()->kind_ = d->Read<int8_t>(); |
| } |
| } |
| }; |
| |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| class UnhandledExceptionSerializationCluster : public SerializationCluster { |
| public: |
| UnhandledExceptionSerializationCluster() |
| : SerializationCluster("UnhandledException") {} |
| ~UnhandledExceptionSerializationCluster() {} |
| |
| void Trace(Serializer* s, RawObject* object) { |
| RawUnhandledException* exception = UnhandledException::RawCast(object); |
| objects_.Add(exception); |
| PushFromTo(exception); |
| } |
| |
| void WriteAlloc(Serializer* s) { |
| s->WriteCid(kUnhandledExceptionCid); |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| RawUnhandledException* exception = objects_[i]; |
| s->AssignRef(exception); |
| } |
| } |
| |
| void WriteFill(Serializer* s) { |
| intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| RawUnhandledException* exception = objects_[i]; |
| AutoTraceObject(exception); |
| WriteFromTo(exception); |
| } |
| } |
| |
| private: |
| GrowableArray<RawUnhandledException*> objects_; |
| }; |
| #endif // !DART_PRECOMPILED_RUNTIME |
| |
| class UnhandledExceptionDeserializationCluster : public DeserializationCluster { |
| public: |
| UnhandledExceptionDeserializationCluster() {} |
| ~UnhandledExceptionDeserializationCluster() {} |
| |
| void ReadAlloc(Deserializer* d) { |
| start_index_ = d->next_index(); |
| PageSpace* old_space = d->heap()->old_space(); |
| intptr_t count = d->ReadUnsigned(); |
| for (intptr_t i = 0; i < count; i++) { |
| d->AssignRef( |
| AllocateUninitialized(old_space, UnhandledException::InstanceSize())); |
| } |
| stop_index_ = d->next_index(); |
| } |
| |
| void ReadFill(Deserializer* d) { |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| RawUnhandledException* exception = |
| reinterpret_cast<RawUnhandledException*>(d->Ref(id)); |
| Deserializer::InitializeHeader(exception, kUnhandledExceptionCid, |
| UnhandledException::InstanceSize()); |
| ReadFromTo(exception); |
| } |
| } |
| }; |
| |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| class InstanceSerializationCluster : public SerializationCluster { |
| public: |
| explicit InstanceSerializationCluster(intptr_t cid) |
| : SerializationCluster("Instance"), cid_(cid) { |
| RawClass* cls = Isolate::Current()->class_table()->At(cid); |
| next_field_offset_in_words_ = cls->ptr()->next_field_offset_in_words_; |
| instance_size_in_words_ = cls->ptr()->instance_size_in_words_; |
| ASSERT(next_field_offset_in_words_ > 0); |
| ASSERT(instance_size_in_words_ > 0); |
| } |
| ~InstanceSerializationCluster() {} |
| |
| void Trace(Serializer* s, RawObject* object) { |
| RawInstance* instance = Instance::RawCast(object); |
| objects_.Add(instance); |
| |
| intptr_t next_field_offset = next_field_offset_in_words_ << kWordSizeLog2; |
| intptr_t offset = Instance::NextFieldOffset(); |
| while (offset < next_field_offset) { |
| RawObject* raw_obj = *reinterpret_cast<RawObject**>( |
| reinterpret_cast<uword>(instance->ptr()) + offset); |
| s->Push(raw_obj); |
| offset += kWordSize; |
| } |
| } |
| |
| void WriteAlloc(Serializer* s) { |
| s->WriteCid(cid_); |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| |
| s->Write<int32_t>(next_field_offset_in_words_); |
| s->Write<int32_t>(instance_size_in_words_); |
| |
| for (intptr_t i = 0; i < count; i++) { |
| RawInstance* instance = objects_[i]; |
| s->AssignRef(instance); |
| } |
| } |
| |
| void WriteFill(Serializer* s) { |
| intptr_t next_field_offset = next_field_offset_in_words_ << kWordSizeLog2; |
| intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| RawInstance* instance = objects_[i]; |
| AutoTraceObject(instance); |
| s->Write<bool>(instance->IsCanonical()); |
| intptr_t offset = Instance::NextFieldOffset(); |
| while (offset < next_field_offset) { |
| RawObject* raw_obj = *reinterpret_cast<RawObject**>( |
| reinterpret_cast<uword>(instance->ptr()) + offset); |
| s->WriteElementRef(raw_obj, offset); |
| offset += kWordSize; |
| } |
| } |
| } |
| |
| private: |
| const intptr_t cid_; |
| intptr_t next_field_offset_in_words_; |
| intptr_t instance_size_in_words_; |
| GrowableArray<RawInstance*> objects_; |
| }; |
| #endif // !DART_PRECOMPILED_RUNTIME |
| |
| class InstanceDeserializationCluster : public DeserializationCluster { |
| public: |
| explicit InstanceDeserializationCluster(intptr_t cid) : cid_(cid) {} |
| ~InstanceDeserializationCluster() {} |
| |
| void ReadAlloc(Deserializer* d) { |
| start_index_ = d->next_index(); |
| PageSpace* old_space = d->heap()->old_space(); |
| intptr_t count = d->ReadUnsigned(); |
| next_field_offset_in_words_ = d->Read<int32_t>(); |
| instance_size_in_words_ = d->Read<int32_t>(); |
| intptr_t instance_size = |
| Object::RoundedAllocationSize(instance_size_in_words_ * kWordSize); |
| for (intptr_t i = 0; i < count; i++) { |
| d->AssignRef(AllocateUninitialized(old_space, instance_size)); |
| } |
| stop_index_ = d->next_index(); |
| } |
| |
| void ReadFill(Deserializer* d) { |
| intptr_t next_field_offset = next_field_offset_in_words_ << kWordSizeLog2; |
| intptr_t instance_size = |
| Object::RoundedAllocationSize(instance_size_in_words_ * kWordSize); |
| |
| for (intptr_t id = start_index_; id < stop_index_; id++) { |
| RawInstance* instance = reinterpret_cast<RawInstance*>(d->Ref(id)); |
| bool is_canonical = d->Read<bool>(); |
| Deserializer::InitializeHeader(instance, cid_, instance_size, |
| is_canonical); |
| intptr_t offset = Instance::NextFieldOffset(); |
| while (offset < next_field_offset) { |
| RawObject** p = reinterpret_cast<RawObject**>( |
| reinterpret_cast<uword>(instance->ptr()) + offset); |
| *p = d->ReadRef(); |
| offset += kWordSize; |
| } |
| if (offset < instance_size) { |
| RawObject** p = reinterpret_cast<RawObject**>( |
| reinterpret_cast<uword>(instance->ptr()) + offset); |
| *p = Object::null(); |
| offset += kWordSize; |
| } |
| ASSERT(offset == instance_size); |
| } |
| } |
| |
| private: |
| const intptr_t cid_; |
| intptr_t next_field_offset_in_words_; |
| intptr_t instance_size_in_words_; |
| }; |
| |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| class LibraryPrefixSerializationCluster : public SerializationCluster { |
| public: |
| LibraryPrefixSerializationCluster() : SerializationCluster("LibraryPrefix") {} |
| ~LibraryPrefixSerializationCluster() {} |
| |
| void Trace(Serializer* s, RawObject* object) { |
| RawLibraryPrefix* prefix = LibraryPrefix::RawCast(object); |
| objects_.Add(prefix); |
| PushFromTo(prefix); |
| } |
| |
| void WriteAlloc(Serializer* s) { |
| s->WriteCid(kLibraryPrefixCid); |
| intptr_t count = objects_.length(); |
| s->WriteUnsigned(count); |
| for (intptr_t i = 0; i < count; i++) { |
| RawLibraryPrefix* prefix = objects_[i]; |
| s->AssignRef(prefix); |
| } |
| } |
| |
| void WriteFill(Serializer* s) { |
| intptr_t count = objects_.length(); |
| for (intptr_t i = 0; i < count; i++) { |
| RawLibraryPrefix* prefix = objects_[i]; |
| AutoTraceObject(prefix); |
| WriteFromTo(prefix); |
| s->Write<uint16_t>(prefix->ptr()->num_imports_); |
| s->Write<bool>(prefix->ptr()->is_deferred_load_); |
| } |
| } |
| |
| private: |
| GrowableArray<RawLibraryPrefix*> objects_; |
| }; |
| #endif // !DART_PRECOMPILED_RUNTIME |
| |
| class LibraryPrefixDeserializationCluster : public DeserializationCluster { |
| public: |
| LibraryPrefixDeserializationCluster() {} |
| ~LibraryPrefixDeserializationCluster() {} |
| |
| void ReadAlloc(Deserializer* d) { |
| start_index_ = d->next_i
|